ATC version 2.0, date: Aug7

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@10557 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
rjones 2013-08-07 21:29:01 +00:00
parent 6d40d7c25d
commit 0e4d1e6b22
87 changed files with 4663 additions and 30479 deletions

View File

@ -1,47 +0,0 @@
// ATC_Error : a base class for atom-continuum errors
#ifndef ATC_ERROR
#define ATC_ERROR
#include <string>
namespace ATC {
class ATC_Error {
public:
// constructor
ATC_Error(int procID, std::string errorDescription) {
procID_ = procID;
errorDescription_ = errorDescription;
};
//ATC_Error(std::string errorDescription) {
// procID_ = LammpsInterface::instance()->comm_rank();
// errorDescription_ = errorDescription;
//};
// data access
virtual int get_id() {
return procID_;
};
virtual std::string get_error_description() {
return errorDescription_;
};
private:
// id of the processor reporting the error
int procID_;
// string describing the type of error
std::string errorDescription_;
};
}
#endif

View File

@ -1,386 +0,0 @@
#include "ATC_HardyKernel.h"
#include "math.h"
#include <iostream> //for debugging purposes; take this out after I'm done
#include <vector>
#include "ATC_Error.h"
#include "Quadrature.h"
using namespace std;
static const double Pi = 4.0*atan(1.0);
static const double tol = 1.0e-8;
namespace ATC {
//------------------------------------------------------------------------
// constructor
ATC_HardyKernel::ATC_HardyKernel(int nparameters, double* parameters):
lammpsInterface_(LammpsInterface::instance()),
Rc_(0),invRc_(0),nsd_(3)
{
Rc_ = parameters[0];
invRc_ = 1.0/Rc_;
Rc_ = parameters[0];
invRc_ = 1.0/Rc_;
invVol_ = 1.0/(4.0/3.0*Pi*pow(Rc_,3));
set_line_quadrature(line_ngauss,line_xg,line_wg);
// get periodicity and box bounds/lengths
lammpsInterface_->get_box_periodicity(periodicity[0],
periodicity[1],periodicity[2]);
lammpsInterface_->get_box_bounds(box_bounds[0][0],box_bounds[1][0],
box_bounds[0][1],box_bounds[1][1],
box_bounds[0][2],box_bounds[1][2]);
for (int k = 0; k < 3; k++) {
box_length[k] = box_bounds[1][k] - box_bounds[0][k];
}
};
// bond function value via quadrature
double ATC_HardyKernel::bond(DENS_VEC& xa, DENS_VEC&xb, double lam1, double lam2)
{
DENS_VEC xab(nsd_), q(nsd_);
double lamg;
double bhsum=0.0;
xab = xa - xb;
for (int i = 0; i < line_ngauss; i++) {
lamg=0.5*((lam2-lam1)*line_xg[i]+(lam2+lam1));
q = lamg*xab + xb;
double locg_value=this->value(q);
bhsum+=locg_value*line_wg[i];
}
return 0.5*(lam2-lam1)*bhsum;
}
// localization-volume intercepts for bond calculation
// bond intercept values assuming spherical support
void ATC_HardyKernel::bond_intercepts(DENS_VEC& xa,
DENS_VEC& xb, double &lam1, double &lam2)
{
if (nsd_ == 2) {// for cylinders, axis is always z!
const int iaxis = 2;
xa[iaxis] = 0.0;
xb[iaxis] = 0.0;
}
lam1 = lam2 = -1;
double ra_n = invRc_*xa.norm(); // lambda = 1
double rb_n = invRc_*xb.norm(); // lambda = 0
bool a_in = (ra_n <= 1.0);
bool b_in = (rb_n <= 1.0);
if (a_in && b_in) {
lam1 = 0.0;
lam2 = 1.0;
return;
}
DENS_VEC xab = xa - xb;
double rab_n = invRc_*xab.norm();
double a = rab_n*rab_n; // always at least an interatomic distance
double b = 2.0*invRc_*invRc_*xab.dot(xb);
double c = rb_n*rb_n - 1.0;
double discrim = b*b - 4.0*a*c; // discriminant
if (discrim < 0) return; // no intersection
// num recipes:
double s1, s2;
if (b < 0.0) {
double aux = -0.5*(b-sqrt(discrim));
s1 = c/aux;
s2 = aux/a;
}
else {
double aux = -0.5*(b+sqrt(discrim));
s1 = aux/a;
s2 = c/aux;
}
if (a_in && !b_in) {
lam1 = s1;
lam2 = 1.0;
}
else if (!a_in && b_in) {
lam1 = 0.0;
lam2 = s2;
}
else {
if (s1 >= 0.0 && s2 <= 1.0) {
lam1 = s1;
lam2 = s2;
}
}
};
//------------------------------------------------------------------------
// constructor
ATC_HardyKernelStep::ATC_HardyKernelStep
(int nparameters, double* parameters):
ATC_HardyKernel(nparameters, parameters)
{
for (int k = 0; k < nsd_; k++ ) {
if ((bool) periodicity[k]) {
if (Rc_ > 0.5*box_length[k]) {
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
};
};
};
}
// function value
double ATC_HardyKernelStep::value(DENS_VEC& x_atom)
{
double rn=invRc_*x_atom.norm();
if (rn <= 1.0) { return 1.0; }
else { return 0.0; }
};
//------------------------------------------------------------------------
/** a step with rectangular support suitable for a rectangular grid */
// constructor
ATC_HardyKernelCell::ATC_HardyKernelCell
(int nparameters, double* parameters):
ATC_HardyKernel(nparameters, parameters)
{
hx = parameters[0];
hy = parameters[1];
hz = parameters[2];
invVol_ = 1.0/8.0/(hx*hy*hz);
cellBounds_.reset(6);
cellBounds_(0) = -hx;
cellBounds_(1) = hx;
cellBounds_(2) = -hy;
cellBounds_(3) = hy;
cellBounds_(4) = -hz;
cellBounds_(5) = hz;
for (int k = 0; k < nsd_; k++ ) {
if ((bool) periodicity[k]) {
if (parameters[k] > 0.5*box_length[k]) {
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
};
};
};
}
// function value
double ATC_HardyKernelCell::value(DENS_VEC& x_atom)
{
if ((cellBounds_(0) <= x_atom(0)) && (x_atom(0) < cellBounds_(1))
&& (cellBounds_(2) <= x_atom(1)) && (x_atom(1) < cellBounds_(3))
&& (cellBounds_(4) <= x_atom(2)) && (x_atom(2) < cellBounds_(5))) {
return 1.0;
}
else {
return 0.0;
}
};
// bond intercept values for rectangular region : origin is the node position
void ATC_HardyKernelCell::bond_intercepts(DENS_VEC& xa,
DENS_VEC& xb, double &lam1, double &lam2)
{
lam1 = 0.0; // start
lam2 = 1.0; // end
bool a_in = (value(xa) > 0.0);
bool b_in = (value(xb) > 0.0);
// (1) both in, no intersection needed
if (a_in && b_in) {
return;
}
// (2) for one in & one out -> one plane intersection
// determine the points of intersection between the line joining
// atoms a and b and the bounding planes of the localization volume
else if (a_in || b_in) {
DENS_VEC xab = xa - xb;
for (int i = 0; i < nsd_; i++) {
// check if segment is parallel to face
if (fabs(xab(i)) > tol) {
for (int j = 0; j < 2; j++) {
double s = (cellBounds_(2*i+j) - xb(i))/xab(i);
// check if between a & b
if (s >= 0 && s <= 1) {
bool in_bounds = false;
DENS_VEC x = xb + s*xab;
if (i == 0) {
if ((cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
in_bounds = true;
}
}
else if (i == 1) {
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
in_bounds = true;
}
}
else if (i == 2) {
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
&& (cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))) {
in_bounds = true;
}
}
if (in_bounds) {
if (a_in) { lam1 = s;}
else { lam2 = s;}
return;
}
}
}
}
}
throw ATC_Error(0,"logic failure in HardyKernel Cell for single intersection\n");
}
// (3) both out -> corner intersection
else {
lam2 = lam1; // default to no intersection
DENS_VEC xab = xa - xb;
double ss[6] = {-1,-1,-1,-1,-1,-1};
int is = 0;
for (int i = 0; i < nsd_; i++) {
// check if segment is parallel to face
if (fabs(xab(i)) > tol) {
for (int j = 0; j < 2; j++) {
double s = (cellBounds_(2*i+j) - xb(i))/xab(i);
// check if between a & b
if (s >= 0 && s <= 1) {
// check if in face
DENS_VEC x = xb + s*xab;
if (i == 0) {
if ((cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
ss[is++] = s;
}
}
else if (i == 1) {
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
ss[is++] = s;
}
}
else if (i == 2) {
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
&& (cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))) {
ss[is++] = s;
}
}
}
}
}
}
if (is == 1) {
// intersection occurs at a box edge - leave lam1 = lam2
}
else if (is == 2) {
lam1 = min(ss[0],ss[1]);
lam2 = max(ss[0],ss[1]);
}
else if (is == 3) {
// intersection occurs at a box vertex - leave lam1 = lam2
}
else {
if (is != 0) throw ATC_Error(0,"logic failure in HardyKernel Cell for corner intersection\n");
}
}
}
//------------------------------------------------------------------------
// constructor
ATC_HardyKernelCubicSphere::ATC_HardyKernelCubicSphere
(int nparameters, double* parameters):
ATC_HardyKernel(nparameters, parameters)
{
for (int k = 0; k < nsd_; k++ ) {
if ((bool) periodicity[k]) {
if (Rc_ > 0.5*box_length[k]) {
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
};
};
};
}
// function value
double ATC_HardyKernelCubicSphere::value(DENS_VEC& x_atom)
{
double r=x_atom.norm();
double rn=r/Rc_;
if (rn < 1.0) { return 5.0*(1.0-3.0*rn*rn+2.0*rn*rn*rn); }
else { return 0.0; }
}
//------------------------------------------------------------------------
// constructor
ATC_HardyKernelQuarticSphere::ATC_HardyKernelQuarticSphere
(int nparameters, double* parameters):
ATC_HardyKernel(nparameters, parameters)
{
for (int k = 0; k < nsd_; k++ ) {
if ((bool) periodicity[k]) {
if (Rc_ > 0.5*box_length[k]) {
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
};
};
};
}
// function value
double ATC_HardyKernelQuarticSphere::value(DENS_VEC& x_atom)
{
double r=x_atom.norm();
double rn=r/Rc_;
if (rn < 1.0) { return 35.0/8.0*pow((1.0-rn*rn),2); }
else { return 0.0; }
}
//------------------------------------------------------------------------
// constructor
ATC_HardyKernelCubicCyl::ATC_HardyKernelCubicCyl
(int nparameters, double* parameters):
ATC_HardyKernel(nparameters, parameters)
{
nsd_ = 2;
double Lz = box_length[2];
invVol_ = 1.0/(Pi*pow(Rc_,2)*Lz);
for (int k = 0; k < nsd_; k++ ) {
if ((bool) periodicity[k]) {
if (Rc_ > 0.5*box_length[k]) {
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
};
};
};
}
// function value
double ATC_HardyKernelCubicCyl::value(DENS_VEC& x_atom)
{
double r=sqrt(pow(x_atom(0),2)+pow(x_atom(1),2));
double rn=r/Rc_;
if (rn < 1.0) { return 10.0/3.0*(1.0-3.0*rn*rn+2.0*rn*rn*rn); }
else { return 0.0; }
}
//------------------------------------------------------------------------
// constructor
ATC_HardyKernelQuarticCyl::ATC_HardyKernelQuarticCyl
(int nparameters, double* parameters):
ATC_HardyKernel(nparameters, parameters)
{
nsd_ = 2;
double Lz = box_length[2];
invVol_ = 1.0/(Pi*pow(Rc_,2)*Lz);
for (int k = 0; k < nsd_; k++ ) {
if ((bool) periodicity[k]) {
if (Rc_ > 0.5*box_length[k]) {
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
};
};
};
}
// function value
double ATC_HardyKernelQuarticCyl::value(DENS_VEC& x_atom)
{
double r=sqrt(pow(x_atom(0),2)+pow(x_atom(1),2));
double rn=r/Rc_;
if (rn < 1.0) { return 3.0*pow((1.0-rn*rn),2); }
else { return 0.0; }
}
};

View File

@ -1,127 +0,0 @@
/** ATC_HardyKernel: Hardy smoothing */
#ifndef ATC_HARDY_KERNEL_H
#define ATC_HARDY_KERNEL_H
#include "LammpsInterface.h"
#include "MatrixLibrary.h"
namespace ATC {
class ATC_HardyKernel {
public:
// constructor
ATC_HardyKernel(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernel() {};
// function value
virtual double value(DENS_VEC& x_atom)=0;
// bond function value via quadrature
virtual double bond(DENS_VEC& xa, DENS_VEC&xb, double lam1, double lam2);
// localization-volume intercepts for bond calculation
virtual void bond_intercepts(DENS_VEC& xa,
DENS_VEC& xb, double &lam1, double &lam2);
double inv_vol(void) { return invVol_; }
protected:
double invVol_; // normalization factor
double Rc_, invRc_; // cutoff radius
int nsd_ ; // number of dimensions
/** pointer to lammps interface class */
LammpsInterface * lammpsInterface_;
/** periodicity flags and lengths */
int periodicity[3];
double box_bounds[2][3];
double box_length[3];
};
/** a step with spherical support */
class ATC_HardyKernelStep : public ATC_HardyKernel {
public:
// constructor
ATC_HardyKernelStep(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernelStep() {};
// function value
double value(DENS_VEC& x_atom);
// bond function value
virtual double bond(DENS_VEC& xa, DENS_VEC&xb, double lam1, double lam2)
{return lam2 -lam1;}
};
/** a step with rectangular support suitable for a rectangular grid */
class ATC_HardyKernelCell : public ATC_HardyKernel {
public:
// constructor
ATC_HardyKernelCell(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernelCell() {};
// function value
virtual double value(DENS_VEC& x_atom);
// bond function value
virtual double bond(DENS_VEC& xa, DENS_VEC&xb, double lam1, double lam2)
{return lam2 -lam1;}
// bond intercept values : origin is the node position
void bond_intercepts(DENS_VEC& xa,
DENS_VEC& xb, double &lam1, double &lam2);
protected:
double hx, hy, hz;
DENS_VEC cellBounds_;
};
class ATC_HardyKernelCubicSphere : public ATC_HardyKernel {
public:
// constructor
ATC_HardyKernelCubicSphere(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernelCubicSphere() {};
// function value
virtual double value(DENS_VEC& x_atom);
};
class ATC_HardyKernelQuarticSphere : public ATC_HardyKernel {
public:
// constructor
ATC_HardyKernelQuarticSphere(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernelQuarticSphere() {};
// function value
virtual double value(DENS_VEC& x_atom);
};
class ATC_HardyKernelCubicCyl : public ATC_HardyKernel {
public:
// constructor
ATC_HardyKernelCubicCyl(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernelCubicCyl() {};
// function value
virtual double value(DENS_VEC& x_atom) ;
};
class ATC_HardyKernelQuarticCyl : public ATC_HardyKernel {
public:
// constructor
ATC_HardyKernelQuarticCyl(int nparameters, double* parameters);
// destructor
virtual ~ATC_HardyKernelQuarticCyl() {};
// function value
virtual double value(DENS_VEC& x_atom);
};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,952 +0,0 @@
// ATC_Transfer : a base class for atom-continuum transfers & control
// (derived classes are physics dependent)
// note init() must be called before most functions will work
// we expect only one derived class to exist, i.e. don't call initilize/modify/etc more than once
// NOTE: implement print
#ifndef ATC_TRANSFER_H
#define ATC_TRANSFER_H
// ATC_Transfer headers
#include "PhysicsModel.h"
#include "MatrixLibrary.h"
#include "Array.h"
#include "Array2D.h"
#include "OutputManager.h"
#include "XT_Function.h"
#include "FE_Element.h"
#include "TimeFilter.h"
#include "LammpsInterface.h"
#include "FE_Engine.h"
#include "ExtrinsicModel.h"
// Other headers
#include <vector>
#include <set>
using namespace std;
namespace ATC {
// Forward declarations
class PrescribedDataManager;
class TimeIntegrator;
/**
* @class ATC_Transfer
* @brief Base class for atom-continuum transfer operators
*/
class ATC_Transfer {
public:
// NOTE should remove friends and use existing ATC hooks
friend class ExtrinsicModel; // friend is not inherited
friend class ExtrinsicModelTwoTemperature;
friend class ExtrinsicModelDriftDiffusion;
friend class ExtrinsicModelElectrostatic;
friend class ExtrinsicModelElectrostaticElastic;
//---------------------------------------------------------------
/** \name enumerated types */
//---------------------------------------------------------------
/*@{*/
/** boundary integration */
enum BoundaryIntegrationType {
NO_QUADRATURE=0,
FE_QUADRATURE,
FE_INTERPOLATION
};
/** boundary integration */
enum IntegrationDomainType {
FULL_DOMAIN=0,
ATOM_DOMAIN,
FE_DOMAIN
};
/** atomic weight specification */
enum AtomicWeightType {
USER=0,
LATTICE,
ELEMENT,
REGION,
GROUP,
MULTISCALE
};
/** shape function location with respect to MD domain */
enum ShapeFunctionType {
FE_ONLY = 0,
MD_ONLY,
BOUNDARY
};
/** */
enum AtomToElementMapType {
LAGRANGIAN=0,
EULERIAN
};
/* enumerated type for coupling matrix structure */
enum MatrixStructure {
FULL=0, // contributions from all nodes
LOCALIZED, // contributions only from nodes with sources
LUMPED // row-sum lumped version of full matrix
};
/** */
enum GroupThermostatType {
RESCALE_TEMPERATURE,
RESCALE_TEMPERATURE_RATE,
RESCALE_RATE
};
/** */
enum GroupThermostatMomentumControl {
NO_MOMENTUM_CONTROL,
ZERO_MOMENTUM,
PRESERVE_MOMENTUM
};
/** */
enum ATC_GroupComputes { LAMBDA_POWER };
/*@}*/
/** constructor */
ATC_Transfer(void);
/** destructor */
virtual ~ATC_Transfer();
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre integration run */
virtual void initialize();
/** post integration run : called at end of run or simulation */
virtual void finish();
/** Predictor phase, executed before Verlet */
virtual void pre_init_integrate() = 0;
/** Predictor phase, Verlet first step for velocity */
virtual void init_integrate_velocity();
/** Predictor phase, executed between velocity and position Verlet */
virtual void mid_init_integrate() = 0;
/** Predictor phase, Verlet first step for position */
virtual void init_integrate_position();
/** Predictor phase, executed after Verlet */
virtual void post_init_integrate() = 0;
/** Corrector phase, executed before Verlet */
virtual void pre_final_integrate();
/** Corrector phase, Verlet second step for velocity */
virtual void final_integrate();
/** Corrector phase, executed after Verlet*/
virtual void post_final_integrate()=0;
//---------------------------------------------------------------
/** \name memory management and processor information exchange */
//---------------------------------------------------------------
/*@{*/
/** pre_exchange is our indicator that atoms have moved across processors */
void pre_exchange() {
atomSwitch_ = true;
}
int memory_usage();
void grow_arrays(int);
void copy_arrays(int, int);
int pack_exchange(int, double *);
int unpack_exchange(int, double *);
int pack_comm(int , int *, double *, int, int *);
void unpack_comm(int, int, double *);
/*@}*/
/** Get grouping bit for LAMMPS compatability */
int get_groupbit() { return groupbit_; }
//---------------------------------------------------------------
/** \name Wrappers for calls to lammps region.h information */
//---------------------------------------------------------------
/*@{*/
bool get_region_bounds(const char * regionName,
double &xmin, double &xmax,
double &ymin, double & ymax,
double &zmin, double &zmax,
double &xscale,
double &yscale,
double &zscale);
/** return pointer to PrescribedDataManager */
PrescribedDataManager * get_prescribed_data_manager() {
return prescribedDataMgr_;
}
/** return referece to ExtrinsicModelManager */
ExtrinsicModelManager & get_extrinsic_model_manager() {
return extrinsicModelManager_;
}
/** compute scalar for output */
virtual double compute_scalar() {return 0.;}
/** compute vector for output */
virtual double compute_vector(int n) {return 0.;}
/*@}*/
//---------------------------------------------------------------
/** \name access methods for output computation data */
//---------------------------------------------------------------
/*@{*/
int scalar_flag() const {return scalarFlag_;}
int vector_flag() const {return vectorFlag_;}
int size_vector() const {return sizeVector_;}
int global_freq() const {return globalFreq_;};
int extscalar() const {return extScalar_;};
int extvector() const {return extVector_;};
int * extlist() {return extList_;};
/*@}*/
//---------------------------------------------------------------
/** \name Access methods for data used by various methods */
//---------------------------------------------------------------
/*@{*/
/** access to name FE fields */
DENS_MAT &get_field(FieldName thisField){return fields_[thisField];};
/** access to FE field time derivatives */
DENS_MAT &get_dot_field(FieldName thisField){return dot_fields_[thisField];};
/** access to name FE source terms */
DENS_MAT &get_source(FieldName thisField){return sources_[thisField];};
/** access to name atomic source terms */
DENS_MAT &get_atomic_source(FieldName thisField){return atomicSources_[thisField];};
/** access to name extrinsic source terms */
DENS_MAT &get_extrinsic_source(FieldName thisField){return extrinsicSources_[thisField];};
/** access to boundary fluxes */
DENS_MAT &get_boundary_flux(FieldName thisField){return boundaryFlux_[thisField];};
/** access to nodal fields of atomic variables */
DENS_MAT &get_atomic_field(FieldName thisField)
{ return fieldNdFiltered_[thisField]; };
/** access to auxilliary storage */
DENS_MAT &get_aux_storage(FieldName thisField)
{ return auxStorage_[thisField]; };
/** access to all fields */
FIELDS &get_fields() {return fields_;};
/** access to all fields rates of change (roc) */
FIELDS &get_fields_roc() {return dot_fields_;};
/** access to all boundary fluxes */
FIELDS &get_boundary_fluxes() {return boundaryFlux_;};
/** add a new field */
void add_fields(map<FieldName,int> & newFieldSizes);
/** access to finite element right-hand side data */
DENS_MAT &get_field_rhs(FieldName thisField)
{ return rhs_[thisField]; };
/** access to inverse mass matrices */
DIAG_MAT &get_mass_mat_inv(FieldName thisField)
{ return massMatInv_[thisField];};
DIAG_MAT &get_mass_mat_md(FieldName thisField)
{ return massMatsMD_[thisField];};
/** access FE rate of change */
DENS_MAT &get_field_roc(FieldName thisField)
{ return dot_fields_[thisField]; };
/** access atomic rate of change contributions to finite element equation */
DENS_MAT &get_fe_atomic_field_roc(FieldName thisField)
{ return fieldRateNdFiltered_[thisField]; };
/** access to atomic rate of change */
DENS_MAT &get_atomic_field_roc(FieldName thisField)
{return dot_fieldRateNdFiltered_[thisField]; };
/** access to second time derivative (2roc) */
DENS_MAT &get_field_2roc(FieldName thisField)
{ return ddot_fields_[thisField]; };
/** access for field mask */
Array2D<bool> &get_field_mask() {return fieldMask_;};
/** access for shape function weigths */
DIAG_MAT &get_shape_function_weights(){return shpWeight_;};
/** access to template matrix for control equations */
SPAR_MAT &get_m_t_template(){return M_T_Template;};
/** access for mapping from global nodes to nodes overlapping MD */
Array<int> &get_node_to_overlap_map(){return nodeToOverlapMap_;};
/** access for mapping from nodes overlapping MD to global nodes */
Array<int> &get_overlap_to_node_map(){return overlapToNodeMap_;};
/** number of nodes whose shape function support overlaps with MD */
int get_nNode_overlap(){return nNodeOverlap_;};
/** check if atomic quadrature is being used for MD_ONLY nodes */
bool atom_quadrature_on(){return atomQuadForInternal_;};
/** check if lambda is localized */
bool use_localized_lambda(){return useLocalizedLambda_;};
/** check if matrix should be lumpted for lambda solve */
bool use_lumped_lambda_solve(){return useLumpedLambda_;};
/** get scaled shape function matrix */
SPAR_MAT &get_nhat_overlap() {return NhatOverlap_;};
/** get scaled shape function matrix weights */
DENS_VEC &get_nhat_overlap_weights() {return NhatOverlapWeights_;};
/** get map general atomic shape function matrix to overlap region */
SPAR_MAT &get_atom_to_overlap_map() {return Trestrict_;};
/** internal atom to global map */
Array<int> &get_internal_to_atom_map() {return internalToAtom_;};
/** ghost atom to global map */
Array<int> &get_ghost_to_atom_map() {return ghostToAtom_;};
/** get number of unique FE nodes */
int get_nNodes() {return nNodes_;};
/** get number of spatial dimensions */
int get_nsd() {return nsd_;};
/** get number of ATC internal atoms on this processor */
int get_nlocal() {return nLocal_;};
/** get total number of LAMMPS atoms on this processor */
int get_nlocal_total() {return nLocalTotal_;};
/** get number of ATC ghost atoms on this processor */
int get_nlocal_ghost() {return nLocalGhost_;};
/** get number of ATC mask atoms on this processor */
int get_nlocal_mask() {return nLocalMask_;};
/** get number of ATC atoms used in lambda computation on this processor */
int get_nlocal_lambda() {return nLocalLambda_;};
/** get number of ATC internal atoms */
int get_ninternal() {return nInternal_;}
/** get number of ATC ghost atoms */
int get_nghost() {return nGhost_;};
/** get the current simulation time */
double get_sim_time() {return simTime_;};
/** access to lammps atomic positions */
double ** get_x() {return lammpsInterface_->xatom();};
/** access to lammps atomic velocities */
double ** get_v() {return lammpsInterface_->vatom();};
/** access to lammps atomic forces */
double ** get_f() {return lammpsInterface_->fatom();};
/** access to physics model */
PhysicsModel * get_physics_model() {return physicsModel_; };
/** access to time filter */
TimeFilterManager * get_time_filter_manager() {return &timeFilterManager_;};
/** access to time integrator */
TimeIntegrator * get_time_integrator() {return timeIntegrator_;};
/** access to FE engine */
FE_Engine * get_fe_engine() {return feEngine_;};
/** access to faceset names */
const set<PAIR> &get_faceset(const string & name) const {return (feEngine_->get_feMesh())->get_faceset(name);};
/** access to overlapped ghost shape function */
SPAR_MAT & get_shape_function_ghost_overlap(){return shpFcnGhostOverlap_;};
/** return fixed node flag for a field */
Array2D<bool> & get_fixed_node_flags(FieldName thisField) {return isFixedNode_[thisField];};
Array<int> & get_node_type() {return nodeType_;};
void get_field(/*const*/ char ** args, int &argIndex,
FieldName &thisField, int &thisIndex);
DIAG_MAT & get_atomic_weights() {return atomicWeights_;};
bool track_charge() {return trackCharge_;};
/** access to set of DENS_MATs accessed by tagging */
DENS_MAT & get_tagged_dens_mat(const string & tag) {return taggedDensMats_[tag];};
/** access to set of SPAR_MATs accessed by tagging */
SPAR_MAT & get_tagged_spar_mat(const string & tag) {return taggedSparMats_[tag];};
/*@}*/
//---------------------------------------------------------------
/** \name boundary integration */
//---------------------------------------------------------------
/*@{*/
void set_boundary_integration_type(int boundaryIntegrationType)
{bndyIntType_ = boundaryIntegrationType;};
void set_boundary_face_set(const set< pair<int,int> > * boundaryFaceSet)
{bndyFaceSet_ = boundaryFaceSet;};
BoundaryIntegrationType parse_boundary_integration
(int narg, char **arg, const set< pair<int,int> > * boundaryFaceSet);
/*@}*/
//---------------------------------------------------------------
/** \name FE nodesets/sidesets functions */
//---------------------------------------------------------------
/*@{*/
/** mask for computation of fluxes */
void set_fixed_nodes();
/** set initial conditions by changing fields */
void set_initial_conditions();
/** calculate and set matrix of sources_ */
void set_sources();
/** array indicating fixed nodes for all fields */
map<FieldName, Array2D<bool> > isFixedNode_;
/** array indicating if the node is boundary, MD, or FE */
Array<int> nodeType_;
/** wrapper for FE_Engine's compute_flux functions */
void compute_flux(const Array2D<bool> & rhs_mask,
const FIELDS &fields,
GRAD_FIELDS &flux,
const PhysicsModel * physicsModel=NULL);
/** wrapper for FE_Engine's compute_boundary_flux functions */
void compute_boundary_flux(const Array2D<bool> & rhs_mask,
const FIELDS &fields,
FIELDS &rhs);
/** wrapper for FE_Engine's compute_rhs_vector functions */
void compute_rhs_vector(const Array2D<bool> & rhs_mask,
const FIELDS &fields,
FIELDS &rhs,
const IntegrationDomainType domain, // = FULL_DOMAIN
const PhysicsModel * physicsModel=NULL);
/** evaluate rhs on a specified domain defined by mask and physics model */
void evaluate_rhs_integral(const Array2D<bool> & rhs_mask,
const FIELDS &fields,
FIELDS &rhs,
const IntegrationDomainType domain,
const PhysicsModel * physicsModel=NULL);
/** assemble various contributions to the heat flux in the atomic region */
void compute_atomic_sources(const Array2D<bool> & rhs_mask,
const FIELDS &fields,
FIELDS &atomicSources);
/** multiply inverse mass matrix times given data in place */
// NOTE change massMatInv to map of pointers and allow for consistent mass matrices
// inverted using CG
void apply_inverse_mass_matrix(MATRIX & data, FieldName thisField)
{
data = massMatInv_[thisField]*data;
};
/** multiply inverse mass matrix times given data and return result */
void apply_inverse_mass_matrix(const MATRIX & data_in, MATRIX & data_out,
FieldName thisField)
{
data_out = massMatInv_[thisField]*data_in;
};
void apply_inverse_md_mass_matrix(MATRIX & data, FieldName thisField)
{ data = massMatMDInv_[thisField]*data; };
void apply_inverse_md_mass_matrix(const MATRIX & data_in, MATRIX & data_out,
FieldName thisField)
{ data_out = massMatMDInv_[thisField]*data_in; };
/*@}*/
//----------------------------------------------------------------
/** \name FE mapping operations */
//----------------------------------------------------------------
/*@{*/
/** Mapping between unique nodes and nodes overlapping MD region */
void map_unique_to_overlap(const MATRIX & uniqueData,
MATRIX & overlapData);
/** Mapping between nodes overlapping MD region to unique nodes */
void map_overlap_to_unique(const MATRIX & overlapData,
MATRIX & uniqueData);
/*@}*/
//----------------------------------------------------------------
/** \name Interscale operators */
//----------------------------------------------------------------
/*@{*/
/** Restrict (number density) : given w_\alpha, w_I = 1/V_I \sum_\alpha N_{I\alpha} w_\alpha */
void restrict(const MATRIX &atomData,
MATRIX &nodeData);
/** Restrict based on atomic volume integration : given w_\alpha, w_I = \sum_\alpha N_{I\alpha} w_\alpha V_\alpha */
void restrict_unscaled(const MATRIX &atomData,
MATRIX &nodeData);
/** Restrict based on atomic volume integration for volumetric quantities : given w_\alpha, w_I = \sum_\alpha N_{I\alpha} w_\alpha */
void restrict_volumetric_quantity(const MATRIX &atomData,
MATRIX &nodeData);
void restrict_volumetric_quantity(const MATRIX &atomData,
MATRIX &nodeData,
const SPAR_MAT &shpFcn);
/** Project based on an atomic volume integration : given w_\alpha, \sum_\alpha M_\alpha w_I = \sum_\alpha N_{I\alpha} w_\alpha V_\alpha (note mass matrix has V_\alpha in it) */
void project(const MATRIX &atomData,
MATRIX &nodeData,
FieldName thisField);
void project_md(const MATRIX &atomData,
MATRIX &nodeData,
FieldName thisField);
/** Project based on an atomic volume integration for volumetric quantities : given w_\alpha, \sum_\alpha M_\alpha w_I = \sum_\alpha N_{I\alpha} w_\alpha */
void project_volumetric_quantity(const MATRIX &atomData,
MATRIX &nodeData,
FieldName thisField);
void project_volumetric_quantity(const MATRIX &atomData,
MATRIX &nodeData,
const SPAR_MAT &shpFcn,
FieldName thisField);
void project_md_volumetric_quantity(const MATRIX &atomData,
MATRIX &nodeData,
FieldName thisField);
void project_md_volumetric_quantity(const MATRIX &atomData,
MATRIX &nodeData,
const SPAR_MAT &shpFcn,
FieldName thisField);
/** Prolong : given w_I, w_\alpha = \sum_I N_{I\alpha} w_I */
void prolong(const MATRIX &nodeData,
MATRIX &atomData);
/** Prolong based on scaled shape functions : given w_I, w_\alpha = \sum_I 1/V_I N_{I\alpha} w_I */
void prolong_scaled(const MATRIX &nodeData,
MATRIX &atomData);
/** Prolong onto ghost atoms*/
void prolong_ghost(const MATRIX &nodeData,
MATRIX &atomData);
/*@}*/
//----------------------------------------------------------------
/** \name Interscale physics constructors */
//----------------------------------------------------------------
/*@{*/
/** Compute atomic masses */
void compute_atomic_mass(MATRIX &atomicMasses);
/** Compute atomic charges */
void compute_atomic_charge(MATRIX &atomicCharges);
/** Compute atomic temperature
possibly using dot product of two velocities */
void compute_atomic_temperature(MATRIX &T,
const double * const* v,
double ** v2 = NULL);
/** Compute atomic kinetic energy
possibly using dot product of two velocities */
void compute_atomic_kinetic_energy(MATRIX &T,
const double * const* v,
double ** v2 = NULL);
/** Compute atomic power : in units dT/dt */
void compute_atomic_power(MATRIX &dot_T,
const double * const* v,
const double * const* f);
void compute_atomic_temperature_roc(MATRIX &dot_T,
const double * const* v,
const double * const* f);
void compute_atomic_power(MATRIX &dot_T,
const double * const* v,
const MATRIX & f);
void compute_atomic_temperature_roc(MATRIX &dot_T,
const double * const* v,
const MATRIX & f);
// NOTE change these when physical mass matrix is used
/** Compute magnitude of atomic force */
void compute_atomic_force_strength(MATRIX &forceStrength,
const double * const* f);
void compute_atomic_force_strength(MATRIX &forceStrength,
const MATRIX & f);
void compute_atomic_force_dot(MATRIX &forceDot,
const double * const* f1,
const MATRIX & f2);
/** Compute lambda power at atoms : in units dT/dt */
void compute_atomic_temperature_roc(MATRIX &atomicVdotflam,
const MATRIX &lambda,
const double * const* v);
void compute_atomic_power(MATRIX &atomicVdotflam,
const MATRIX &lambda,
const double * const* v);
/** Compute lambda power at atoms : in units dT/dt */
void compute_atomic_lambda_power(MATRIX &atomicPower,
const MATRIX &force,
const double * const* v);
void compute_atomic_temperature_lambda_roc(MATRIX &atomicPower,
const MATRIX &force,
const double * const* v);
/** Compute lambda power at atoms with explicit application */
void compute_lambda_power_explicit(MATRIX &lambdaPower,
const MATRIX &lambda,
const double * const* v,
const double dt);
/** Compute atomic position */
void compute_atomic_position(DENS_MAT &atomicDisplacement,
const double * const* x);
/** Compute atomic center of mass */
void compute_atomic_centerOfMass(DENS_MAT &atomicCom,
const double * const* x);
/** Compute atomic displacement */
void compute_atomic_displacement(DENS_MAT &atomicDisplacement,
const double * const* x);
/** Compute atomic mass displacement */
void compute_atomic_centerOfMass_displacement(DENS_MAT &atomicMd,
const double * const* x);
/** Compute atomic velocity */
void compute_atomic_velocity(DENS_MAT &atomicVelocity,
const double * const* v);
/** Compute atomic momentum */
void compute_atomic_momentum(DENS_MAT &atomicMomentum,
const double * const* v);
/** Compute atomic acceleration */
void compute_atomic_acceleration(DENS_MAT &atomicAcceleration,
const double * const* f);
/** Compute atomic force */
void compute_atomic_force(DENS_MAT &atomicForce,
const double * const* f);
/*@}*/
/** allow FE_Engine to construct ATC structures after mesh is constructed */
void initialize_mesh_data(void);
protected:
/** pointer to lammps interface class */
LammpsInterface * lammpsInterface_;
/** pointer to physics model */
PhysicsModel * physicsModel_;
/** manager for extrinsic models */
ExtrinsicModelManager extrinsicModelManager_;
/** method to create physics model */
void create_physics_model(const PhysicsType & physicsType,
string matFileName);
/** global flag to indicate atoms have changed processor
keyed off of atomSwitch (see pre_exchange() which sets atomSwitch =true)
*/
int globalSwitch_ ;
/** a global flag to trigger reset of shape function at will */
bool resetSwitch_;
/** flag on if initialization has been performed */
bool initialized_;
/** flag to determine if charge is tracked */
bool trackCharge_;
TimeFilterManager timeFilterManager_;
TimeIntegrator * timeIntegrator_;
/** finite element handler */
FE_Engine * feEngine_;
/** prescribed data handler */
PrescribedDataManager * prescribedDataMgr_;
/** reference atomic coordinates */
DENS_MAT atomicCoords_;
DENS_MAT atomicCoordsMask_;
/** number of unique FE nodes */
int nNodes_;
/** Number of Spatial Dimensions */
int nsd_;
/** data for handling atoms crossing processors */
bool atomSwitch_;
/** reference position of the atoms */
double ** xref_;
double Xprd_,Yprd_,Zprd_;
double XY_,YZ_,XZ_;
void set_xref();
/** current time in simulation */
double simTime_;
/** re-read reference positions */
bool readXref_;
string xRefFile_;
//---------------------------------------------------------------
/** \name FE nodesets/sidesets data */
//---------------------------------------------------------------
/*@{*/
/** mask for computation of fluxes */
Array2D<bool> fieldMask_;
/** sources */
FIELDS sources_;
FIELDS atomicSources_;
FIELDS extrinsicSources_;
/** boundary flux quadrature */
int bndyIntType_;
const set< pair<int,int> > * bndyFaceSet_;
set<string> boundaryFaceNames_;
/*@}*/
//---------------------------------------------------------------
/** \name output data */
//---------------------------------------------------------------
/*@{*/
/** base name for output files */
string outputPrefix_;
/** output frequency */
int outputFrequency_;
/** sample frequency */
int sampleFrequency_;
/** step counter */
int stepCounter_;
/** sample counter */
int sampleCounter_;
/** atomic output */
/** base name for output files */
string outputPrefixAtom_;
/** output frequency */
int outputFrequencyAtom_;
/** output object */
OutputManager mdOutputManager_;
set<string> atomicOutputMask_;
/*@}*/
//---------------------------------------------------------------
/** \name output functions */
//---------------------------------------------------------------
/*@{*/
void output();
void atomic_output();
/*@}*/
//---------------------------------------------------------------
/** \name member data related to compute_scalar() and compute_vector() */
//---------------------------------------------------------------
/*@{*/
int scalarFlag_; // 0/1 if compute_scalar() function exists
int vectorFlag_; // 0/1 if compute_vector() function exists
int sizeVector_; // N = size of global vector
int globalFreq_; // frequency global data is available at
int extScalar_; // 0/1 if scalar is intensive/extensive
int extVector_; // 0/1/-1 if vector is all int/ext/extlist
int *extList_; // list of 0/1 int/ext for each vec component
/*@}*/
//---------------------------------------------------------------
/** \name fields and necessary data for FEM */
//---------------------------------------------------------------
/*@{*/
map<FieldName,int> fieldSizes_;
FIELDS fields_;
map<FieldName,DIAG_MAT > massMats_;
map<FieldName,DIAG_MAT > massMatInv_;
map<FieldName,DIAG_MAT > massMatsMD_;
map<FieldName,DIAG_MAT > massMatMDInv_;
virtual void compute_md_mass_matrix(FieldName thisField,
map<FieldName,DIAG_MAT> & massMats) {};
DENS_MAT consistentMassInverse_;
FIELDS rhs_; // for pde
FIELDS rhsAtomDomain_; // for thermostat
FIELDS boundaryFlux_; // for thermostat & rhs pde
/*@}*/
//---------------------------------------------------------------
/** \name time integration and filtering fields */
//---------------------------------------------------------------
/*@{*/
FIELDS dot_fields_;
FIELDS ddot_fields_;
FIELDS dddot_fields_;
FIELDS dot_fieldsMD_;
FIELDS ddot_fieldsMD_;
FIELDS dot_dot_fieldsMD_;
/** Restricted Fields */
FIELDS fieldNdOld_;
FIELDS fieldNdFiltered_;
FIELDS fieldRateNdOld_;
FIELDS fieldRateNdFiltered_;
FIELDS dot_fieldRateNdOld_;
FIELDS dot_fieldRateNdFiltered_;
/** auxilliary storage */
FIELDS auxStorage_;
/*@}*/
//---------------------------------------------------------------
/** \name quadrature weights */
//---------------------------------------------------------------
/*@{*/
DIAG_MAT NodeVolumes_;
DIAG_MAT invNodeVolumes_;
/** atomic quadrature integration weights (V_\alpha) */
DIAG_MAT atomicWeights_;
DIAG_MAT atomicWeightsMask_;
double atomicVolume_; // global atomic volume for homogeneous set of atoms
map<int,double> Valpha_;
AtomicWeightType atomWeightType_;
/** weighting factor per shape function:
shpWeight_(I,I) = 1/N_I = 1/(\sum_\alpha N_{I\alpha}) */
DIAG_MAT shpWeight_;
DIAG_MAT fluxMask_;
DIAG_MAT fluxMaskComplement_;
/*@}*/
//---------------------------------------------------------------
/** \name quadrature weight function */
//---------------------------------------------------------------
/*@{*/
/** determine weighting method for atomic integration */
void reset_atomicWeightsLattice();
void reset_atomicWeightsElement();
void reset_atomicWeightsRegion();
void reset_atomicWeightsGroup();
void reset_atomicWeightsMultiscale(const SPAR_MAT & shapeFunctionMatrix,
DIAG_MAT & atomicVolumeMatrix);
void compute_consistent_md_mass_matrix(const SPAR_MAT & shapeFunctionMatrix,
SPAR_MAT & mdMassMatrix);
/** resets shape function matrices based on atoms on this processor */
virtual void reset_nlocal();
void reset_coordinates();
void set_atomic_weights();
virtual void reset_shape_functions();
void reset_NhatOverlap();
/*@}*/
//---------------------------------------------------------------
/** \name atom data */
//---------------------------------------------------------------
/*@{*/
/** bitwise comparisons for boundary (ghost) atoms */
int groupbit_;
int groupbitGhost_;
set<int> igroups_;
set<int> igroupsGhost_;
/** number of atoms of correct type,
ghosts are atoms outside our domain of interest
boundary are atoms contributing to boundary flux terms */
/** Number of "internal" atoms on this processor */
int nLocal_;
/** Number of atoms on this processor */
int nLocalTotal_;
int nLocalGhost_;
int nLocalMask_;
int nLocalLambda_;
int nInternal_;
int nGhost_;
Array<int> internalToAtom_;
std::map<int,int> atomToInternal_;
Array<int> ghostToAtom_;
DENS_MAT ghostAtomCoords_;
/*@}*/
//----------------------------------------------------------------
/** \name maps and masks */
//----------------------------------------------------------------
/*@{*/
AtomToElementMapType atomToElementMapType_;
int atomToElementMapFrequency_;
Array<int> atomToElementMap_;
Array<int> ghostAtomToElementMap_;
/** overlap map, from shapeWeights */
// -1 is no overlap, otherwise entry is overlap index
Array<int> nodeToOverlapMap_;
// mapping from overlap nodes to unique nodes
Array<int> overlapToNodeMap_;
int nNodeOverlap_;
Array<bool> elementMask_;
Array<int> elementToMaterialMap_;
Array< set <int> > atomMaterialGroups_;
int regionID_;
bool atomQuadForInternal_;
bool useLocalizedLambda_;
bool useLumpedLambda_;
/*@}*/
//----------------------------------------------------------------
/** \name Map related functions */
//----------------------------------------------------------------
/*@{*/
bool check_internal(int eltIdx);
int check_shape_function_type(int nodeIdx);
bool intersect_ghost(int eltIdx);
virtual void set_ghost_atoms() = 0;
/*@}*/
//----------------------------------------------------------------
/** \name shape function matrices */
//----------------------------------------------------------------
/*@{*/
// sparse matrix where columns correspond to global node numbering
// dimensions are numAtoms X numNodes (the transpose of N_{I\alpha} )
/** shpFcn_ is N_{I\alpha} the un-normalized shape function evaluated at the atoms */
SPAR_MAT shpFcn_;
vector<SPAR_MAT > shpFcnDerivs_;
SPAR_MAT shpFcnGhost_;
SPAR_MAT shpFcnGhostOverlap_;
vector<SPAR_MAT > shpFcnDerivsGhost_;
SPAR_MAT shpFcnMasked_;
vector<SPAR_MAT > shpFcnDerivsMask_;
Array<bool> atomMask_;
/** map from species string tag to the species density */
map<string,DENS_MAT> taggedDensMats_;
/** map from species string tag to shape function and weight matrices */
map<string,SPAR_MAT> taggedSparMats_;
/** weighted shape function matrices at overlap nodes
for use with thermostats */
// dimensions are numAtoms X numNodesOverlap
SPAR_MAT NhatOverlap_;
SPAR_MAT Trestrict_;
DENS_VEC NhatOverlapWeights_;
/*@}*/
//---------------------------------------------------------------
/** \name thermostat data */
//---------------------------------------------------------------
/*@{*/
/** sparse matrix to store elements needed for CG solve */
SPAR_MAT M_T_Template;
DIAG_MAT maskMat_;
bool equilibriumStart_;
//---------------------------------------------------------------
/** \name time filtering */
//---------------------------------------------------------------
/*@{*/
/** allocate memory for time filter */
void init_filter();
void update_filter(MATRIX &filteredQuantity,
const MATRIX &unfilteredQuantity,
MATRIX &unfilteredQuantityOld,
const double dt);
double get_unfiltered_coef(const double dt);
void update_filter_implicit(MATRIX &filteredQuantity,
const MATRIX &unfilteredQuantity,
const double dt);
/*@}*/
/** group computes : type, group_id -> value */
map< pair < int, int > , double> groupCompute_;
/** group computes : type, group_id -> value */
map< pair < string, FieldName > , double> nsetCompute_;
/** allow FE_Engine to construct data manager after mesh is constructed */
void construct_prescribed_data_manager (void);
//---------------------------------------------------------------
/** \name restart procedures */
//---------------------------------------------------------------
bool useRestart_;
string restartFileName_;
virtual void read_restart_data(string fileName_, OUTPUT_LIST & data);
virtual void write_restart_data(string fileName_, OUTPUT_LIST & data);
void pack_fields(OUTPUT_LIST & data);
//---------------------------------------------------------------
/** \name neighbor reset frequency */
//---------------------------------------------------------------
int neighborResetFrequency_;
};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,346 +0,0 @@
/** ATC_TransferHardy : Hardy smoothing */
#ifndef ATC_TRANSFER_HARDY_H
#define ATC_TRANSFER_HARDY_H
// ATC_Transfer headers
#include "ATC_Transfer.h"
#include "LammpsInterface.h"
#include "ATC_HardyKernel.h"
#include "TimeFilter.h"
// Other headers
#include <map>
#include <list>
using std::list;
namespace ATC {
enum hardyNormalization {
NO_NORMALIZATION=0,
VOLUME_NORMALIZATION, NUMBER_NORMALIZATION, MASS_NORMALIZATION
};
enum hardyFieldName {
HARDY_DENSITY=0,
HARDY_DISPLACEMENT,
HARDY_MOMENTUM,
HARDY_VELOCITY,
HARDY_PROJECTED_VELOCITY,
HARDY_TEMPERATURE,
HARDY_KINETIC_TEMPERATURE,
HARDY_STRESS,
HARDY_HEAT_FLUX,
HARDY_ENERGY,
HARDY_NUMBER_DENSITY,
HARDY_ESHELBY_STRESS,
HARDY_CAUCHY_BORN_STRESS,
HARDY_TRANSFORMED_STRESS,
HARDY_VACANCY_CONCENTRATION,
HARDY_TYPE_CONCENTRATION,
NUM_HARDY_FIELDS
};
/** string to field enum */
static bool string_to_hardy_field(const string & name, hardyFieldName & index) {
if (name=="density")
index = HARDY_DENSITY;
else if (name=="displacement")
index = HARDY_DISPLACEMENT;
else if (name=="momentum")
index = HARDY_MOMENTUM;
else if (name=="velocity")
index = HARDY_VELOCITY;
else if (name=="projected_velocity")
index = HARDY_PROJECTED_VELOCITY;
else if (name=="temperature")
index = HARDY_TEMPERATURE;
else if (name=="kinetic_temperature")
index = HARDY_KINETIC_TEMPERATURE; // temperature from full KE
else if (name=="stress")
index = HARDY_STRESS;
else if (name=="eshelby_stress")
index = HARDY_ESHELBY_STRESS;
else if (name=="cauchy_born_stress")
index = HARDY_CAUCHY_BORN_STRESS;
else if (name=="heat_flux")
index = HARDY_HEAT_FLUX;
else if (name=="energy")
index = HARDY_ENERGY;
else if (name=="number_density")
index = HARDY_NUMBER_DENSITY;
else if (name=="transformed_stress")
index = HARDY_TRANSFORMED_STRESS;
else if (name=="vacancy_concentration")
index = HARDY_VACANCY_CONCENTRATION;
else if (name=="type_concentration")
index = HARDY_TYPE_CONCENTRATION;
else
return false;
return true;
};
/** string to field enum */
static bool hardy_field_to_string(const int & index,string & name)
{
if (index==HARDY_DENSITY)
name = "density";
else if (index==HARDY_DISPLACEMENT)
name = "displacement";
else if (index==HARDY_MOMENTUM)
name = "momentum";
else if (index == HARDY_VELOCITY)
name="velocity";
else if (index == HARDY_PROJECTED_VELOCITY)
name="projected_velocity";
else if (index == HARDY_TEMPERATURE)
name="temperature";
else if (index == HARDY_KINETIC_TEMPERATURE)
name="kinetic_temperature";
else if (index == HARDY_STRESS)
name="stress";
else if (index == HARDY_ESHELBY_STRESS)
name="eshelby_stress";
else if (index == HARDY_CAUCHY_BORN_STRESS)
name="cauchy_born_stress";
else if (index == HARDY_HEAT_FLUX)
name="heat_flux";
else if (index == HARDY_ENERGY)
name="energy";
else if (index == HARDY_NUMBER_DENSITY)
name="number_density";
else if (index == HARDY_TRANSFORMED_STRESS)
name="transformed_stress";
else if (index == HARDY_VACANCY_CONCENTRATION)
name="vacancy_concentration";
else if (index == HARDY_TYPE_CONCENTRATION)
name="type_concentration";
else
return false;
return true;
};
// Forward declarations
class FE_Engine;
class StressCauchyBorn;
class ATC_TransferHardy : public ATC_Transfer {
public:
// constructor
ATC_TransferHardy(std::string groupName, std::string matParamFile = "none");
// destructor
~ATC_TransferHardy();
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
/** post time integration */
virtual void finish();
/** first time substep routines */
virtual void pre_init_integrate();
virtual void init_integrate_velocity(){};
virtual void mid_init_integrate(){};
virtual void init_integrate_position(){};
virtual void post_init_integrate();
/** second time substep routine */
virtual void pre_final_integrate();
virtual void final_integrate(){};
virtual void post_final_integrate();
virtual void set_ghost_atoms() {};
private:
/** pointer to position data : either x_reference or x_current */
double ** xPointer_;
/** data */
map <string, DENS_MAT > hardyData_;
map <string, DENS_MAT > hardyDataOld_;
map <string, DENS_MAT > filteredHardyData_;
DENS_MAT atomicTemperature_;
DENS_MAT atomicKineticTemperature_;
DENS_MAT atomicDensity_;
DENS_MAT atomicMomentum_;
DENS_MAT atomicDisplacement_;
DENS_MAT atomicVelocity_;
DENS_MAT atomicStress_;
DENS_MAT atomicHeat_;
DENS_MAT atomicEnergy_;
/** reference data */
bool setRefPE_;
DENS_MAT nodalRefPotentialEnergy_;
double nodalRefPEvalue_;
bool setRefPEvalue_;
/** contour/boundary integral data */
map < pair<string,string>, const set< PAIR > * > bndyIntegralData_;
map < pair<string,string>, const set< PAIR > * > contourIntegralData_;
/** workset data */
SPAR_MAT kernelShpFcn_;
SPAR_MAT atomicBondTable_;
DENS_MAT vbar_;
DENS_MAT ubar_;
DENS_MAT atomicForceTable_;
DENS_MAT atomicHeatTable_;
DENS_MAT uVariationVelocity_;
vector< SPAR_MAT > gradientTable_;
/** calculation flags */
Array<bool> fieldFlags_;
Array<bool> outputFlags_;
Array<bool> gradFlags_;
Array<bool> rateFlags_;
map<string,int> computes_;
/** calculation flags */
Array<int> fieldSizes_;
/** compute nodal quantities */
void compute_potential_energy(DENS_MAT & nodalPE);
void compute_number_density(DENS_MAT & density);
void compute_mass_density(DENS_MAT & density);
void compute_displacement(DENS_MAT & displacement,
const DENS_MAT & density);
void compute_momentum(DENS_MAT & momentum);
void compute_projected_velocity(DENS_MAT & velocity);
void compute_velocity(DENS_MAT & velocity,
const DENS_MAT & density, const DENS_MAT & momentum);
void compute_variation_velocity(DENS_MAT & velocity,
const DENS_MAT & vI);
void compute_temperature(DENS_MAT & temperature);
void compute_kinetic_temperature(DENS_MAT & temperature);
void compute_stress(DENS_MAT & stress);
void compute_heatflux(DENS_MAT & flux);
void compute_total_energy(DENS_MAT & energy);
void compute_eshelby_stress(DENS_MAT & eshebly_stress,
const DENS_MAT & energy, const DENS_MAT & stress,
const DENS_MAT & displacement_gradient);
void compute_cauchy_born_stress(DENS_MAT & cb_stress,
const DENS_MAT & displacement_gradient);
void compute_transformed_stress(DENS_MAT & stress,
const DENS_MAT & T, const DENS_MAT & displacement_gradient);
void compute_vacancy_concentration(DENS_MAT & vacancy_concentration,
const DENS_MAT & displacement_gradient,
const DENS_MAT & number_density);
void compute_type_concentration(DENS_MAT & type_concentration);
/** compute smooth fields */
void compute_fields(void);
void time_filter_pre (double dt, bool output_now = true);
void time_filter_post(double dt, bool output_now = true);
/** compute boundary integral */
void compute_boundary_integrals(void);
/** output function */
void output();
/** physics specific filter initialization */
void init_filter();
/** kernel */
ATC_HardyKernel* kernelFunction_;
/** mapping of atomic pairs to pair index value */
map< pair< int,int >,int > pairMap_;
int nPairs_;
/** routine to compute pair map */
void compute_pair_map();
/** routine to calculate matrix of Hardy bond functions */
void compute_bond_matrix();
/** routine to calculate matrix of kernel shape functions */
void compute_kernel_matrix();
/** routine to calculate matrix of gradient of Hardy functions */
void compute_gradient_matrix();
/** routine to check pair map */
void check_pair_map();
/** routine to calculate matrix of force & position dyads */
void compute_force_matrix();
/** routine to calculate matrix of heat flux vector components */
void compute_heat_matrix();
/** routine to calculate stress on-the-fly */
void compute_potential_stress(DENS_MAT& stress);
/** routine to calculate force part of the heat flux on-the-fly */
void compute_potential_heatflux(DENS_MAT& flux);
/** periodicity flags and lengths */
int periodicity[3];
double box_bounds[2][3];
double box_length[3];
/** routine to adjust node-pair distances due to periodicity */
void periodicity_correction(DENS_VEC& xaI);
/** routine to set xPointer to xref or xatom */
void set_xPointer();
/** number of atom types */
int nTypes_;
protected:
/** project (number density): given w_\alpha,
w_I = \sum_\alpha N_{I\alpha} w_\alpha */
void project_count_normalized(const DENS_MAT & atomData,
DENS_MAT & nodeData);
/** hardy_project (volume density): given w_\alpha,
w_I = 1/\Omega_I \sum_\alpha N_{I\alpha} w_\alpha
where \Omega_I = \int_{support region of node I} N_{I} dV */
void project_volume_normalized(const DENS_MAT & atomData,
DENS_MAT & nodeData);
/** gradient_compute: given w_I,
w_J = \sum_I N_I'{xJ} \dyad w_I
where N_I'{xJ} is the gradient of the normalized
shape function of node I evaluated at node J */
void gradient_compute(const DENS_MAT & inNodeData,
DENS_MAT & outNodeData);
int nNodesGlobal_;
/** compute kernel shape functions on-the-fly w/o storing N_Ia */
bool kernelOnTheFly_;
/** compute stress or heat flux on-the-fly w/o storing B_Iab */
bool bondOnTheFly_;
/** if false, no coarse velocity is calculated for kernel-based estimates */
bool useAtomicShapeFunctions_;
/** a continuum model to compare to and/or estimate Hardy quantities */
StressCauchyBorn * cauchyBornStress_;
const LammpsInterface * constLammpsInterface_;
Array<TimeFilter *> timeFilters_;
/** check consistency of fieldFlags_ */
void check_fieldFlags_consistency();
};
};
#endif

View File

@ -1,541 +0,0 @@
// ATC_Transfer headers
#include "ATC_TransferThermal.h"
#include "ATC_Error.h"
#include "LammpsInterface.h"
#include "PrescribedDataManager.h"
// Other Headers
#include <vector>
#include <set>
#include <utility>
namespace ATC {
ATC_TransferThermal::ATC_TransferThermal(string groupName,
string matParamFile,
ExtrinsicModelType extrinsicModel)
: ATC_Transfer(),
thermostat_(this),
pmfcOn_(false)
{
// assign default "internal" group
int igroup = lammpsInterface_->find_group(groupName.c_str());
groupbit_ |= lammpsInterface_->group_bit(igroup);
igroups_.insert(igroup);
// Allocate PhysicsModel
create_physics_model(THERMAL, matParamFile);
// create extrinsic physics model
if (extrinsicModel != NO_MODEL) {
extrinsicModelManager_.create_model(extrinsicModel,matParamFile);
}
simTime_ = 0.;
integrationType_ = TimeIntegrator::VERLET;
atomicOutputMask_.insert("temperature");
// set up field data based on physicsModel
physicsModel_->get_num_fields(fieldSizes_,fieldMask_);
// output variable vector info:
// output[1] = total coarse scale thermal energy
// output[2] = average temperature
vectorFlag_ = 1;
sizeVector_ = 2;
globalFreq_ = 1;
extVector_ = 1;
if (extrinsicModel != NO_MODEL)
sizeVector_ += extrinsicModelManager_.size_vector(sizeVector_);
}
ATC_TransferThermal::~ATC_TransferThermal()
{
}
void ATC_TransferThermal::initialize()
{
// Base class initalizations
ATC_Transfer::initialize();
if (!timeFilterManager_.filter_dynamics()) {
DENS_VEC atomicKineticEnergy(nLocal_);
compute_atomic_kinetic_energy(atomicKineticEnergy, lammpsInterface_->vatom());
project_volumetric_quantity(atomicKineticEnergy,fieldNdFiltered_[TEMPERATURE],TEMPERATURE);
fieldNdFiltered_[TEMPERATURE] *= 2.;
}
thermostat_.initialize();
extrinsicModelManager_.initialize();
if (!initialized_) {
// initialize sources based on initial FE temperature
double dt = lammpsInterface_->dt();
prescribedDataMgr_->set_sources(simTime_+.5*dt,sources_);
extrinsicModelManager_.set_sources(fields_,extrinsicSources_);
thermostat_.compute_boundary_flux(fields_);
compute_atomic_sources(fieldMask_,fields_,atomicSources_);
}
if (timeFilterManager_.need_reset()) {
init_filter();
timeFilterManager_.initialize();
}
// reset integration field mask
temperatureMask_.reset(NUM_FIELDS,NUM_FLUX);
temperatureMask_ = false;
for (int i = 0; i < NUM_FLUX; i++)
temperatureMask_(TEMPERATURE,i) = fieldMask_(TEMPERATURE,i);
initialized_ = true;
if (pmfcOn_) {
oldFieldTemp_.reset(nNodes_,1);
}
// read in field data if necessary
if (useRestart_) {
OUTPUT_LIST data;
read_restart_data(restartFileName_,data);
useRestart_ = false;
}
}
void ATC_TransferThermal::init_filter()
{
// NOTE assume total filtered time derivatives are zero
ATC_Transfer::init_filter();
if (integrationType_==TimeIntegrator::VERLET) {
// initialize restricted fields
// NOTE: comment in to initialize fieldRateNdOld_ to current time deriviative
// current assumption is that it is zero
//DenseMatrix<double> atomicPower(nLocal_,1);
//compute_atomic_power(atomicPower,
// lammpsInterface_->vatom(),
// lammpsInterface_->fatom());
//restrict(atomicPower,fieldRateNdOld_[TEMPERATURE]);
//fieldRateNdOld *= 2.;
DENS_MAT atomicKineticEnergy(nLocal_,1);
DENS_MAT nodalAtomicTemperature(nNodes_,1);
compute_atomic_temperature(atomicKineticEnergy,
lammpsInterface_->vatom());
restrict(atomicKineticEnergy, nodalAtomicTemperature);
nodalAtomicTemperature *= 2.;
fieldNdOld_[TEMPERATURE] = nodalAtomicTemperature;
}
if (timeFilterManager_.end_equilibrate()) { // set up correct initial lambda power to enforce initial temperature rate of 0
if (integrationType_==TimeIntegrator::VERLET) {
if (equilibriumStart_) {
if (thermostat_.get_thermostat_type()==Thermostat::FLUX) { // based on FE equation
DENS_MAT vdotflamMat(-2.*fieldRateNdFiltered_[TEMPERATURE]); // note 2 is for 1/2 vdotflam addition
thermostat_.reset_lambda_power(vdotflamMat);
}
else { // based on MD temperature equation
DENS_MAT vdotflamMat(-1.*fieldRateNdFiltered_[TEMPERATURE]);
thermostat_.reset_lambda_power(vdotflamMat);
}
}
}
}
else { // set up space for filtered atomic power
// should set up all data structures common to equilibration and filtering,
// specifically filtered atomic power
if (integrationType_==TimeIntegrator::FRACTIONAL_STEP) {
dot_atomicTemp.reset(nNodes_,1);
dot_atomicTempOld.reset(nNodes_,1);
dot_dot_atomicTemp.reset(nNodes_,1);
dot_dot_atomicTempOld.reset(nNodes_,1);
}
}
}
void ATC_TransferThermal::compute_md_mass_matrix(FieldName thisField,
map<FieldName,DIAG_MAT> & massMats)
{
if (thisField == TEMPERATURE) {
DENS_VEC atomicCapacity(nLocal_);
atomicCapacity = nsd_*(LammpsInterface::instance()->kBoltzmann());
DENS_VEC nodalAtomicCapacity(nNodes_);
restrict_volumetric_quantity(atomicCapacity,nodalAtomicCapacity);
massMats[thisField].reset(nodalAtomicCapacity);
}
}
void ATC_TransferThermal::finish()
{
// base class
ATC_Transfer::finish();
// nothing specific to thermal
}
bool ATC_TransferThermal::modify(int narg, char **arg)
{
bool foundMatch = false;
int argIndx = 0;
// check to see if input is a transfer class command
// check derived class before base class
if (strcmp(arg[argIndx],"transfer")==0) {
argIndx++;
// pass-through to thermostat
if (strcmp(arg[argIndx],"thermal")==0) {
argIndx++;
if (strcmp(arg[argIndx],"control")==0) {
argIndx++;
foundMatch = thermostat_.modify(narg-argIndx,&arg[argIndx]);
}
}
// switch for equilibrium filtering start
/*! \page man_equilibrium_start fix_modify AtC transfer equilibrium_start
\section syntax
fix_modify AtC transfer equilibrium_start <on|off>
\section examples
<TT> fix_modify atc transfer equilibrium_start on </TT> \n
\section description
Starts filtered calculations assuming they start in equilibrium, i.e. perfect finite element force balance.
\section restrictions
only needed before filtering is begun
\section related
see \ref man_time_filter
\section default
on
*/
else if (strcmp(arg[argIndx],"equilibrium_start")==0) {
argIndx++;
if (strcmp(arg[argIndx],"on")==0) {
equilibriumStart_ = true;
foundMatch = true;
}
else if (strcmp(arg[argIndx],"off")==0) {
equilibriumStart_ = false;
foundMatch = true;
}
}
// time integration scheme
/*! \page man_time_integration fix_modify AtC transfer pmfc
\section syntax
fix_modify AtC transfer pmfc <on|off>
\section examples
<TT> fix_modify atc transfer pmfc on </TT>
\section description
Switches the poor man's fractional step algorithm on where the finite element data lags the exact atomic data by one time step for overlap nodes
\section restrictions
\section related
\section default
off
*/
else if (strcmp(arg[argIndx],"pmfc")==0) {
if (integrationType_!=TimeIntegrator::VERLET || timeFilterManager_.filter_dynamics())
throw ATC_Error(0,"Can only use poor man's fractional step with Verlet integration without filtering");
pmfcOn_ = !pmfcOn_;
foundMatch = true;
}
}
// no match, call base class parser
if (!foundMatch) {
foundMatch = ATC_Transfer::modify(narg, arg);
}
return foundMatch;
}
//--------------------------------------------------
// pack_fields
// bundle all allocated field matrices into a list
// for output needs
//--------------------------------------------------
void ATC_TransferThermal::pack_thermal_fields(OUTPUT_LIST & data)
{
data["ddFieldTemp"] = & oldFieldTemp_;
data["lambdaPowerFiltered"] = &(thermostat_.get_filtered_lambda_power());
}
//--------------------------------------------------
// write_restart_file
// bundle matrices that need to be saved and call
// fe_engine to write the file
//--------------------------------------------------
void ATC_TransferThermal::write_restart_data(string fileName, OUTPUT_LIST & data)
{
pack_thermal_fields(data);
ATC_Transfer::write_restart_data(fileName,data);
}
//--------------------------------------------------
// write_restart_file
// bundle matrices that need to be saved and call
// fe_engine to write the file
//--------------------------------------------------
void ATC_TransferThermal::read_restart_data(string fileName, OUTPUT_LIST & data)
{
pack_thermal_fields(data);
ATC_Transfer::read_restart_data(fileName,data);
}
void ATC_TransferThermal::reset_nlocal()
{
ATC_Transfer::reset_nlocal();
thermostat_.reset_nlocal();
}
void ATC_TransferThermal::pre_init_integrate()
{
//ATC_Transfer::pre_init_integrate();
double dt = lammpsInterface_->dt();
double dtLambda = 0.5*dt;
if (pmfcOn_) {
oldFieldTemp_ = fields_[TEMPERATURE];
}
// Apply thermostat to atom velocities
thermostat_.apply_pre_predictor(dtLambda,lammpsInterface_->ntimestep());
// Predict nodal temperatures and time derivatives based on FE data
// 4th order Gear
// switch call based on filter
if (timeFilterManager_.filter_dynamics())
gear1_4_predict(fields_[TEMPERATURE],dot_fields_[TEMPERATURE],
ddot_fields_[TEMPERATURE],dddot_fields_[TEMPERATURE],dt);
else
gear1_3_predict(fields_[TEMPERATURE],dot_fields_[TEMPERATURE],
ddot_fields_[TEMPERATURE],dt);
extrinsicModelManager_.pre_init_integrate();
// fixed values, non-group bcs handled through FE
set_fixed_nodes();
simTime_ += .5*dt;
}
void ATC_TransferThermal::post_init_integrate()
{
// Nothing to do here
//ATC_Transfer::post_init_integrate();
}
void ATC_TransferThermal::pre_final_integrate()
{
ATC_Transfer::pre_final_integrate();
}
void ATC_TransferThermal::post_final_integrate()
{
//ATC_Transfer::post_final_integrate();
double dt = lammpsInterface_->dt();
double dtLambda = dt*0.5;
// predict thermostat contributions
// compute sources based on predicted FE temperature
prescribedDataMgr_->set_sources(simTime_+.5*dt,sources_);
extrinsicModelManager_.set_sources(fields_,extrinsicSources_);
thermostat_.compute_boundary_flux(fields_);
compute_atomic_sources(temperatureMask_,fields_,atomicSources_);
thermostat_.apply_pre_corrector(dtLambda,lammpsInterface_->ntimestep());
// Determine FE contributions to d theta/dt
// Compute atom-integrated rhs
// parallel communication happens within FE_Engine
compute_rhs_vector(temperatureMask_,fields_,rhs_,FE_DOMAIN);
// For flux matching, add 1/2 of "drag" power
thermostat_.add_to_rhs(rhs_);
extrinsicModelManager_.post_final_integrate();
// add in atomic FE contributions for verlet method
if (integrationType_==TimeIntegrator::VERLET) {
DENS_MAT atomicPower(nLocal_,1);
compute_atomic_power(atomicPower,
lammpsInterface_->vatom(),
lammpsInterface_->fatom());
DENS_MAT nodalAtomicPower(nNodes_,1);
restrict_volumetric_quantity(atomicPower,nodalAtomicPower);
nodalAtomicPower *= 2.;
if (timeFilterManager_.filter_variables())
update_filter_implicit(fieldRateNdFiltered_[TEMPERATURE],nodalAtomicPower,dt);
else
fieldRateNdFiltered_[TEMPERATURE] = nodalAtomicPower;
if (!timeFilterManager_.filter_variables() || timeFilterManager_.filter_dynamics())
rhs_[TEMPERATURE] += fieldRateNdFiltered_[TEMPERATURE];
else
rhs_[TEMPERATURE] += nodalAtomicPower;
}
// Finish updating temperature
DENS_MAT R_theta(nNodes_,1);
apply_inverse_mass_matrix(rhs_[TEMPERATURE],TEMPERATURE);
R_theta = (rhs_[TEMPERATURE] - dot_fields_[TEMPERATURE])*dt;
if (timeFilterManager_.filter_dynamics())
gear1_4_correct(fields_[TEMPERATURE],dot_fields_[TEMPERATURE],
ddot_fields_[TEMPERATURE],dddot_fields_[TEMPERATURE],
R_theta,dt);
else
gear1_3_correct(fields_[TEMPERATURE],dot_fields_[TEMPERATURE],
ddot_fields_[TEMPERATURE],R_theta,dt);
// only requirecd for poor man's fractional step
if (pmfcOn_) {
DENS_MAT atomicKineticEnergy(nLocal_,1);
compute_atomic_kinetic_energy(atomicKineticEnergy,
lammpsInterface_->vatom());
DENS_MAT temperatureNd(nNodes_,1);
project_md_volumetric_quantity(atomicKineticEnergy,
temperatureNd,
TEMPERATURE);
temperatureNd *= 2.;
dot_fields_[TEMPERATURE] = 1.0/dt * ( temperatureNd - oldFieldTemp_);
fields_[TEMPERATURE] = temperatureNd;
}
// fix nodes, non-group bcs applied through FE
set_fixed_nodes();
// compute sources based on final FE updates
prescribedDataMgr_->set_sources(simTime_+.5*dt,sources_);
extrinsicModelManager_.set_sources(fields_,extrinsicSources_);
thermostat_.compute_boundary_flux(fields_);
compute_atomic_sources(temperatureMask_,fields_,atomicSources_);
// apply corrector phase of thermostat
thermostat_.apply_post_corrector(dtLambda,lammpsInterface_->ntimestep());
// add in MD contributions to time derivative
// update filtered temperature
DENS_MAT atomicKineticEnergy(nLocal_,1);
compute_atomic_kinetic_energy(atomicKineticEnergy,
lammpsInterface_->vatom());
DENS_MAT temperatureNd(nNodes_,1);
project_md_volumetric_quantity(atomicKineticEnergy,temperatureNd,TEMPERATURE);
temperatureNd *= 2.;
if (!timeFilterManager_.filter_dynamics())
fieldNdFiltered_[TEMPERATURE] = temperatureNd;
else if (integrationType_==TimeIntegrator::VERLET)
update_filter_implicit(fieldNdFiltered_[TEMPERATURE],temperatureNd,dt);
simTime_ += .5*dt;
output();
}
//--------------------------------------------------------------------
// compute_vector
//--------------------------------------------------------------------
// this is for direct output to lammps thermo
double ATC_TransferThermal::compute_vector(int n)
{
// output[1] = total coarse scale thermal energy
// output[2] = average temperature
double mvv2e = lammpsInterface_->mvv2e(); // convert to lammps energy units
if (n == 0) {
Array<FieldName> mask(1);
FIELDS energy;
mask(0) = TEMPERATURE;
feEngine_->compute_energy(mask, // NOTE make this a base class function
fields_,
physicsModel_,
elementToMaterialMap_,
energy,
&elementMask_);
double phononEnergy = mvv2e * energy[TEMPERATURE].col_sum();
return phononEnergy;
}
else if (n == 1) {
double aveT = fields_[TEMPERATURE].col_sum()/nNodes_;
return aveT;
}
else if (n > 1) {
double extrinsicValue = extrinsicModelManager_.compute_vector(n);
return extrinsicValue;
}
return 0.;
}
//--------------------------------------------------------------------
// output
//--------------------------------------------------------------------
void ATC_TransferThermal::output()
{
double dt = lammpsInterface_->dt();
double step = (double) lammpsInterface_->ntimestep();
++stepCounter_;
if ((outputFrequency_ > 0)
&& ((stepCounter_ ==1) || (stepCounter_ % outputFrequency_ == 0)) ) {
OUTPUT_LIST output_data;
// Add some outputs only on Proc 0
if (lammpsInterface_->comm_rank() == 0) {
// base class output
ATC_Transfer::output();
// global data
double T_mean = fields_[TEMPERATURE].col_sum(0)/nNodes_;
feEngine_->add_global("temperature_mean", T_mean);
double T_stddev = fields_[TEMPERATURE].col_stdev(0);
feEngine_->add_global("temperature_std_dev", T_stddev);
double Ta_mean = fieldNdFiltered_[TEMPERATURE].col_sum(0)/nNodes_;
feEngine_->add_global("atomic_temperature_mean", Ta_mean);
double Ta_stddev = fieldNdFiltered_[TEMPERATURE].col_stdev(0);
feEngine_->add_global("atomic_temperature_std_dev", Ta_stddev);
// mesh data
output_data["nodalAtomicTemperature"] = & fieldNdFiltered_[TEMPERATURE];
output_data["dot_temperature"] = & dot_fields_[TEMPERATURE];
output_data["ddot_temperature"] = & ddot_fields_[TEMPERATURE];
output_data["nodalAtomicPower"] = & fieldRateNdFiltered_[TEMPERATURE];
// auxilliary data
thermostat_.output(dt,output_data);
extrinsicModelManager_.output(dt,output_data);
}
// Output fe data on proc 0
if (lammpsInterface_->comm_rank() == 0) {
feEngine_->write_data(simTime_, fields_, & output_data);
}
}
if ((outputFrequencyAtom_ > 0)
&& ((stepCounter_ ==1) || (stepCounter_ % outputFrequencyAtom_ == 0)) )
atomic_output();
}
void ATC_TransferThermal::set_ghost_atoms()
{
// Nothing to do here
}
};

View File

@ -1,96 +0,0 @@
/** ATC_TransferThermal : a class for atom-continuum transfers &
control involving heat transport */
#ifndef ATC_TRANSFER_THERMAL_H
#define ATC_TRANSFER_THERMAL_H
// ATC_Transfer headers
#include "ATC_Transfer.h"
#include "Thermostat.h"
#include "TimeIntegrator.h"
// Other headers
#include <map>
namespace ATC {
class ATC_TransferThermal : public ATC_Transfer {
public:
// constructor
ATC_TransferThermal(std::string groupName, std::string matParamFile,
ExtrinsicModelType extrinsic = NO_MODEL);
// destructor
~ATC_TransferThermal();
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
/** post time integration */
virtual void finish();
/** first time substep routines */
virtual void pre_init_integrate();
virtual void mid_init_integrate(){};
virtual void post_init_integrate();
/** second time substep routine */
virtual void pre_final_integrate();
virtual void post_final_integrate();
/** compute vector for output */
virtual double compute_vector(int n);
private:
/** sets the position/velocity of the ghost atoms */
virtual void set_ghost_atoms();
/** resets any arrays associated with local atom count */
virtual void reset_nlocal();
/** compute the mass matrix components coming from MD integration */
virtual void compute_md_mass_matrix(FieldName thisField,
map<FieldName,DIAG_MAT> & massMats);
/** time integration flag and access method */
TimeIntegrator::TimeIntegrationType integrationType_;
virtual TimeIntegrator::TimeIntegrationType get_integration_type(){return integrationType_;};
/** fractional step auxilliary storage */
DENS_MAT delTheta;
DENS_MAT delThetaV;
DENS_MAT dot_atomicTemp;
DENS_MAT dot_atomicTempOld;
DENS_MAT dot_dot_atomicTemp;
DENS_MAT dot_dot_atomicTempOld;
/** physics specific filter initialization */
void init_filter();
/** field mask for velocity integration */
Array2D<bool> temperatureMask_;
void output();
/** thermostat manager */
Thermostat thermostat_;
// Data for poor man's fractional step
bool pmfcOn_;
DENS_MAT oldFieldTemp_;
// Add in fields for restarting
virtual void read_restart_data(string fileName_, OUTPUT_LIST & data);
virtual void write_restart_data(string fileName_, OUTPUT_LIST & data);
void pack_thermal_fields(OUTPUT_LIST & data);
};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,207 +0,0 @@
#ifndef ATC_TYPEDEFS_H
#define ATC_TYPEDEFS_H
#include <set>
using std::pair;
using std::set;
#include "Array.h"
#include "Array2D.h"
#include "XT_Function.h"
#include "MatrixLibrary.h"
#include "ATC_Error.h"
namespace ATC
{
/** Material types */
enum FieldName { // Intrinsic Fields
TEMPERATURE=0,
DISPLACEMENT,
VELOCITY,
MASS_DENSITY,
CHARGE_DENSITY,
ELECTRON_DENSITY, // Extrinsic Fields
ELECTRON_VELOCITY,
ELECTRON_TEMPERATURE,
ELECTRIC_POTENTIAL,
NUM_FIELDS
};
/** solver types */
enum SolverType { DIRECT=0, ITERATIVE};
/** physics types */
enum PhysicsType
{
NO_PHYSICS=0, // for post-processing only
THERMAL,
ELASTIC,
THERMO_ELASTIC,
SPECIES
};
/** rhs types */
enum FluxType
{
FLUX = 0, // has a source weighted by gradient of shape function
SOURCE, // has a source term weighted by the shape function
PRESCRIBED_SOURCE, // has a prescribed source term
EXTRINSIC_SOURCE, // has an extrinsic source term
NUM_FLUX
};
/** stiffness/ derivative of rhs types */
enum StiffnessType
{
BB_STIFFNESS = 0,
NN_STIFFNESS,
BN_STIFFNESS,
NB_STIFFNESS,
NUM_STIFFNESS
};
/** typedefs for N and B integrand functions */
typedef DenseMatrix<double> FIELD;
typedef vector<DenseMatrix<double> > GRAD_FIELD;
typedef map<FieldName, DenseMatrix<double> > FIELDS;
typedef map<FieldName, vector<DenseMatrix<double> > > GRAD_FIELDS;
/** typedefs for input/output */
typedef map<string, Matrix<double>*> OUTPUT_LIST;
/** misc typedefs */
typedef pair<int, int> PAIR;
typedef map<FieldName, map<PAIR, Array<XT_Function*> > > SURFACE_SOURCE;
typedef map<FieldName, Array2D<XT_Function *> > VOLUME_SOURCE;
typedef vector<SparseMatrix<double> > GRAD_SHPFCN;
/** typedefs for FE_Mesh */
typedef map<string, set<int > > NODE_SET_MAP;
typedef map<string, set<int > > ELEMENT_SET_MAP;
typedef map<string, set<PAIR> > FACE_SET_MAP;
/** string to index */
static bool string_to_index(const string & dim, int & index, int & sgn)
{
char dir;
if (dim.empty()) return false;
sgn = (dim[0] == '-') ? -1 : 1;
dir = dim[dim.size()-1]; // dir is last character
if (dir == 'x') index = 0;
else if (dir == 'y') index = 1;
else if (dir == 'z') index = 2;
else return false;
return true;
};
/** string to index */
static string index_to_string(const int &index)
{
if (index==0) return "x";
else if (index==1) return "y";
else if (index==2) return "z";
return "unknown";
};
/** string to index */
static bool string_to_index(const string &dim, int &index)
{
if (dim=="x")
index = 0;
else if (dim=="y")
index = 1;
else if (dim=="z")
index = 2;
else
return false;
return true;
};
/** field name enum to string */
static string field_to_string(const FieldName index)
{
switch (index) {
case TEMPERATURE:
return "temperature";
case DISPLACEMENT:
return "displacement";
case VELOCITY:
return "velocity";
case MASS_DENSITY:
return "mass_density";
case CHARGE_DENSITY:
return "charge_density";
case ELECTRON_DENSITY:
return "electron_density";
case ELECTRON_VELOCITY:
return "electron_velocity";
case ELECTRON_TEMPERATURE:
return "electron_temperature";
case ELECTRIC_POTENTIAL:
return "electric_potential";
default:
throw ATC_Error(0,"field not found in field_to_string");
}
};
/** string to field enum */
static FieldName string_to_field(const string & name)
{
if (name=="temperature")
return TEMPERATURE;
else if (name=="displacement")
return DISPLACEMENT;
else if (name=="velocity")
return VELOCITY;
else if (name=="mass_density")
return MASS_DENSITY;
else if (name=="charge_density")
return CHARGE_DENSITY;
else if (name=="electron_density")
return ELECTRON_DENSITY;
else if (name=="electron_velocity")
return ELECTRON_VELOCITY;
else if (name=="electron_temperature")
return ELECTRON_TEMPERATURE;
else if (name=="electric_potential")
return ELECTRIC_POTENTIAL;
else
throw ATC_Error(0,name + " is not a valid field");
};
static bool is_intrinsic(const FieldName & field_enum)
{
if (field_enum==TEMPERATURE
|| field_enum==DISPLACEMENT
|| field_enum==VELOCITY
|| field_enum==MASS_DENSITY
|| field_enum==CHARGE_DENSITY) return true;
else return false;
};
static void print_mask(const Array2D<bool> & rhsMask)
{
for (int i = 0; i < NUM_FIELDS; i++) {
FieldName field = (FieldName) i;
string name = field_to_string(field);
if (rhsMask(field,FLUX)
|| rhsMask(field,SOURCE)
|| rhsMask(field,PRESCRIBED_SOURCE)
|| rhsMask(field,EXTRINSIC_SOURCE)) {
cout << "RHS_MASK: " << name;
if (rhsMask(field,FLUX)) cout << " flux";
if (rhsMask(field,SOURCE)) cout << " source";
if (rhsMask(field,PRESCRIBED_SOURCE)) cout << " prescribed_src";
if (rhsMask(field,EXTRINSIC_SOURCE)) cout << " extrinsic_src";
cout << "\n";
}
}
}
}
#endif

View File

@ -1,170 +0,0 @@
#ifndef ARRAY_H
#define ARRAY_H
//#include<stdlib.h>
//#include<stdio.h>
#include<iostream>
#include<string>
#include<cstdio>
template<typename T>
class Array {
public:
Array();
Array(int len);
Array(const Array<T>& A);
~Array();
// Resize and reinitialize the array
void reset(int len);
// Access method to get the element i:
T& operator() (int i);
// Access method to get the element i:
const T& operator() (int i) const;
// Assignment
Array<T>& operator= (const Array<T> &other);
Array<T>& operator= (const T &value);
// Get length of array
int get_length() const;
int size() const;
// Do I have this element?
bool has_member(T val) const;
// Return pointer to internal data
const T* get_data() const;
T* get_ptr() const;
// print
void print(std::string name = "") const;
// Dump templated type to disk; operation not safe for all types
void write_restart(FILE *f) const;
private:
int len_;
T *data_;
};
template<typename T>
Array<T>::Array(void) {
len_ = 0;
data_ = NULL;
}
template<typename T>
Array<T>::Array(int len) {
len_ = len;
data_ = new T[len_];
}
template<typename T>
Array<T>::Array(const Array<T>& A) {
len_ = A.len_;
if (A.data_==NULL)
data_ = NULL;
else {
data_ = new T[len_];
for(int i=0;i<len_;i++)
data_[i] = A.data_[i];
}
}
template<typename T>
void Array<T>::reset(int len) {
if (len_ == len) { // no size change; don't realloc memory
return;
}
else { // size change, realloc memory
len_ = len;
if (data_ != NULL)
delete[] data_;
if (len_ > 0)
data_ = new T[len_];
else {
data_ = NULL;
len_ = 0;
}
}
}
template<typename T>
T& Array<T>::operator() (int i) {
// Array bounds checking
return data_[i];
}
template<typename T>
Array<T>& Array<T>::operator= (const Array<T> &other) {
if (data_ == NULL) { // initialize my internal storage to match LHS
len_ = other.len_;
if (other.data_==NULL)
data_ = NULL;
else
data_ = new T[len_];
}
for(int i=0;i<len_;i++)
data_[i] = other.data_[i];
return *this;
}
template<typename T>
Array<T>& Array<T>::operator= (const T &value) {
for(int i=0;i<len_;i++)
data_[i] = value;
return *this;
}
template<typename T>
const T& Array<T>::operator() (int i) const {
// Array bounds checking
return data_[i];
}
template<typename T>
int Array<T>::get_length(void) const {
return len_;
}
template<typename T>
int Array<T>::size(void) const {
return len_;
}
template<typename T>
bool Array<T>::has_member(T val) const {
int i;
bool retval = false;
for(i=0;i<len_;i++)
if (val == data_[i])
retval = true;
return(retval);
}
template<typename T>
void Array<T>::write_restart(FILE *f) const {
fwrite(&len_,sizeof(int),1,f);
if (len_ > 0)
fwrite(data_,sizeof(T),len_,f);
}
template<typename T>
const T* Array<T>::get_data() const {
return data_;
}
template<typename T>
T* Array<T>::get_ptr() const {
return data_;
}
template<typename T>
Array<T>::~Array() {
if (data_ != NULL)
delete[] data_;
}
template<typename T>
void Array<T>::print(std::string name) const {
std::cout << "------- Begin "<<name<<" -----------------\n";
if (data_ != NULL) {
for(int i=0;i<len_;i++) std::cout << data_[i] << " ";
std::cout << "\n";
}
std::cout << "\n------- End "<<name<<" -------------------\n";
}
#endif // Array.h

View File

@ -1,172 +0,0 @@
#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <string>
#include <iostream>
#include <cstdio>
template<typename T>
class Array2D {
public:
Array2D();
Array2D(int nrows, int ncols);
Array2D(const Array2D<T>& A); // copy constructor
~Array2D();
// Resize and reinitalize matrix
void reset(int nrows, int ncols);
// Access method to get the (i,j) element:
T& operator() (int i, int j);
// Access method to get the (i,j) element:
const T& operator() (int i, int j) const;
// Copy operator
Array2D<T>& operator= (const Array2D<T>& other);
// assignment operator
Array2D<T>& operator= (const T other);
// Get size of Array2D
int nRows() const;
int nCols() const;
// Do I have this element?
bool has_member(T val) const;
// print
void print(std::string name ="") const;
// Dump templated type to disk; operation not safe for all types
void write_restart(FILE *f) const;
private:
int nrows_, ncols_;
T *data_;
};
template<typename T>
Array2D<T>::Array2D() {
nrows_ = 0;
ncols_ = 0;
data_ = NULL;
}
template<typename T>
Array2D<T>::Array2D(int nrows, int ncols) {
nrows_ = nrows;
ncols_ = ncols;
data_ = new T[nrows_ * ncols_];
}
template<typename T>
Array2D<T>::Array2D(const Array2D<T>& A) {
nrows_ = A.nrows_;
ncols_ = A.ncols_;
if (A.data_==NULL)
data_ = NULL;
else {
data_ = new T[nrows_ * ncols_];
for(int i=0;i<nrows_*ncols_;i++)
data_[i] = A.data_[i];
}
}
template<typename T>
void Array2D<T>::reset(int nrows, int ncols) {
if (nrows_ == nrows && ncols_ == ncols) { // no size change; don't realloc memory
return;
}
else { // size changed; realloc memory
nrows_ = nrows;
ncols_ = ncols;
if (data_ != NULL)
delete [] data_;
if (ncols_ > 0 && nrows_ > 0)
data_ = new T[nrows_ * ncols_];
else {
data_ = NULL;
nrows_ = 0;
ncols_ = 0;
}
}
}
template<typename T>
T& Array2D<T>::operator() (int row, int col) {
// Array bounds checking
return data_[col*nrows_ + row];
}
template<typename T>
const T& Array2D<T>::operator() (int row, int col) const {
// Array bounds checking
return data_[col*nrows_ + row];
}
template<typename T>
Array2D<T>& Array2D<T>::operator= (const Array2D<T>& other) {
if (data_ == NULL) { // initialize my internal storage to match LHS
nrows_ = other.nrows_;
ncols_ = other.ncols_;
if (other.data_==NULL)
data_ = NULL;
else
data_ = new T[nrows_ * ncols_];
}
for(int i=0;i<nrows_*ncols_;i++)
data_[i] = other.data_[i];
return *this;
}
template<typename T>
Array2D<T>& Array2D<T>::operator= (const T other) {
for(int i=0;i<nrows_*ncols_;i++)
data_[i] = other;
return *this;
}
template<typename T>
int Array2D<T>::nRows() const {
return nrows_;
}
template<typename T>
int Array2D<T>::nCols() const {
return ncols_;
}
template<typename T>
bool Array2D<T>::has_member(T val) const {
int i;
bool retval = false;
for(i=0;i<nrows_*ncols_;i++)
if (val == data_[i])
retval = true;
return(retval);
}
template<typename T>
void Array2D<T>::write_restart(FILE *f) const {
fwrite(&nrows_,sizeof(int),1,f);
fwrite(&ncols_,sizeof(int),1,f);
if (nrows_*ncols_ > 0)
fwrite(data_,sizeof(T),nrows_*ncols_,f);
}
template<typename T>
Array2D<T>::~Array2D() {
if (data_ != NULL)
delete[] data_;
}
template<typename T>
void Array2D<T>::print(std::string name) const {
std::cout << "------- Begin "<<name<<" -----------------\n";
if (data_ != NULL) {
for(int col=0;col<ncols_;col++) {
for(int row=0;row<nrows_;row++) {
std::cout << data_[col*nrows_ + row] << " ";
}
std::cout << "\n";
}
}
std::cout << "\n------- End "<<name<<" -------------------\n";
}
#endif // Array2D.h

View File

@ -1,419 +0,0 @@
// ATC_Transfer Headers
#include "AtomicRegulator.h"
#include "CG.h"
#include "ATC_Error.h"
#include "PrescribedDataManager.h"
#include "TimeIntegrator.h"
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class AtomicRegulator
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
AtomicRegulator::AtomicRegulator(ATC_Transfer * atcTransfer) :
atcTransfer_(atcTransfer),
howOften_(1),
timeFilter_(NULL),
regulatorMethod_(NULL),
boundaryIntegrationType_(ATC_Transfer::NO_QUADRATURE),
nNodes_(0),
nsd_(0),
nLocal_(0),
needReset_(true),
resetData_(true)
{
// nothing to do
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
AtomicRegulator::~AtomicRegulator()
{
if (timeFilter_)
delete timeFilter_;
destroy();
}
//--------------------------------------------------------
// destroy:
// deallocates all memory
//--------------------------------------------------------
void AtomicRegulator::destroy()
{
if (regulatorMethod_)
delete regulatorMethod_;
}
//--------------------------------------------------------
// modify:
// parses and adjusts controller state based on
// user input, in the style of LAMMPS user input
//--------------------------------------------------------
bool AtomicRegulator::modify(int narg, char **arg)
{
bool foundMatch = false;
return foundMatch;
}
//--------------------------------------------------------
// reset_nlocal:
// resizes lambda force if necessary
//--------------------------------------------------------
void AtomicRegulator::reset_nlocal()
{
nLocal_ = atcTransfer_->get_nlocal();
if (nLocal_ > 0)
lambdaForce_.reset(nLocal_,nsd_);
if (regulatorMethod_)
regulatorMethod_->reset_nlocal();
}
//--------------------------------------------------------
// reset_data:
// sets up storage for all data structures
//--------------------------------------------------------
void AtomicRegulator::reset_data()
{
nNodes_ = atcTransfer_->get_nNodes();
nsd_ = atcTransfer_->get_nsd();
if (timeFilter_)
delete timeFilter_;
timeFilter_ = NULL;
resetData_ = false;
}
//--------------------------------------------------------
// reset_method:
// sets up methods, if necessary
//--------------------------------------------------------
void AtomicRegulator::reset_method()
{
// set up defaults for anything that didn't get set
if (!regulatorMethod_)
regulatorMethod_ = new RegulatorMethod(this);
if (!timeFilter_)
timeFilter_ = (atcTransfer_->get_time_filter_manager())->construct();
needReset_ = false;
}
//--------------------------------------------------------
// initialize:
// sets up methods before a run
//--------------------------------------------------------
void AtomicRegulator::initialize()
{
// make sure consistent boundary integration is being used
atcTransfer_->set_boundary_integration_type(boundaryIntegrationType_);
// reset data related to local atom count
reset_nlocal();
}
//--------------------------------------------------------
// output:
// pass through to appropriate output methods
//--------------------------------------------------------
void AtomicRegulator::output(double dt, OUTPUT_LIST & outputData) const
{
regulatorMethod_->output(dt,outputData);
}
//--------------------------------------------------------
// apply_pre_predictor:
// applies the controller in the pre-predictor
// phase of the time integrator
//--------------------------------------------------------
void AtomicRegulator::apply_pre_predictor(double dt, int timeStep)
{
if (timeStep % howOften_==0) // apply full integration scheme, including filter
regulatorMethod_->apply_pre_predictor(dt);
}
//--------------------------------------------------------
// apply_mid_predictor:
// applies the controller in the mid-predictor
// phase of the time integrator
//--------------------------------------------------------
void AtomicRegulator::apply_mid_predictor(double dt, int timeStep)
{
if (timeStep % howOften_==0) // apply full integration scheme, including filter
regulatorMethod_->apply_mid_predictor(dt);
}
//--------------------------------------------------------
// apply_post_predictor:
// applies the controller in the post-predictor
// phase of the time integrator
//--------------------------------------------------------
void AtomicRegulator::apply_post_predictor(double dt, int timeStep)
{
if (timeStep % howOften_==0) // apply full integration scheme, including filter
regulatorMethod_->apply_post_predictor(dt);
}
//--------------------------------------------------------
// apply_pre_corrector:
// applies the controller in the pre-corrector phase
// of the time integrator
//--------------------------------------------------------
void AtomicRegulator::apply_pre_corrector(double dt, int timeStep)
{
if (timeStep % howOften_==0) // apply full integration scheme, including filter
regulatorMethod_->apply_pre_corrector(dt);
}
//--------------------------------------------------------
// apply_post_corrector:
// applies the controller in the post-corrector phase
// of the time integrator
//--------------------------------------------------------
void AtomicRegulator::apply_post_corrector(double dt, int timeStep)
{
if (timeStep % howOften_==0) // apply full integration scheme, including filter
regulatorMethod_->apply_post_corrector(dt);
}
//--------------------------------------------------------
// compute_boundary_flux:
// computes the boundary flux to be consistent with
// the controller
//--------------------------------------------------------
void AtomicRegulator::compute_boundary_flux(FIELDS & fields)
{
regulatorMethod_->compute_boundary_flux(fields);
}
//--------------------------------------------------------
// add_to_rhs:
// adds any controller contributions to the FE rhs
//--------------------------------------------------------
void AtomicRegulator::add_to_rhs(FIELDS & rhs)
{
regulatorMethod_->add_to_rhs(rhs);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class RegulatorMethod
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
RegulatorMethod::RegulatorMethod(AtomicRegulator * atomicRegulator) :
atomicRegulator_(atomicRegulator),
atcTransfer_(atomicRegulator->get_atc_transfer()),
fieldMask_(NUM_FIELDS,NUM_FLUX),
boundaryFlux_(atcTransfer_->get_boundary_fluxes()),
nNodes_(atomicRegulator_->get_nNodes())
{
fieldMask_ = false;
}
//--------------------------------------------------------
// compute_boundary_flux
// default computation of boundary flux based on
// finite
//--------------------------------------------------------
void RegulatorMethod::compute_boundary_flux(FIELDS & fields)
{
atcTransfer_->compute_boundary_flux(fieldMask_,
fields,
boundaryFlux_);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class RegulatorShapeFunction
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
RegulatorShapeFunction::RegulatorShapeFunction(AtomicRegulator * atomicRegulator) :
RegulatorMethod(atomicRegulator),
maxIterations_(50),
tolerance_(1.e-10),
nNodeOverlap_(atcTransfer_->get_nNode_overlap()),
nsd_(atomicRegulator_->get_nsd()),
lambda_(atomicRegulator_->get_lambda()),
shapeFunctionMatrix_(atcTransfer_->get_nhat_overlap()),
glcMatrixTemplate_(atcTransfer_->get_m_t_template()),
shapeFunctionGhost_(atcTransfer_->get_shape_function_ghost_overlap()),
internalToAtom_(atcTransfer_->get_internal_to_atom_map()),
internalToOverlapMap_(atcTransfer_->get_atom_to_overlap_map()),
ghostToAtom_(atcTransfer_->get_ghost_to_atom_map()),
nLocal_(0),
nLocalLambda_(0),
nLocalGhost_(0)
{
if (atcTransfer_->use_lumped_lambda_solve())
matrixSolver_ = new LambdaMatrixSolverLumped(glcMatrixTemplate_,
shapeFunctionMatrix_,
maxIterations_,
tolerance_);
else
matrixSolver_ = new LambdaMatrixSolverCg(glcMatrixTemplate_,
shapeFunctionMatrix_,
maxIterations_,
tolerance_);
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
RegulatorShapeFunction::~RegulatorShapeFunction()
{
if (matrixSolver_)
delete matrixSolver_;
}
//--------------------------------------------------------
// solve_for_lambda
// solves matrix equation for lambda using given rhs
//--------------------------------------------------------
void RegulatorShapeFunction::solve_for_lambda(const DENS_MAT & rhs)
{
// set up weighting matrix
DIAG_MAT weights;
if (nLocalLambda_>0)
set_weights(weights);
// solve on overlap nodes
DENS_MAT rhsOverlap(nNodeOverlap_,rhs.nCols());
atcTransfer_->map_unique_to_overlap(rhs, rhsOverlap);
DENS_MAT lambdaOverlap(nNodeOverlap_,lambda_.nCols());
for (int i = 0; i < rhs.nCols(); i++) {
CLON_VEC tempRHS(rhsOverlap,CLONE_COL,i);
CLON_VEC tempLambda(lambdaOverlap,CLONE_COL,i);
matrixSolver_->execute(tempRHS,tempLambda,weights,atcTransfer_);
}
// map solution back to all nodes
atcTransfer_->map_overlap_to_unique(lambdaOverlap,lambda_);
}
//--------------------------------------------------------
// reset_nlocal:
// resets data dependent on local atom count
//--------------------------------------------------------
void RegulatorShapeFunction::reset_nlocal()
{
RegulatorMethod::reset_nlocal();
nLocal_ = atomicRegulator_->get_nLocal();
nLocalLambda_ = atcTransfer_->get_nlocal_lambda();
nLocalGhost_ = atcTransfer_->get_nlocal_ghost();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class LambdaMatrixSolver
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab references to necessary data
//--------------------------------------------------------
LambdaMatrixSolver::LambdaMatrixSolver(SPAR_MAT & matrixTemplate, SPAR_MAT & shapeFunctionMatrix, int maxIterations, double tolerance) :
matrixTemplate_(matrixTemplate),
shapeFunctionMatrix_(shapeFunctionMatrix),
maxIterations_(maxIterations),
tolerance_(tolerance)
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class LambdaMatrixSolverLumped
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab references to necessary data
//--------------------------------------------------------
LambdaMatrixSolverLumped::LambdaMatrixSolverLumped(SPAR_MAT & matrixTemplate, SPAR_MAT & shapeFunctionMatrix, int maxIterations, double tolerance) :
LambdaMatrixSolver(matrixTemplate,shapeFunctionMatrix,maxIterations,tolerance)
{
// do nothing
}
void LambdaMatrixSolverLumped::execute(VECTOR & rhs, VECTOR & lambda, DIAG_MAT & weights, ATC_Transfer * atcTransfer)
{
// form matrix : sum_a N_Ia * W_a * N_Ja
SPAR_MAT myMatrixLocal(matrixTemplate_);
if (weights.nRows()>0)
myMatrixLocal.WeightedLeastSquares(shapeFunctionMatrix_,weights);
// swap contributions
SPAR_MAT myMatrix(matrixTemplate_);
LammpsInterface::instance()->allsum(myMatrixLocal.get_ptr(),
myMatrix.get_ptr(), myMatrix.size());
DIAG_MAT lumpedMatrix(myMatrix.nRows(),myMatrix.nCols());
for (int i = 0; i < myMatrix.nRows(); i++)
for (int j = 0; j < myMatrix.nCols(); j++)
lumpedMatrix(i,i) += myMatrix(i,j);
// solve lumped equation
for (int i = 0; i < rhs.size(); i++)
lambda(i) = rhs(i)/lumpedMatrix(i,i);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class LambdaMatrixSolverCg
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab references to necessary data
//--------------------------------------------------------
LambdaMatrixSolverCg::LambdaMatrixSolverCg(SPAR_MAT & matrixTemplate, SPAR_MAT & shapeFunctionMatrix, int maxIterations, double tolerance) :
LambdaMatrixSolver(matrixTemplate,shapeFunctionMatrix,maxIterations,tolerance)
{
// do nothing
}
void LambdaMatrixSolverCg::execute(VECTOR & rhs, VECTOR & lambda, DIAG_MAT & weights, ATC_Transfer * atcTransfer)
{
// form matrix : sum_a N_Ia * W_a * N_Ja
SPAR_MAT myMatrixLocal(matrixTemplate_);
if (weights.nRows()>0)
myMatrixLocal.WeightedLeastSquares(shapeFunctionMatrix_,weights);
// swap contributions
SPAR_MAT myMatrix(matrixTemplate_);
LammpsInterface::instance()->allsum(myMatrixLocal.get_ptr(),
myMatrix.get_ptr(), myMatrix.size());
DIAG_MAT preConditioner = myMatrix.get_diag();
int myMaxIt = 2*myMatrix.nRows(); // note could also use the fixed parameter
double myTol = tolerance_;
int convergence = CG(myMatrix, lambda, rhs, preConditioner, myMaxIt, myTol);
// error if didn't converge
if (convergence>0)
throw ATC_Error(0,"CG solver did not converge in LambdaMatrixSolverCg::execute()");
}
};

View File

@ -1,394 +0,0 @@
/** Atomic Regulator : a base class class for atom-continuum control */
#ifndef ATOMICREGULATOR_H
#define ATOMICREGULATOR_H
// ATC_Transfer headers
#include "ATC_Transfer.h"
// other headers
#include <map>
#include <set>
namespace ATC {
// forward declarations
class TimeFilter;
class RegulatorMethod;
class LambdaMatrixSolver;
/**
* @class AtomicRegulator
* @brief Base class for atom-continuum control
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class AtomicRegulator
//--------------------------------------------------------
//--------------------------------------------------------
class AtomicRegulator {
public:
// constructor
AtomicRegulator(ATC_Transfer * atcTransfer);
// destructor
~AtomicRegulator();
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
/** add output information */
virtual void output(double dt, OUTPUT_LIST & outputData) const;
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal();
// application steps
/** apply the thermostat in the pre-predictor phase */
virtual void apply_pre_predictor(double dt, int timeStep);
/** apply the thermostat in the mid-predictor phase */
virtual void apply_mid_predictor(double dt, int timeStep);
/** apply the thermostat in the post-predictor phase */
virtual void apply_post_predictor(double dt, int timeStep);
/** apply the thermostat in the pre-correction phase */
virtual void apply_pre_corrector(double dt, int timeStep);
/** apply the thermostat in the post-correction phase */
virtual void apply_post_corrector(double dt, int timeStep);
// coupling to FE state
/** compute the thermal boundary flux, must be consistent with thermostat */
virtual void compute_boundary_flux(FIELDS & fields);
/** add contributions (if any) to the finite element right-hand side */
virtual void add_to_rhs(FIELDS & rhs);
// data access, intended for method objects
/** return value of lambda */
DENS_MAT & get_lambda() {return lambda_;};
/** return the atomic force defined by lambda */
DENS_MAT & get_lambda_force() {return lambdaForce_;};
/** access for ATC transfer */
ATC_Transfer * get_atc_transfer() {return atcTransfer_;};
/** access for time filter */
TimeFilter * get_time_filter() {return timeFilter_;};
/** access for number of nodes */
int get_nNodes() {return nNodes_;};
/** access for number of spatial dimensions */
int get_nsd() {return nsd_;};
/** access for number of local atoms */
int get_nLocal() {return nLocal_;};
/** access for boundary integration methods */
ATC_Transfer::BoundaryIntegrationType get_boundary_integration_type()
{return boundaryIntegrationType_;};
/** access for boundary face sets */
const set< pair<int,int> > * get_face_sets()
{ return boundaryFaceSet_;};
protected:
void destroy();
/** point to atc_transfer object */
ATC_Transfer * atcTransfer_;
/** how often in number of time steps thermostat is applied */
int howOften_;
// reset/reinitialize flags
/** flag to see if data requires a reset */
bool resetData_;
/** flag to reset data */
bool needReset_;
/** resets data structures */
void reset_data();
/** reinitialize method */
void reset_method();
// regulator data
/** control parameter */
DENS_MAT lambda_;
/** lambda force computed by controller */
DENS_MAT lambdaForce_;
/** number of nodes */
int nNodes_;
/** number of spatial dimensions */
int nsd_;
/** number of local atoms */
int nLocal_;
// method pointers
/** time filtering object */
TimeFilter * timeFilter_;
/** sets up and solves the thermostat equations */
RegulatorMethod * regulatorMethod_;
// boundary flux information
ATC_Transfer::BoundaryIntegrationType boundaryIntegrationType_;
const set< pair<int,int> > * boundaryFaceSet_;
private:
// DO NOT define this
AtomicRegulator();
};
/**
* @class RegulatorMethod
* @brief Base class for implementation of control algorithms
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class RegulatorMethod
//--------------------------------------------------------
//--------------------------------------------------------
class RegulatorMethod {
public:
RegulatorMethod(AtomicRegulator * atomicRegulator);
~RegulatorMethod(){};
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal(){};
/** applies thermostat to atoms in the pre-predictor phase */
virtual void apply_pre_predictor(double dt){};
/** applies thermostat to atoms in the mid-predictor phase */
virtual void apply_mid_predictor(double dt){};
/** applies thermostat to atoms in the post-predictor phase */
virtual void apply_post_predictor(double dt){};
/** applies thermostat to atoms in the pre-corrector phase */
virtual void apply_pre_corrector(double dt){};
/** applies thermostat to atoms in the post-corrector phase */
virtual void apply_post_corrector(double dt){};
/** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
virtual void compute_boundary_flux(FIELDS & fields);
/** add contributions (if any) to the finite element right-hand side */
virtual void add_to_rhs(FIELDS & rhs){};
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData){};
protected:
/** pointer to ATC_transfer object */
ATC_Transfer * atcTransfer_;
/** pointer to atomic regulator object for data */
AtomicRegulator * atomicRegulator_;
/** boundary flux */
FIELDS & boundaryFlux_;
/** field mask for specifying boundary flux */
Array2D<bool> fieldMask_;
/** number of nodes */
int nNodes_;
private:
// DO NOT define this
RegulatorMethod();
};
/**
* @class RegulatorShapeFunction
* @brief Base class for implementation of regulation algorithms using the shape function matrices
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class RegulatorShapeFunction
// base class for all regulators of general form
// of N^T w N lambda = rhs
//--------------------------------------------------------
//--------------------------------------------------------
class RegulatorShapeFunction : public RegulatorMethod {
public:
RegulatorShapeFunction(AtomicRegulator * atomicRegulator);
~RegulatorShapeFunction();
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal();
protected:
// methods
/** solve matrix equation */
void solve_for_lambda(const DENS_MAT & rhs);
/** set weighting factor for in matrix Nhat^T * weights * Nhat */
virtual void set_weights(DIAG_MAT & weights){};
// member data
/** lambda coupling parameter */
DENS_MAT & lambda_;
/** shape function matrix for use in GLC solve */
SPAR_MAT & shapeFunctionMatrix_;
/** pre-templated sparsity pattern for N^T * T * N */
SPAR_MAT & glcMatrixTemplate_;
/** reference to ATC unity shape function on ghost atoms */
SPAR_MAT & shapeFunctionGhost_;
/** maximum number of iterations used in solving for lambda */
int maxIterations_;
/** tolerance used in solving for lambda */
double tolerance_;
/** matrix solver object */
LambdaMatrixSolver * matrixSolver_;
/** maps internal atom ids to LAMMPS atom ids */
Array<int> & internalToAtom_;
/** maps internal atoms to overlap atoms */
SPAR_MAT & internalToOverlapMap_;
/** maps ghost atom and LAMMPS atom ids */
Array<int> & ghostToAtom_;
/** number of overlapping nodes */
int nNodeOverlap_;
/** number of spatial dimensions */
int nsd_;
/** number of ATC internal atoms on this processor */
int nLocal_;
/** number of thermostatted ATC internal atoms on this processor */
int nLocalLambda_;
/** number of ATC ghost atoms on this processor */
int nLocalGhost_;
private:
// DO NOT define this
RegulatorShapeFunction();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class LambdaMatrixSolver
//--------------------------------------------------------
//--------------------------------------------------------
class LambdaMatrixSolver {
public:
LambdaMatrixSolver(SPAR_MAT & matrixTemplate, SPAR_MAT & shapeFunctionMatrix, int maxIterations, double tolerance);
~LambdaMatrixSolver(){};
/** execute the solver */
virtual void execute(VECTOR & rhs, VECTOR & lambda, DIAG_MAT & weights,ATC_Transfer * atcTransfer_=NULL) = 0;
protected:
/** sparse template for the matrix */
SPAR_MAT & matrixTemplate_;
/** non-symmetric part of the matrix */
SPAR_MAT & shapeFunctionMatrix_;
/** maximum number of iterations */
int maxIterations_;
/** relative tolerance to solve to */
double tolerance_;
private:
// DO NOT define this
LambdaMatrixSolver();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class LambdaMatrixSolverLumped
//--------------------------------------------------------
//--------------------------------------------------------
class LambdaMatrixSolverLumped : public LambdaMatrixSolver {
public:
LambdaMatrixSolverLumped(SPAR_MAT & matrixTemplate, SPAR_MAT & shapeFunctionMatrix, int maxIterations, double tolerance);
~LambdaMatrixSolverLumped(){};
/** execute the solver */
virtual void execute(VECTOR & rhs, VECTOR & lambda, DIAG_MAT & weights,ATC_Transfer * atcTransfer_=NULL);
protected:
private:
// DO NOT define this
LambdaMatrixSolverLumped();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class LambdaMatrixSolverCg
//--------------------------------------------------------
//--------------------------------------------------------
class LambdaMatrixSolverCg : public LambdaMatrixSolver {
public:
LambdaMatrixSolverCg(SPAR_MAT & matrixTemplate, SPAR_MAT & shapeFunctionMatrix, int maxIterations, double tolerance);
~LambdaMatrixSolverCg(){};
/** execute the solver */
virtual void execute(VECTOR & rhs, VECTOR & lambda, DIAG_MAT & weights,ATC_Transfer * atcTransfer_=NULL);
protected:
private:
// DO NOT define this
LambdaMatrixSolverCg();
};
};
#endif

View File

@ -1,79 +0,0 @@
//*****************************************************************
// Iterative template routine -- CG
//
// CG solves the symmetric positive definite linear
// system Ax=b using the Conjugate Gradient method.
//
// CG follows the algorithm described on p. 15 in the
// SIAM Templates book.
//
// The return value indicates convergence within max_iter (input)
// iterations (0), or no convergence within max_iter iterations (1).
//
// Upon successful return, output arguments have the following values:
//
// x -- approximate solution to Ax = b
// max_iter -- the number of iterations performed before the
// tolerance was reached
// tol -- the residual after the final iteration
//
//*****************************************************************
template < class Matrix, class Vector, class DataVector, class Preconditioner, class Real >
int
CG(const Matrix &A, Vector &x, const DataVector &b, const Preconditioner &M, int &max_iter, Real &tol) {
Real resid;
DenseVector<Real> p, z, q;
Real alpha, beta, rho, rho_1;
DenseVector<Real> tmp;
tmp.reset(b.size());
p.reset(b.size());
z.reset(b.size());
q.reset(b.size());
Real normb = b.norm();
DenseVector<Real> r;
tmp = A*x;
r = b - tmp;
// Implicit assumption that only diagonal matrices are being used for preconditioning
Preconditioner Minv = M.inv();
if (normb == 0.0)
normb = 1;
if ((resid = r.norm() / normb) <= tol) {
tol = resid;
max_iter = 0;
return 0;
}
for (int i = 0; i < max_iter; i++) {
z = Minv*r;
rho = r.dot(z);
if (i == 0)
p = z;
else {
beta = rho / rho_1;
tmp = p*beta;
p = z + tmp;
}
q = A*p;
alpha = rho / p.dot(q);
x += p*alpha;
r -= q*alpha;
if ((resid = r.norm() / normb) <= tol)
{
tol = resid;
max_iter = i+1;
return 0;
}
rho_1 = rho;
}
tol = resid;
return 1;
}

View File

@ -1,243 +0,0 @@
#ifndef CLONEVECTOR_H
#define CLONEVECTOR_H
#include "Vector.h"
template<typename T>
class CloneVector : public Vector<T>
{
public:
CloneVector(); // do not implement
CloneVector(const Vector<T> &c);
CloneVector(const Matrix<T> &c, int dim, INDEX idx=0);
CloneVector(const DiagonalMatrix<T> &c, INDEX idx=0);
// overloaded virtual functions
T& operator[](INDEX i);
T operator[](INDEX i) const;
T operator()(INDEX i, INDEX j=0) const;
T& operator()(INDEX i, INDEX j=0);
INDEX nRows() const;
CloneVector<T>& operator=(const T &v);
CloneVector<T>& operator=(const CloneVector<T> &C);
CloneVector<T>& operator=(const Matrix<T> &C);
virtual bool memory_contiguous() const;
T* get_ptr() const;
void resize(INDEX nRows, INDEX nCols=0, bool copy=false);
void reset(INDEX nRows, INDEX nCols=0, bool zero=true);
void copy(const T * ptr, INDEX nRows, INDEX nCols=0);
private:
void _resize(INDEX nRows, INDEX nCols, bool copy, bool zero);
Vector<T> * const _baseV; // ptr to a base vector
Matrix<T> * const _baseM; // ptr to a base matrix
int _clone_type; // what to clown (see enum CLONE_TYPE)
INDEX _idx; // index of matrix dimension to clone
};
///////////////////////////////////////////////////////////////////////////////
// Template definitions ///////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// Construct from another vector
//-----------------------------------------------------------------------------
template<typename T>
CloneVector<T>::CloneVector(const Vector<T> &c)
: Vector<T>(), _baseV(const_cast<Vector<T>*>(&c)), _baseM(NULL)
{}
//-----------------------------------------------------------------------------
// Construct from a matrix, the const_cast isn't pretty
/* CloneVector(const Matrix<T> &c, int dim, INDEX idx)
/ attaches to a slice of a matrix
/ Arguments: c = pointer to the matrix
/ dim = type of slice CLONE_ROW, CLONE_COL, CLONE_DIAG
/ idx = index of row or column (no effect on diag currently)
*/
//-----------------------------------------------------------------------------
template<typename T>
CloneVector<T>::CloneVector(const Matrix<T> &c, int dim, INDEX idx)
: Vector<T>(), _baseV(NULL), _baseM(const_cast<Matrix<T>*>(&c))
, _clone_type(dim), _idx(idx)
{}
//-----------------------------------------------------------------------------
// Construct from a DiagonalMatrix
//-----------------------------------------------------------------------------
template<typename T>
CloneVector<T>::CloneVector(const DiagonalMatrix<T> &c, INDEX idx)
: Vector<T>(), _baseV(NULL), _baseM(const_cast<DiagonalMatrix<T>*>(&c))
, _clone_type(CLONE_DIAG), _idx(0)
{}
//-----------------------------------------------------------------------------
// value (const) indexing operator
//-----------------------------------------------------------------------------
template<typename T>
T CloneVector<T>::operator()(INDEX i, INDEX j) const
{
return (*this)[i];
}
//-----------------------------------------------------------------------------
// reference index operator
//-----------------------------------------------------------------------------
template<typename T>
T& CloneVector<T>::operator()(INDEX i, INDEX j)
{
return (*this)[i];
}
//-----------------------------------------------------------------------------
// Indexes the cloned vector either from another vector or a matrix
//-----------------------------------------------------------------------------
template<typename T>
T CloneVector<T>::operator[](INDEX i) const
{
if (_baseV) return (*_baseV)(i);
if (_clone_type == CLONE_ROW) return (*_baseM)(_idx, i);
else if (_clone_type == CLONE_COL) return (*_baseM)(i,_idx);
else if (_clone_type == CLONE_DIAG) return (*_baseM)(i,i);
return 0;
}
//-----------------------------------------------------------------------------
// Indexes the cloned vector either from another vector or a matrix
//-----------------------------------------------------------------------------
template<typename T>
T& CloneVector<T>::operator[](INDEX i)
{
if (_baseV) return (*_baseV)(i);
if (_clone_type == CLONE_ROW) return (*_baseM)(_idx, i);
if (_clone_type == CLONE_COL) return (*_baseM)(i,_idx);
if (_clone_type == CLONE_DIAG) return (*_baseM)(i,i);
return (*_baseV)(i);
}
//-----------------------------------------------------------------------------
// Returns the size of the base vector or of the row/col of the base matrix
//-----------------------------------------------------------------------------
template<typename T>
INDEX CloneVector<T>::nRows() const
{
using std::min;
if (_baseV) return _baseV->size();
if (_clone_type == CLONE_ROW) return _baseM->nCols();
if (_clone_type == CLONE_COL) return _baseM->nRows();
if (_clone_type == CLONE_DIAG) return min(_baseM->nRows(), _baseM->nCols());
return 0;
}
//-----------------------------------------------------------------------------
// assigns all elements to a constant
//-----------------------------------------------------------------------------
template<typename T>
CloneVector<T>& CloneVector<T>::operator=(const T &v)
{
this->set_all_elements_to(v); // NOTE: DO NOT do _baseX->set_elements_to()
return *this;
}
//-----------------------------------------------------------------------------
// assigns all elements to the corresponding elements in C
//-----------------------------------------------------------------------------
template<typename T>
CloneVector<T>& CloneVector<T>::operator=(const CloneVector<T> &C)
{
GCK(*this, C, this->size()!=C.size(), "Error in CloneVector:operator=");
FORi VIDX(i) = C[i];
return *this;
}
//-----------------------------------------------------------------------------
// assigns all elements to the corresponding elements in C
//-----------------------------------------------------------------------------
template<typename T>
CloneVector<T>& CloneVector<T>::operator=(const Matrix<T> &C)
{
GCK(*this, C, this->size()!=C.size(), "Error in CloneVector:operator=");
FORi VIDX(i) = C[i];
return *this;
}
//-----------------------------------------------------------------------------
// returns true only if its guaranteed memory is contiguous
//-----------------------------------------------------------------------------
template<typename T>
bool CloneVector<T>::memory_contiguous() const
{
// drill down through clone of clones
if (_baseV) return _baseV->memory_contiguous();
// could be okay if DiagonalMatrix, but can't guarantee this
if (_clone_type == CLONE_DIAG) return false;
#ifdef ROW_STORAGE
return _clone_type == CLONE_ROW;
#else
return _clone_type == CLONE_COL;
#endif
}
//-----------------------------------------------------------------------------
// Returns a pointer to the data unless the data is a column of a matrix
//-----------------------------------------------------------------------------
template<typename T>
T* CloneVector<T>::get_ptr() const
{
if (_baseV) return _baseV->get_ptr();
#ifdef ROW_STORAGE
if (_clone_type == CLONE_ROW) return _baseM->get_ptr() + this->size()*_idx;
if (_clone_type == CLONE_COL) return _baseM->get_ptr() + this->size();
if (_clone_type == CLONE_DIAG) return _baseM->get_ptr();
#else
if (_clone_type == CLONE_COL) return _baseM->get_ptr() + this->size()*_idx;
if (_clone_type == CLONE_ROW) return _baseM->get_ptr() + this->size();
if (_clone_type == CLONE_DIAG) return _baseM->get_ptr();
#endif
return 0;
}
//-----------------------------------------------------------------------------
// general resize function, can handle parents that are matrices or vectors
//-----------------------------------------------------------------------------
template<typename T>
void CloneVector<T>::_resize(INDEX nRows, INDEX nCols, bool copy, bool zero)
{
if (_baseV)
{
if (copy) _baseV->resize(nRows, nCols, copy);
else _baseV->reset (nRows, nCols, zero);
return;
}
// parent is a matrix, need to decide what the Vector is cloning
switch (_clone_type)
{
case CLONE_ROW: // now the leading dimension is rows
nCols = nCols ? nCols : _baseM->nCols();
break;
case CLONE_COL: // now the leading dimension is columns
nCols = nCols ? nCols : _baseM->nRows();
Utility::Swap(nRows, nCols);
break;
case CLONE_DIAG: // lets just hope you knew what you were doing
break;
default:
return;
}
if (zero) _baseM->reset(nRows, nCols, zero); // zero overrides copy
else _baseM->resize(nRows, nCols, copy);
}
//-----------------------------------------------------------------------------
// resizes the matrix and optionally copies what fits
//-----------------------------------------------------------------------------
template<typename T>
void CloneVector<T>::resize(INDEX nRows, INDEX nCols, bool copy)
{
_resize(nRows, nCols, copy, false);
}
//-----------------------------------------------------------------------------
// resizes the matrix and optionally zeros it out
//-----------------------------------------------------------------------------
template<typename T>
void CloneVector<T>::reset(INDEX nRows, INDEX nCols, bool zero)
{
_resize(nRows, nCols, false, zero);
}
//-----------------------------------------------------------------------------
// resizes the matrix and copies data
//-----------------------------------------------------------------------------
template<typename T>
void CloneVector<T>::copy(const T * ptr, INDEX nRows, INDEX nCols)
{
_resize(nRows, nCols, false, false);
memcpy(this->get_ptr(), ptr, this->size()*sizeof(T));
}
#endif

View File

@ -1,317 +0,0 @@
#ifndef DENSEMATRIX_H
#define DENSEMATRIX_H
#include "Matrix.h"
template <typename T>
class DenseMatrix : public Matrix<T>
{
public:
DenseMatrix(INDEX rows=0, INDEX cols=0, bool z=1) { _create(rows, cols, z); }
DenseMatrix(const DenseMatrix<T>& c) : _data(NULL){ _copy(c); }
DenseMatrix(const SparseMatrix<T>& c): _data(NULL){ c.dense_copy(*this);}
DenseMatrix(const Matrix<T>& c) : _data(NULL){ _copy(c); }
// const SparseMatrix<T> * p = sparse_cast(&c);
// (p) ? p->dense_copy(*this) : _copy(c); }
~DenseMatrix() { _delete();}
void reset (INDEX rows, INDEX cols, bool zero=true);
void resize(INDEX rows, INDEX cols, bool copy=false);
void copy (const T * ptr, INDEX rows, INDEX cols);
/** returns transpose(this) * B */
DenseMatrix<T> transMat(const DenseMatrix<T>& B) const;
/** returns by element multiply A_ij = this_ij * B_ij */
DenseMatrix<T> mult_by_element(const DenseMatrix<T>& B) const;
/** overloaded virtual functions */
T& operator()(INDEX i, INDEX j) { MICK(i,j) return DATA(i,j); }
T operator()(INDEX i, INDEX j) const { MICK(i,j) return DATA(i,j); }
T operator[](INDEX i) const { VICK(i) return _data[i]; }
T& operator[](INDEX i) { VICK(i) return _data[i]; }
INDEX nRows() const { return _nRows; }
INDEX nCols() const { return _nCols; }
T * get_ptr() const { return _data; }
void write_restart(FILE *f) const;
void set_all_elements_to(const T &v);
DiagonalMatrix<T> get_diag() const;
DenseMatrix<T>& operator=(const T &v);
DenseMatrix<T>& operator=(const Matrix<T> &c);
DenseMatrix<T>& operator=(const DenseMatrix<T> &c);
DenseMatrix<T>& operator=(const SparseMatrix<T> &c);
private:
void _delete();
void _create(INDEX rows, INDEX cols, bool zero=false);
void _copy(const Matrix<T> &c);
T *_data;
INDEX _nRows, _nCols;
};
//! Computes the cofactor matrix of A.
template<typename T>
DenseMatrix<T> adjugate(const Matrix<T> &A, bool symmetric=false);
//! Returns a the tensor product of two vectors
template<typename T>
DenseMatrix<T> tensor_product(const Vector<T> &a, const Vector<T> &b);
//----------------------------------------------------------------------------
// Returns an identity matrix, defaults to 3x3.
//----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> eye(INDEX rows=3, INDEX cols=3)
{
const double dij[] = {0.0, 1.0};
DENS_MAT I(rows, cols, false); // do not need to pre-zero
for (INDEX j=0; j<cols; j++)
for (INDEX i=0; i<rows; i++)
I(i,j) = dij[i==j];
return I;
}
//----------------------------------------------------------------------------
// resizes the matrix and optionally zeros it out (default - zero)
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::reset(INDEX rows, INDEX cols, bool zero)
{
if (!this->is_size(rows, cols))
{
_delete();
_create(rows, cols);
}
if (zero) this->zero();
}
//----------------------------------------------------------------------------
// resizes the matrix and optionally copies over what still fits
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::resize(INDEX rows, INDEX cols, bool copy)
{
if (this->is_size(rows, cols)) return; // if is correct size, done
if (!copy)
{
_delete();
_create(rows, cols);
return;
}
DenseMatrix<T> temp(*this);
_delete();
_create(rows, cols);
FORij MIDX(i,j) = temp.in_range(i,j) ? temp(i,j) : T(0);
}
//----------------------------------------------------------------------------
// resizes the matrix and copies data
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::copy(const T * ptr, INDEX rows, INDEX cols)
{
resize(rows, cols, false);
memcpy(_data, ptr, this->size()*sizeof(T));
}
//----------------------------------------------------------------------------
// returns transpose(this) * B
//----------------------------------------------------------------------------
template <typename T>
DenseMatrix<T> DenseMatrix<T>::transMat(const DenseMatrix<T>& B) const
{
DenseMatrix C;
MultAB(*this, B, C, true);
return C;
}
//----------------------------------------------------------------------------
// returns this_ij * B_ij
//----------------------------------------------------------------------------
template <typename T>
DenseMatrix<T> DenseMatrix<T>::mult_by_element(const DenseMatrix<T>& B) const
{
DenseMatrix C;
C.reset(_nRows,_nCols);
FORij C(i,j) = (*this)(i,j)*B(i,j);
return C;
}
//----------------------------------------------------------------------------
// writes the matrix data to a file
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::write_restart(FILE *f) const
{
fwrite(&_nRows, sizeof(INDEX),1,f);
fwrite(&_nCols, sizeof(INDEX),1,f);
if (this->size()) fwrite(_data, sizeof(T), this->size(), f);
}
//----------------------------------------------------------------------------
// sets all elements to a value (optimized)
//----------------------------------------------------------------------------
template <typename T>
inline void DenseMatrix<T>::set_all_elements_to(const T &v)
{
FORi _data[i] = v;
}
//-----------------------------------------------------------------------------
// Return a diagonal matrix containing the diagonal entries of this matrix
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> DenseMatrix<T>::get_diag() const
{
DiagonalMatrix<T> D(nRows(), true); // initialized to zero
INDEX i;
for (i=0; i<nRows(); i++)
{
D(i,i) = DATA(i,i);
}
return D;
}
//----------------------------------------------------------------------------
// clears allocated memory
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::_delete()
{
_nRows = _nCols = 0;
if (_data) delete [] _data;
}
//----------------------------------------------------------------------------
// allocates memory for an rows by cols DenseMatrix
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::_create(INDEX rows, INDEX cols, bool zero)
{
_nRows=rows;
_nCols=cols;
_data = (this->size() ? new T [_nCols*_nRows] : NULL);
if (zero) this->zero();
}
//----------------------------------------------------------------------------
// creates a deep memory copy from a general matrix
//----------------------------------------------------------------------------
template <typename T>
void DenseMatrix<T>::_copy(const Matrix<T> &c)
{
if (!_data || this->size()!=c.size())
{
_delete();
_create(c.nRows(), c.nCols());
}
else
{
_nRows = c.nRows();
_nCols = c.nCols();
}
memcpy(_data, c.get_ptr(), c.size()*sizeof(T));
}
//----------------------------------------------------------------------------
// sets all elements to a constant
//----------------------------------------------------------------------------
template <typename T>
DenseMatrix<T>& DenseMatrix<T>::operator=(const T &v)
{
this->set_all_elements_to(v);
return *this;
}
//----------------------------------------------------------------------------
// copys c with a deep copy
//----------------------------------------------------------------------------
template <typename T>
DenseMatrix<T>& DenseMatrix<T>::operator=(const Matrix<T> &c)
{
_copy(c);
return *this;
}
//----------------------------------------------------------------------------
// copys c with a deep copy
//----------------------------------------------------------------------------
template <typename T>
DenseMatrix<T>& DenseMatrix<T>::operator=(const DenseMatrix<T> &c)
{
_copy(c);
return *this;
}
//-----------------------------------------------------------------------------
// copys c with a deep copy, including zeros
//-----------------------------------------------------------------------------
template <typename T>
DenseMatrix<T>& DenseMatrix<T>::operator=(const SparseMatrix<T> &c)
{
_delete();
_create(c.nRows(), c.nCols(), true);
SparseMatrix<T>::compress(c);
for (INDEX i=0; i<c.size(); i++)
{
TRIPLET<T> x = c.get_triplet(i);
cout << "x.i: "<< x.i << "\nx.j: "<< x.j << "\nv.j: "<< x.v << std::endl << std::endl;
MIDX(x.i, x.j) = x.v;
}
return *this;
}
//* Returns the transpose of the cofactor matrix of A.
//* see http://en.wikipedia.org/wiki/Adjugate_matrix
//* symmetric flag only affects cases N>3
template<typename T>
DenseMatrix<T> adjugate(const Matrix<T> &A, bool symmetric)
{
if (!A.is_square()) gerror("adjugate can only be computed for square matrices.");
DenseMatrix<T> C(A.nRows(), A.nRows());
switch (A.nRows()) {
case 1:
gerror("adjugate must be computed for matrixes of size greater than 1");
case 2:
C(0,0) = A(1,1); C(0,1) =-A(0,1);
C(1,0) =-A(1,0); C(1,1) = A(0,0);
break;
case 3: // 3x3 case was tested vs matlab
C(0,0) = A(1,1)*A(2,2)-A(1,2)*A(2,1);
C(1,0) =-A(1,0)*A(2,2)+A(1,2)*A(2,0); // i+j is odd (reverse sign)
C(2,0) = A(1,0)*A(2,1)-A(1,1)*A(2,0);
C(0,1) =-A(0,1)*A(2,2)+A(0,2)*A(2,1); // i+j is odd
C(1,1) = A(0,0)*A(2,2)-A(0,2)*A(2,0);
C(2,1) =-A(0,0)*A(2,1)+A(0,1)*A(2,0); // i+j is odd
C(0,2) = A(0,1)*A(1,2)-A(0,2)*A(1,1);
C(1,2) =-A(0,0)*A(1,2)+A(0,2)*A(1,0); // i+j is odd
C(2,2) = A(0,0)*A(1,1)-A(0,1)*A(1,0);
break;
default:
// NOTE: - det() is only defined for type double
// this feature is neither tested nor optimal - use at your own risk!!!
DenseMatrix<T> m(A.nRows()-1, A.nRows()-1);
double sign[] = {1.0, -1.0};
for (unsigned j=0; j<A.nCols(); j++) {
for (unsigned i=0; i<A.nRows(); i++) {
for (unsigned mj=0; mj<m.nCols(); mj++) {
for (unsigned mi=0; mi<m.nRows(); mi++) {
m(mi, mj) = A(mi+(mi>=i), mj+(mj>=j)); // skip row i and col j
}
}
if (!symmetric) C(j,i)=det(m)*sign[(i+j)&1];
if (symmetric && i>=j) C(i,j)=C(j,i)=det(m)*sign[(i+j)&1];
}
}
}
return C;
}
// Returns a the tensor product of two vectors
template<typename T>
DenseMatrix<T> tensor_product(const Vector<T> &a, const Vector<T> &b)
{
DenseMatrix<T> ab(a.size(), b.size());
for (unsigned j=0; j<b.size(); j++)
for (unsigned i=0; i<a.size(); i++)
ab(i,j) = a(i)*b(j);
return ab;
}
//* Returns a DenseMatrix with random values (like matlab rand(m,n)
template<typename T>
DenseMatrix<T> rand(unsigned rows, unsigned cols, int seed=1234)
{
srand(seed);
const double rand_max_inv = 1.0 / double(RAND_MAX);
DenseMatrix<T> R(rows, cols, false);
for (unsigned i=0; i<R.size(); i++) R[i]=double(::rand())*rand_max_inv;
return R;
}
#endif

View File

@ -1,150 +0,0 @@
#ifndef DENSEVECTOR_H
#define DENSEVECTOR_H
#include "Vector.h"
template<typename T>
class DenseVector : public Vector<T>
{
public:
explicit DenseVector(INDEX n=0, bool z=1) { _create(n,z); }
DenseVector(const DenseVector<T> &c) : _data(NULL) { _copy(c); }
DenseVector(const Vector<T> &c) : _data(NULL) { _copy(c); }
virtual ~DenseVector() { _delete(); }
//* resizes the Vector, ignores nCols, optionally copys what fits
void resize(INDEX rows, INDEX cols=1, bool copy=false);
//* resizes the Vector, ignores nCols, optionally zeros it out
void reset (INDEX rows, INDEX cols=1, bool zero=true);
//* resizes the Vector and copies data, ignores nCols
void copy(const T * ptr, INDEX rows, INDEX cols=1);
// overloaded inline virtual functions
T operator[](INDEX i) const { VICK(i) return _data[i]; }
T& operator[](INDEX i) { VICK(i) return _data[i]; }
T operator()(INDEX i, INDEX j=0) const { VICK(i) return _data[i]; }
T& operator()(INDEX i, INDEX j=0) { VICK(i) return _data[i]; }
void set_all_elements_to(const T &v) { FORi _data[i] = v; }
INDEX nRows() const { return _size; }
T* get_ptr() const { return _data; }
DenseVector<T>& operator=(const T &v);
DenseVector<T>& operator=(const Vector<T> &c);
DenseVector<T>& operator=(const DenseVector<T> &c);
void write_restart(FILE *f) const;
private:
void _delete();
void _create(INDEX n, bool zero=0);
void _copy(const Vector<T> &c);
T *_data;
INDEX _size;
};
///////////////////////////////////////////////////////////////////////////////
// Template definitions ///////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// resizes the matrix and optionally copies over what still fits, ignores cols
//-----------------------------------------------------------------------------
template <typename T>
void DenseVector<T>::resize(INDEX rows, INDEX cols, bool copy)
{
if (_size==rows) return; // if is correct size, done
if (!copy)
{
_delete();
_create(rows);
return;
}
DenseVector<T> temp(*this);
_delete();
_create(rows);
FORi _data[i] = i<temp.size() ? temp[i] : T(0.0);
return;
}
///////////////////////////////////////////////////////////////////////////////
//* resizes the matrix and optionally zeros it out
template <typename T>
void DenseVector<T>::reset(INDEX rows, INDEX cols, bool zero)
{
if (_size!=rows)
{
_delete();
_create(rows);
}
if (zero) this->zero();
}
///////////////////////////////////////////////////////////////////////////////
//* resizes the matrix and optionally zeros it out
template <typename T>
void DenseVector<T>::copy(const T * ptr, INDEX rows, INDEX cols)
{
resize(rows, 1, false);
memcpy(_data, ptr, this->size()*sizeof(T));
}
///////////////////////////////////////////////////////////////////////////////
//* writes the matrix data to a file
template <typename T>
void DenseVector<T>::write_restart(FILE *f) const
{
fwrite(&_size, sizeof(INDEX),1,f);
if(_size) fwrite(_data, sizeof(T), _size, f);
}
///////////////////////////////////////////////////////////////////////////////
//* clears allocated memory
template <typename T>
inline void DenseVector<T>::_delete()
{
if (_data) delete [] _data;
_size = 0;
}
///////////////////////////////////////////////////////////////////////////////
//* allocates memory for an rows by cols DenseMatrix
template <typename T>
inline void DenseVector<T>::_create(INDEX n, bool zero)
{
_size=n;
_data = _size ? new T [_size] : NULL ;
if (zero) this->zero();
}
///////////////////////////////////////////////////////////////////////////////
//* creates a deep memory copy from a general matrix
template <typename T>
inline void DenseVector<T>::_copy(const Vector<T> &c)
{
if (!_data || _size!=c.size())
{
_delete();
_create(c.size(), false);
}
else _size = c.size();
memcpy(_data, c.get_ptr(), _size*sizeof(T));
}
///////////////////////////////////////////////////////////////////////////////
//* assigns v to all values in the vector
template <typename T>
DenseVector<T>& DenseVector<T>::operator=(const T &v)
{
FORi VIDX(i) = v;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
//* copys c with a deep copy
template <typename T>
DenseVector<T>& DenseVector<T>::operator=(const Vector<T> &c)
{
_copy(c);
return *this;
}
///////////////////////////////////////////////////////////////////////////////
//* copys c with a deep copy
template <typename T>
DenseVector<T>& DenseVector<T>::operator=(const DenseVector<T> &c)
{
_copy(c);
return *this;
}
#endif

View File

@ -1,462 +0,0 @@
#ifndef DIAGONALMATRIX_H
#define DIAGONALMATRIX_H
#include "MatrixDef.h"
template<typename T>
class DiagonalMatrix : public Matrix<T>
{
public:
explicit DiagonalMatrix(INDEX nRows=0, bool zero=0);
DiagonalMatrix(const DiagonalMatrix<T>& c);
DiagonalMatrix(const Vector<T>& v);
virtual ~DiagonalMatrix();
//* resizes the matrix, ignores nCols, optionally zeros
void reset(INDEX rows, INDEX cols=0, bool zero=true);
//* resizes the matrix, ignores nCols, optionally copies what fits
void resize(INDEX rows, INDEX cols=0, bool copy=false);
//* resets based on full copy of vector v
void reset(const Vector<T>& v);
//* resets based on full copy of a DiagonalMatrix
void reset(const DiagonalMatrix<T>& v);
//* resizes the matrix, ignores nCols, optionally copies what fits
void copy(const T * ptr, INDEX rows, INDEX cols=0);
//* resets based on a "shallow" copy of a vector
void shallowreset(const Vector<T> &v);
//* resets based on a "shallow" copy of a DiagonalMatrix
void shallowreset(const DiagonalMatrix<T> &c);
T& operator()(INDEX i, INDEX j);
T operator()(INDEX i, INDEX j) const;
T& operator[](INDEX i);
T operator[](INDEX i) const;
INDEX nRows() const;
INDEX nCols() const;
T* get_ptr() const;
void write_restart(FILE *f) const;
// Dump matrix contents to screen (not defined for all datatypes)
string tostring() const { return _data->tostring(); }
using Matrix<T>::matlab;
void matlab(ostream &o, const string &s="D") const;
// overloaded operators
DiagonalMatrix<T>& operator=(const T s);
DiagonalMatrix<T>& operator=(const DiagonalMatrix<T> &C);
//DiagonalMatrix<T>& operator=(const Vector<T> &C);
INDEX size() const { return _data->size(); }
//* computes the inverse of this matrix
DiagonalMatrix<T>& inv_this();
//* returns a copy of the inverse of this matrix
DiagonalMatrix<T> inv() const;
protected:
void _set_equal(const Matrix<T> &r);
DiagonalMatrix& operator=(const Vector<T> &c) {}
DiagonalMatrix& operator=(const Matrix<T> &c) {}
private:
void _delete();
Vector<T> *_data;
};
//-----------------------------------------------------------------------------
// DiagonalMatrix-DiagonalMatrix multiplication
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> operator*(const DiagonalMatrix<T>& A, const DiagonalMatrix<T>& B)
{
SSCK(A, B, "DiagonalMatrix-DiagonalMatrix multiplication");
DiagonalMatrix<T> R(A);
for (INDEX i=0; i<R.nRows(); i++) R[i] *= B[i];
return R;
}
//-----------------------------------------------------------------------------
// DiagonalMatrix-matrix multiplication
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> operator*(const DiagonalMatrix<T>& A, const Matrix<T> &B)
{
GCK(A, B, A.nCols()!=B.nRows(), "DiagonalMatrix-Matrix multiplication");
DenseMatrix<T> R(B); // makes a copy of r to return
for (INDEX i=0; i<R.nRows(); i++)
for (INDEX j=0; j<R.nCols(); j++)
R(i,j) *= A[i];
return R;
}
//-----------------------------------------------------------------------------
// matrix-DiagonalMatrix multiplication
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> operator*(const Matrix<T> &B, const DiagonalMatrix<T>& A)
{
GCK(B, A, B.nCols()!=A.nRows(), "Matrix-DiagonalMatrix multiplication");
DenseMatrix<T> R(B); // makes a copy of r to return
for (INDEX j=0; j<R.nCols(); j++)
for (INDEX i=0; i<R.nRows(); i++)
R(i,j) *= A[j];
return R;
}
//-----------------------------------------------------------------------------
// DiagonalMatrix-vector multiplication
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<T> operator*(const DiagonalMatrix<T>& A, const Vector<T> &b)
{
GCK(A, b, A.nCols()!=b.size(), "DiagonalMatrix-Vector multiplication");
DenseVector<T> r(b); // makes a copy of r to return
for (INDEX i=0; i<r.size(); i++)
r[i] *= A[i];
return r;
}
//-----------------------------------------------------------------------------
// vector-DiagonalMatrix multiplication
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<T> operator*(const Vector<T> &b, const DiagonalMatrix<T>& A)
{
GCK(b, A, b.size()!=A.nRows(), "Matrix-DiagonalMatrix multiplication");
DenseVector<T> r(b); // makes a copy of r to return
for (INDEX i=0; i<r.size(); i++)
r[i] *= A[i];
return r;
}
//-----------------------------------------------------------------------------
// DiagonalMatrix-SparseMatrix multiplication
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T> operator*(const DiagonalMatrix<T> &A, const SparseMatrix<T>& B)
{
GCK(A, B, A.nCols()!=B.nRows() ,"DiagonalMatrix-SparseMatrix multiplication");
SparseMatrix<T> R(B);
CloneVector<T> d(A);
R.row_scale(d);
return R;
}
//-----------------------------------------------------------------------------
// DiagonalMatrix-scalar multiplication
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> operator*(DiagonalMatrix<T> &A, const T s)
{
DiagonalMatrix<T> R(A);
R *= s;
return R;
}
//-----------------------------------------------------------------------------
// Commute with DiagonalMatrix * double
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> operator*(const T s, const DiagonalMatrix<T>& A)
{
DiagonalMatrix<T> R(A);
R *= s;
return R;
}
//-----------------------------------------------------------------------------
// DiagonalMatrix addition
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> operator+(const DiagonalMatrix<T> &A, const DiagonalMatrix<T> &B)
{
DiagonalMatrix<T> R(A);
R+=B;
return R;
}
//-----------------------------------------------------------------------------
// DiagonalMatrix subtraction
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> operator-(const DiagonalMatrix<T> &A, const DiagonalMatrix<T> &B)
{
DiagonalMatrix<T> R(A);
return R-=B;
}
//-----------------------------------------------------------------------------
// template member definitions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Default constructor - optionally zeros the matrix
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>::DiagonalMatrix(INDEX rows, bool zero)
: _data(NULL)
{
reset(rows, zero);
}
//-----------------------------------------------------------------------------
// copy constructor - makes a full copy
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>::DiagonalMatrix(const DiagonalMatrix<T>& c)
: _data(NULL)
{
reset(c);
}
//-----------------------------------------------------------------------------
// copy constructor from vector
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>::DiagonalMatrix(const Vector<T>& v)
: _data(NULL)
{
reset(v);
}
//-----------------------------------------------------------------------------
// destructor
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>::~DiagonalMatrix()
{
_delete();
}
//-----------------------------------------------------------------------------
// deletes the data stored by this matrix
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::_delete()
{
if (_data) delete _data;
}
//-----------------------------------------------------------------------------
// resizes the matrix, ignores nCols, optionally zeros
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::reset(INDEX rows, INDEX cols, bool zero)
{
_delete();
_data = new DenseVector<T>(rows, zero);
}
//-----------------------------------------------------------------------------
// resizes the matrix, ignores nCols, optionally copies what fits
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::resize(INDEX rows, INDEX cols, bool copy)
{
_data->resize(rows, copy);
}
//-----------------------------------------------------------------------------
// changes the diagonal of the matrix to a vector v (makes a copy)
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::reset(const Vector<T>& v)
{
if (&v == _data) return; // check for self-reset
_delete();
_data = new DenseVector<T>(v);
}
//-----------------------------------------------------------------------------
// copys from another DiagonalMatrix
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::reset(const DiagonalMatrix<T>& c)
{
reset(*(c._data));
}
//-----------------------------------------------------------------------------
// resizes the matrix and copies data
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::copy(const T * ptr, INDEX rows, INDEX cols)
{
if (_data) _data->reset(rows, false);
else _data = new DenseVector<T>(rows, false);
memcpy(_data, ptr, this->size()*sizeof(T));
}
//-----------------------------------------------------------------------------
// shallow reset from another DiagonalMatrix
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::shallowreset(const DiagonalMatrix<T> &c)
{
_delete();
_data = new CloneVector<T>(*(c._data));
}
//-----------------------------------------------------------------------------
// shallow reset from Vector
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::shallowreset(const Vector<T> &v)
{
_delete();
_data = new CloneVector<T>(v);
}
//-----------------------------------------------------------------------------
// reference indexing operator - must throw an error if i!=j
//-----------------------------------------------------------------------------
template<typename T>
T& DiagonalMatrix<T>::operator()(INDEX i, INDEX j)
{
GCK(*this,*this,i!=j,"DiagonalMatrix: tried to index off diagonal");
return VIDX(i);
}
//-----------------------------------------------------------------------------
// value indexing operator - returns 0 if i!=j
//-----------------------------------------------------------------------------
template<typename T>
T DiagonalMatrix<T>::operator()(INDEX i, INDEX j) const
{
return (i==j) ? (*_data)(i) : (T)0;
}
//-----------------------------------------------------------------------------
// flat reference indexing operator
//-----------------------------------------------------------------------------
template<typename T>
T& DiagonalMatrix<T>::operator[](INDEX i)
{
return (*_data)(i);
}
//-----------------------------------------------------------------------------
// flat value indexing operator
//-----------------------------------------------------------------------------
template<typename T>
T DiagonalMatrix<T>::operator[](INDEX i) const
{
return (*_data)(i);
}
//-----------------------------------------------------------------------------
// returns the number of rows
//-----------------------------------------------------------------------------
template<typename T>
INDEX DiagonalMatrix<T>::nRows() const
{
return _data->size();
}
//-----------------------------------------------------------------------------
// returns the number of columns (same as nCols())
//-----------------------------------------------------------------------------
template<typename T>
INDEX DiagonalMatrix<T>::nCols() const
{
return _data->size();
}
//-----------------------------------------------------------------------------
// returns a pointer to the diagonal values, dangerous!
//-----------------------------------------------------------------------------
template<typename T>
T* DiagonalMatrix<T>::get_ptr() const
{
return _data->get_ptr();
}
//-----------------------------------------------------------------------------
// writes the diagonal to a binary data restart file
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::write_restart(FILE *f) const
{
_data->write_restart(f);
}
//-----------------------------------------------------------------------------
// sets the diagonal to a constant
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>& DiagonalMatrix<T>::operator=(const T v)
{
this->set_all_elements_to(v);
return *this;
}
//-----------------------------------------------------------------------------
// assignment operator with another diagonal matrix
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>& DiagonalMatrix<T>::operator=(const DiagonalMatrix<T>& C)
{
reset(C);
return *this;
}
//-----------------------------------------------------------------------------
// writes a matlab command to duplicate this sparse matrix
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::matlab(ostream &o, const string &s) const
{
_data->matlab(o, s);
o << s <<"=diag("<<s<<",0);\n";
}
//-----------------------------------------------------------------------------
// inverts this matrix, returns a reference
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T>& DiagonalMatrix<T>::inv_this()
{
for(INDEX i=0; i<nRows(); i++)
{
if (VIDX(i)!=T(0)) VIDX(i) = 1.0/VIDX(i);
else
{
cout<<"DiagonalMatrix::inv(): ("<<i<<","<<i<<")=0\n";
}
}
// Error check info
const double min_max = _data->minabs() / _data->maxabs();
if (min_max > 1e-14) return *this;
cout << "DiagonalMatrix::inv_this(): Warning: Matrix is badly scaled.";
cout << " RCOND = "<<min_max<<"\n";
return *this;
}
//-----------------------------------------------------------------------------
// returns the inverse of this matrix
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> DiagonalMatrix<T>::inv() const
{
DiagonalMatrix<T> invA(*this); // Make copy of A to invert
for(INDEX i=0; i<invA.nRows(); i++)
{
if (VIDX(i)!=T(0)) invA[i]=1.0/VIDX(i);
else
{
cout<<"DiagonalMatrix::inv(): ("<<i<<","<<i<<")=0\n";
}
}
// Error check info
const double min_max = _data->minabs() / _data->maxabs();
if (min_max > 1e-14) return invA;
cout << "DiagonalMatrix::inv(): Warning: Matrix is badly scaled.";
cout << " RCOND = "<<min_max<<"\n";
return invA;
}
//-----------------------------------------------------------------------------
// computes a matrix inverse
//-----------------------------------------------------------------------------
inline DiagonalMatrix<double> inv(const DiagonalMatrix<double>& A)
{
return A.inv();
}
//-----------------------------------------------------------------------------
// general diagonalmatrix assigment
//-----------------------------------------------------------------------------
template<typename T>
void DiagonalMatrix<T>::_set_equal(const Matrix<T> &r)
{
this->resize(r.nRows(), r.nCols());
const Matrix<T> *pr = &r;
const SparseMatrix<T> *ps = dynamic_cast<const SparseMatrix<T>*> (pr);
const DiagonalMatrix<T> *pd = dynamic_cast<const DiagonalMatrix<T>*> (pr);
const Vector<T> *pv = dynamic_cast<const Vector<T>*> (pr);
if (ps) this->reset(ps->get_diag());
else if (pd) this->reset(*pd);
else if (pv) this->reset(*pv);
else
{
cout <<"Error in general sparse matrix assignment\n";
}
}
//-----------------------------------------------------------------------------
// casts a generic matrix pointer into a DiagonalMatrix pointer - null if fail
//-----------------------------------------------------------------------------
template<typename T>
const DiagonalMatrix<T> *diag_cast(const Matrix<T> *m)
{
return dynamic_cast<const DiagonalMatrix<T>*>(m);
}
#endif

View File

@ -1,251 +0,0 @@
// ATC transfer headers
#include "ElasticTimeIntegrator.h"
#include "ATC_Transfer.h"
#include "TimeFilter.h"
#include "ATC_Error.h"
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticTimeIntegrator
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab data from ATC
//--------------------------------------------------------
ElasticTimeIntegrator::ElasticTimeIntegrator(ATC_Transfer * atcTransfer,
TimeIntegrationType timeIntegrationType) :
TimeIntegrator(atcTransfer, timeIntegrationType)
{
// do nothing
}
//--------------------------------------------------------
// modify
// parses inputs and modifies state of the filter
//--------------------------------------------------------
bool ElasticTimeIntegrator::modify(int narg, char **arg)
{
// currently no parsing for elastic time integration
return false;
}
//--------------------------------------------------------
// initialize
// sets up all the necessary data
//--------------------------------------------------------
void ElasticTimeIntegrator::initialize()
{
if (needReset_ || timeFilterManager_->need_reset()) {
if (timeIntegrationMethod_)
delete timeIntegrationMethod_;
if (timeFilterManager_->need_reset()) {
if (timeFilter_)
delete timeFilter_;
timeFilter_ = timeFilterManager_->construct(TimeFilterManager::IMPLICIT);
}
if (timeFilterManager_->filter_dynamics()) {
timeIntegrationMethod_ = new ElasticTimeIntegratorVerletFiltered(this);
}
else {
timeIntegrationMethod_ = new ElasticTimeIntegratorVerlet(this);
}
}
TimeIntegrator::initialize();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticIntegrationMethod
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab data from ATC
//--------------------------------------------------------
ElasticIntegrationMethod::ElasticIntegrationMethod(ElasticTimeIntegrator * elasticTimeIntegrator) :
TimeIntegrationMethod(elasticTimeIntegrator),
timeFilter_(timeIntegrator_->get_time_filter()),
displacement_(atcTransfer_->get_field(DISPLACEMENT)),
velocity_(atcTransfer_->get_field(VELOCITY)),
acceleration_(atcTransfer_->get_field_roc(VELOCITY)),
nodalAtomicDisplacement_(atcTransfer_->get_atomic_field(DISPLACEMENT)),
nodalAtomicVelocity_(atcTransfer_->get_atomic_field(VELOCITY)),
velocityRhs_(atcTransfer_->get_field_rhs(VELOCITY)),
nodalAtomicForce_(atcTransfer_->get_fe_atomic_field_roc(VELOCITY)),
forceFilteringData_(atcTransfer_->get_aux_storage(VELOCITY))
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticTimeIntegratorVerlet
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ElasticTimeIntegratorVerlet::ElasticTimeIntegratorVerlet(ElasticTimeIntegrator * elasticTimeIntegrator) :
ElasticIntegrationMethod(elasticTimeIntegrator)
{
TimeFilterManager * timeFilterManager = (timeIntegrator_->get_atc_transfer())->get_time_filter_manager();
if (timeFilterManager->need_reset()) {
timeFilter_->initialize(nodalAtomicForce_);
}
// reset filtering data, if needed
if (!(timeFilterManager->end_equilibrate())) {
forceFilteringData_.reset(atcTransfer_->get_nNodes(),atcTransfer_->get_nsd());
}
}
//--------------------------------------------------------
// mid_initial_integrate1
// time integration at the mid-point of Verlet step 1
//--------------------------------------------------------
void ElasticTimeIntegratorVerlet::mid_initial_integrate1(double dt)
{
explicit_1(velocity_,acceleration_,.5*dt);
}
//--------------------------------------------------------
// post_initial_integrate1
// time integration after Verlet step 1
//--------------------------------------------------------
void ElasticTimeIntegratorVerlet::post_initial_integrate1(double dt)
{
// NOTE could use explicit_2 with velocityRhs_ as the 2nd derivative
// for improved accuracy, but this would be inconsistent with
// the atomic integration scheme
explicit_1(displacement_,velocity_,dt);
}
//--------------------------------------------------------
// pre_final_integrate1
// first time integration computations
// before Verlet step 2
//--------------------------------------------------------
void ElasticTimeIntegratorVerlet::pre_final_integrate1(double dt)
{
// Compute MD contribution to FEM equation
DENS_MAT atomicForces;
atcTransfer_->compute_atomic_force(atomicForces,atcTransfer_->get_f());
atcTransfer_->restrict_volumetric_quantity(atomicForces,nodalAtomicForce_);
timeFilter_->apply_post_step2(forceFilteringData_,nodalAtomicForce_,dt);
}
//--------------------------------------------------------
// post_final_integrate1
// second time integration computations
// after Verlet step 2
//--------------------------------------------------------
void ElasticTimeIntegratorVerlet::post_final_integrate1(double dt)
{
atcTransfer_->apply_inverse_mass_matrix(velocityRhs_,
acceleration_,
VELOCITY);
explicit_1(velocity_,acceleration_,.5*dt);
}
//--------------------------------------------------------
// post_process
// post processing of variables before output
//--------------------------------------------------------
void ElasticTimeIntegratorVerlet::post_process(double dt)
{
DENS_MAT atomicQuantity;
atcTransfer_->compute_atomic_momentum(atomicQuantity,atcTransfer_->get_v());
atcTransfer_->project_md_volumetric_quantity(atomicQuantity,nodalAtomicVelocity_,VELOCITY);
atcTransfer_->compute_atomic_centerOfMass_displacement(atomicQuantity,atcTransfer_->get_x());
atcTransfer_->project_md_volumetric_quantity(atomicQuantity,nodalAtomicDisplacement_,VELOCITY);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticTimeIntegratorVerletFiltered
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ElasticTimeIntegratorVerletFiltered::ElasticTimeIntegratorVerletFiltered(ElasticTimeIntegrator * elasticTimeIntegrator) :
ElasticTimeIntegratorVerlet(elasticTimeIntegrator),
nodalAtomicAcceleration_(atcTransfer_->get_atomic_field_roc(VELOCITY))
{
// swap filtered and unfiltered forces
if ((timeIntegrator_->get_time_filter_manager())->end_equilibrate()) {
DENS_MAT temp(nodalAtomicForce_);
nodalAtomicForce_ = forceFilteringData_;
forceFilteringData_ = temp;
}
}
//--------------------------------------------------------
// mid_initial_integrate1
// time integration at the mid-point of Verlet step 1
//--------------------------------------------------------
void ElasticTimeIntegratorVerletFiltered::mid_initial_integrate1(double dt)
{
explicit_1(velocity_,acceleration_,.5*dt);
explicit_1(nodalAtomicVelocity_,nodalAtomicAcceleration_,.5*dt);
}
//--------------------------------------------------------
// post_initial_integrate1
// time integration after Verlet step 1
//--------------------------------------------------------
void ElasticTimeIntegratorVerletFiltered::post_initial_integrate1(double dt)
{
// NOTE could use explicit_2 with velocityRhs_ as the 2nd derivative
// for improved accuracy, but this would be inconsistent with
// the atomic integration scheme
explicit_1(displacement_,velocity_,dt);
explicit_1(nodalAtomicDisplacement_,nodalAtomicVelocity_,dt);
}
//--------------------------------------------------------
// pre_final_integrate1
// first time integration computations
// before Verlet step 2
//--------------------------------------------------------
void ElasticTimeIntegratorVerletFiltered::pre_final_integrate1(double dt)
{
// Compute MD contribution to FEM equation
DENS_MAT atomicForces;
atcTransfer_->compute_atomic_force(atomicForces,atcTransfer_->get_f());
// apply time filtering to instantaneous atomic force for FE equation
// NOTE would an explicit-implicit time filter be more accurate?
atcTransfer_->restrict_volumetric_quantity(atomicForces,forceFilteringData_);
timeFilter_->apply_post_step2(nodalAtomicForce_,forceFilteringData_,dt);
}
//--------------------------------------------------------
// post_final_integrate1
// second time integration computations
// after Verlet step 2
//--------------------------------------------------------
void ElasticTimeIntegratorVerletFiltered::post_final_integrate1(double dt)
{
DENS_MAT velocityRoc(velocityRhs_.nRows(),velocityRhs_.nCols());
atcTransfer_->apply_inverse_mass_matrix(velocityRhs_,
acceleration_,
VELOCITY);
explicit_1(velocity_,acceleration_,.5*dt);
atcTransfer_->apply_inverse_md_mass_matrix(nodalAtomicForce_,
nodalAtomicAcceleration_,
VELOCITY);
explicit_1(nodalAtomicVelocity_,nodalAtomicAcceleration_,.5*dt);
}
};

View File

@ -1,209 +0,0 @@
/** ElasticTimeIntegrator : a class to implement various elasticity integrators for FE quantities */
#ifndef ELASTIC_TIME_INTEGRATOR_H
#define ELASTIC_TIME_INTEGRATOR_H
// ATC_Transfer headers
#include "TimeIntegrator.h"
using namespace std;
namespace ATC {
// forward declarations
class ElasticIntegrationMethod;
/**
* @class ElasticTimeIntegrator
* @brief Base class fo various time integrators for elasticity FE quantities
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticTimeIntegrator
// Base class for elastic integrators which handles
// parsing and stores basic data structures
//--------------------------------------------------------
//--------------------------------------------------------
class ElasticTimeIntegrator : public TimeIntegrator {
public:
// constructor
ElasticTimeIntegrator(ATC_Transfer * atcTransfer,
TimeIntegrationType timeIntegrationType);
// destructor
virtual ~ElasticTimeIntegrator(){};
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
private:
// DO NOT define this
ElasticTimeIntegrator();
};
/**
* @class ElasticIntegrationMethod
* @brief Base class fo various time integration methods for elasticity FE quantities
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticIntegrationMethod
// Base class for elastic integration methods which
// update the FE quantities in time
//--------------------------------------------------------
//--------------------------------------------------------
class ElasticIntegrationMethod : public TimeIntegrationMethod {
public:
// constructor
ElasticIntegrationMethod(ElasticTimeIntegrator * elasticTimeIntegrator);
// destructor
virtual ~ElasticIntegrationMethod(){};
protected:
/** time filtering application object */
TimeFilter * timeFilter_;
/** finite element displacement field */
DENS_MAT & displacement_;
/** finite element velocity field */
DENS_MAT & velocity_;
/** finite element acceleration field */
DENS_MAT & acceleration_;
/** atomic nodal displacement field */
DENS_MAT & nodalAtomicDisplacement_;
/** atomic nodal velocity field */
DENS_MAT & nodalAtomicVelocity_;
/** right-hand side of velocity equation */
DENS_MAT & velocityRhs_;
/** force at nodes from atomic quantities */
DENS_MAT & nodalAtomicForce_;
/** filtered power for computation during equilibration */
DENS_MAT & forceFilteringData_;
private:
// DO NOT define this
ElasticIntegrationMethod();
};
/**
* @class ElasticTimeIntegratorVerlet
* @brief Verlet integration for FE elastic quantities
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticTimeIntegratorVerlet
// Uses the second order Verlet integration to update
// the finite element velocity and displacement
// fields, i.e. the same integration used for the
// atomic velocities and positions.
//--------------------------------------------------------
//--------------------------------------------------------
class ElasticTimeIntegratorVerlet : public ElasticIntegrationMethod {
public:
// constructor
ElasticTimeIntegratorVerlet(ElasticTimeIntegrator * elasticTimeIntegrator);
// destructor
virtual ~ElasticTimeIntegratorVerlet(){};
// time step methods, corresponding to ATC_Transfer
/** first part of mid_initial_integrate */
virtual void mid_initial_integrate1(double dt);
/** first part of post_initial_integrate */
virtual void post_initial_integrate1(double dt);
/** first part of pre_final_integrate */
virtual void pre_final_integrate1(double dt);
/** first part of post_final_integrate */
virtual void post_final_integrate1(double dt);
/** post processing step before output */
virtual void post_process(double dt);
private:
// DO NOT define this
ElasticTimeIntegratorVerlet();
};
/**
* @class ElasticTimeIntegratorVerlet
* @brief Verlet integration for FE elastic quantities with time filtering
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElasticTimeIntegratorVerletFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class ElasticTimeIntegratorVerletFiltered : public ElasticTimeIntegratorVerlet {
public:
// constructor
ElasticTimeIntegratorVerletFiltered(ElasticTimeIntegrator * elasticTimeIntegrator);
// destructor
virtual ~ElasticTimeIntegratorVerletFiltered(){};
// time step methods, corresponding to ATC_Transfer
/** first part of mid_initial_integrate */
virtual void mid_initial_integrate1(double dt);
/** first part of post_initial_integrate */
virtual void post_initial_integrate1(double dt);
/** first part of pre_final_integrate */
virtual void pre_final_integrate1(double dt);
/** first part of post_final_integrate */
virtual void post_final_integrate1(double dt);
/** post processing step before output */
virtual void post_process(double dt){};
protected:
/** atomic nodal acceleration field */
DENS_MAT & nodalAtomicAcceleration_;
private:
// DO NOT define this
ElasticTimeIntegratorVerletFiltered();
};
};
#endif

View File

@ -1,66 +0,0 @@
#include "ElectronFlux.h"
#include "StringManip.h"
#include "ATC_Error.h"
#include <iostream>
#include <fstream>
namespace ATC {
using namespace ATC_STRING;
ElectronFluxLinear::ElectronFluxLinear(
fstream &fileId, map<string,double> & parameters)
: ElectronFlux(),
electronMobility_(0),
electronDiffusivity_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
double value = str2dbl(line[1]);
if (line[0] == "mobility") {
electronMobility_ = value;
parameters["electron_mobility"] = electronMobility_;
}
else if (line[0] == "diffusivity") {
electronDiffusivity_ = value;
parameters["electron_diffusivity"] = electronDiffusivity_;
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
}
}
ElectronFluxThermopower::ElectronFluxThermopower(
fstream &fileId, map<string,double> & parameters)
: ElectronFlux(),
electronMobility_(0),
seebeckCoef_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
double value = str2dbl(line[1]);
if (line[0] == "mobility") {
electronMobility_ = value;
parameters["electron_mobility"] = electronMobility_;
}
else if (line[0] == "seebeck") {
seebeckCoef_ = value;
parameters["seebeck_coefficient"] = seebeckCoef_;
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
}
}
}

View File

@ -1,96 +0,0 @@
#ifndef ELECTRON_FLUX_H
#define ELECTRON_FLUX_H
#include <map>
#include <string>
using std::map;
using std::string;
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
namespace ATC {
class ElectronFlux
{
public:
ElectronFlux() {};
virtual ~ElectronFlux() {};
/** computes flux */
virtual void electron_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)=0;
};
//-----------------------------------------------------------------------
class ElectronFluxLinear : public ElectronFlux
{
public:
ElectronFluxLinear(fstream &matfile, map<string,double> & parameters);
virtual ~ElectronFluxLinear() {};
virtual void electron_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)
{
// J_n = - \mu n grad \phi - D grad n
const FIELD & n = (fields.find(ELECTRON_DENSITY))->second;
const GRAD_FIELD & dn =(gradFields.find(ELECTRON_DENSITY))->second;
const GRAD_FIELD & dphi =(gradFields.find(ELECTRIC_POTENTIAL))->second;
// NOTE use electron velocity instead
flux.push_back(-electronMobility_*dphi[0]);
flux.push_back(-electronMobility_*dphi[1]);
flux.push_back(-electronMobility_*dphi[2]);
flux[0] *= n; // scale by n to get : -n \mu grad(\phi)
flux[1] *= n;
flux[2] *= n;
flux[0] += -electronDiffusivity_* dn[0];
flux[1] += -electronDiffusivity_* dn[1];
flux[2] += -electronDiffusivity_* dn[2];
};
protected:
double electronMobility_, electronDiffusivity_;
};
//-----------------------------------------------------------------------
class ElectronFluxThermopower : public ElectronFlux
{
public:
ElectronFluxThermopower(fstream &matfile,map<string,double> & parameters);
virtual ~ElectronFluxThermopower() {};
virtual void electron_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)
{
static const double kB_ = 8.617343e-5;// [eV/K]
// J_n = - \mu n grad \phi - \mu kB/e T_e grad n
// - \mu S n grad T_e - \mu kB/e n grad T_e
const FIELD & n = (fields.find(ELECTRON_DENSITY))->second;
const GRAD_FIELD & dn =(gradFields.find(ELECTRON_DENSITY))->second;
const GRAD_FIELD & dphi =(gradFields.find(ELECTRIC_POTENTIAL))->second;
const GRAD_FIELD & dT =(gradFields.find(ELECTRON_TEMPERATURE))->second;
flux.push_back(-electronMobility_*dphi[0]);
flux.push_back(-electronMobility_*dphi[1]);
flux.push_back(-electronMobility_*dphi[2]);
double coef = -electronMobility_*(seebeckCoef_ + kB_);
flux[0] += coef* dT[0];
flux[1] += coef* dT[1];
flux[2] += coef* dT[2];
flux[0] *= n; // scale by n
flux[1] *= n;
flux[2] *= n;
GRAD_FIELD tmp = dn;
const FIELD & Te = (fields.find(ELECTRON_TEMPERATURE))->second;
tmp[0] *= Te;
tmp[1] *= Te;
tmp[2] *= Te;
coef = -electronMobility_*kB_; // kB: eV/K/e -> V/K
flux[0] += tmp[0];
flux[1] += tmp[1];
flux[2] += tmp[2];
};
protected:
double electronMobility_, seebeckCoef_;
};
}
#endif

View File

@ -1,54 +0,0 @@
#include "ElectronHeatCapacity.h"
#include "StringManip.h"
#include "ATC_Error.h"
#include <iostream>
#include <fstream>
namespace ATC {
using namespace ATC_STRING;
ElectronHeatCapacityConstant::ElectronHeatCapacityConstant(
fstream &fileId, map<string,double> & parameters)
: ElectronHeatCapacity(),
electronHeatCapacity_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
else if (line[0] == "capacity") {
electronHeatCapacity_ = str2dbl(line[1]);
parameters["electron_heat_capacity"] = electronHeatCapacity_;
}
else {
throw ATC_Error(0, "unrecognized material function:" + line[0]);
}
}
}
ElectronHeatCapacityLinear::ElectronHeatCapacityLinear(
fstream &fileId, map<string,double> & parameters)
: ElectronHeatCapacity(),
electronHeatCapacity_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
else if (line[0] == "capacity") {
electronHeatCapacity_ = str2dbl(line[1]);
parameters["electron_heat_capacity"] = electronHeatCapacity_;
}
else {
throw ATC_Error(0, "unrecognized material function: " + line[0]);
}
}
}
}

View File

@ -1,76 +0,0 @@
#ifndef ELECTRON_HEAT_CAPACITY_H
#define ELECTRON_HEAT_CAPACITY_H
#include <map>
#include <string>
using std::map;
using std::string;
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
namespace ATC {
class ElectronHeatCapacity
{
public:
ElectronHeatCapacity() {};
virtual ~ElectronHeatCapacity() {};
/** computes heat capacity */
virtual void electron_heat_capacity(const FIELDS &fields,
FIELD &capacity)=0;
/** computes thermal energy */
virtual void electron_thermal_energy(const FIELDS &fields,
FIELD &energy)=0;
};
//-------------------------------------------------------------------
class ElectronHeatCapacityConstant : public ElectronHeatCapacity
{
public:
ElectronHeatCapacityConstant(fstream &matfile,
map<string,double> & parameters);
virtual ~ElectronHeatCapacityConstant() {};
virtual void electron_heat_capacity(const FIELDS &fields,
FIELD &capacity)
{
const FIELD & T = (fields.find(ELECTRON_TEMPERATURE))->second;
capacity.reset(T.nRows(),T.nCols());
capacity = electronHeatCapacity_;
};
virtual void electron_thermal_energy(const FIELDS &fields,
FIELD &energy)
{
const FIELD & T = (fields.find(ELECTRON_TEMPERATURE))->second;
energy = electronHeatCapacity_ * T;
};
protected:
double electronHeatCapacity_;
};
//-------------------------------------------------------------------
class ElectronHeatCapacityLinear : public ElectronHeatCapacity
{
public:
ElectronHeatCapacityLinear(fstream &matfile,
map<string,double> & parameters);
virtual ~ElectronHeatCapacityLinear() {};
virtual void electron_heat_capacity(const FIELDS &fields,
FIELD &capacity)
{
const FIELD & T = (fields.find(ELECTRON_TEMPERATURE))->second;
capacity = electronHeatCapacity_*T;
};
virtual void electron_thermal_energy(const FIELDS &fields,
FIELD &energy)
{
const FIELD & T = (fields.find(ELECTRON_TEMPERATURE))->second;
energy = 0.5 * electronHeatCapacity_ * T;
energy *= T;
};
protected:
double electronHeatCapacity_;
};
}
#endif

View File

@ -1,80 +0,0 @@
#include "ElectronHeatFlux.h"
#include "StringManip.h"
#include "ATC_Error.h"
#include <iostream>
#include <fstream>
namespace ATC {
using namespace ATC_STRING;
ElectronHeatFluxLinear::ElectronHeatFluxLinear(
fstream &fileId, map<string,double> & parameters)
: ElectronHeatFlux(),
conductivity_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
else if (line[0] == "conductivity") {
conductivity_ = str2dbl(line[1]);
parameters["electron_thermal_conductivity"] = conductivity_;
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
}
}
ElectronHeatFluxPowerLaw::ElectronHeatFluxPowerLaw(
fstream &fileId, map<string,double> & parameters)
: ElectronHeatFlux(),
conductivity_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
else if (line[0] == "conductivity") {
conductivity_ = str2dbl(line[1]);
parameters["electron_thermal_conductivity"] = conductivity_;
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
}
}
ElectronHeatFluxThermopower::ElectronHeatFluxThermopower(
fstream &fileId, map<string,double> & parameters,
/*const*/ ElectronFlux * electronFlux)
: ElectronHeatFlux(),
electronFlux_(electronFlux),
conductivity_(0),
seebeckCoef_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
double value = str2dbl(line[1]);
if (line[0] == "conductivity") {
conductivity_ = value;
parameters["electron_thermal_conductivity"] = conductivity_;
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
seebeckCoef_ = parameters["seebeck_coefficient"];
}
}
}

View File

@ -1,112 +0,0 @@
#ifndef ELECTRON_HEAT_FLUX_H
#define ELECTRON_HEAT_FLUX_H
#include <map>
#include <string>
using std::map;
using std::string;
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
#include "ElectronFlux.h"
namespace ATC {
class ElectronHeatFlux
{
public:
ElectronHeatFlux() {};
virtual ~ElectronHeatFlux() {};
/** computes heat flux */
virtual void electron_heat_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)=0;
};
//-----------------------------------------------------------------------
class ElectronHeatFluxLinear : public ElectronHeatFlux
{
public:
ElectronHeatFluxLinear(fstream &matfile,map<string,double> & parameters);
virtual ~ElectronHeatFluxLinear() {};
virtual void electron_heat_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)
{
// flux = -ke dTe/dx
const GRAD_FIELD& dT = (gradFields.find(ELECTRON_TEMPERATURE))->second;
flux.push_back(-conductivity_ * dT[0]);
flux.push_back(-conductivity_ * dT[1]);
flux.push_back(-conductivity_ * dT[2]);
};
protected:
double conductivity_;
};
//-----------------------------------------------------------------------
class ElectronHeatFluxPowerLaw : public ElectronHeatFlux
{
public:
ElectronHeatFluxPowerLaw(fstream &matfile,map<string,double> &parameters);
virtual ~ElectronHeatFluxPowerLaw() {};
virtual void electron_heat_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)
{
// flux = -ke * ( Te / T ) dT;
const GRAD_FIELD dT = (gradFields.find(ELECTRON_TEMPERATURE))->second;
const FIELD & T = (fields.find(TEMPERATURE))->second;
const FIELD & Te = (fields.find(ELECTRON_TEMPERATURE))->second;
flux.push_back(dT[0]);
flux.push_back(dT[1]);
flux.push_back(dT[2]);
FIELD k_e;
k_e = (-conductivity_* Te) / T;
flux[0] *= k_e;
flux[1] *= k_e;
flux[2] *= k_e;
};
protected:
double conductivity_;
};
//-----------------------------------------------------------------------
class ElectronHeatFluxThermopower : public ElectronHeatFlux
{
public:
ElectronHeatFluxThermopower(fstream &matfile,
map<string,double> & parameters,
/*const*/ ElectronFlux * electronFlux = NULL);
virtual ~ElectronHeatFluxThermopower() {};
virtual void electron_heat_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux)
{
// flux = -ke * ( Te / T ) dT + pi J_e;
const GRAD_FIELD dT = (gradFields.find(ELECTRON_TEMPERATURE))->second;
const FIELD & T = (fields.find(TEMPERATURE))->second;
const FIELD & Te = (fields.find(ELECTRON_TEMPERATURE))->second;
flux.push_back(dT[0]);
flux.push_back(dT[1]);
flux.push_back(dT[2]);
FIELD k_e;
k_e = (-conductivity_* Te) / T;
flux[0] *= k_e;
flux[1] *= k_e;
flux[2] *= k_e;
GRAD_FIELD tmp;
electronFlux_->electron_flux(fields, gradFields, tmp);
tmp[0] *= Te;
tmp[1] *= Te;
tmp[2] *= Te;
flux[0] += seebeckCoef_*tmp[0];
flux[1] += seebeckCoef_*tmp[1];
flux[2] += seebeckCoef_*tmp[2];
};
protected:
double conductivity_,seebeckCoef_;
ElectronFlux * electronFlux_;
};
}
#endif

View File

@ -1,58 +0,0 @@
#include "ElectronPhononExchange.h"
#include "StringManip.h"
#include "ATC_Error.h"
#include <iostream>
#include <fstream>
namespace ATC {
using namespace ATC_STRING;
ElectronPhononExchangeLinear::ElectronPhononExchangeLinear(
fstream &fileId, map<string,double> & parameters)
: ElectronPhononExchange(),
exchangeCoef_(0)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
else if (line[0] == "coefficient") {
exchangeCoef_ = str2dbl(line[1]);
parameters["electron_phonon_exchange_coefficient"] = exchangeCoef_;
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
}
}
ElectronPhononExchangePowerLaw::ElectronPhononExchangePowerLaw(
fstream &fileId, map<string,double> & parameters)
: ElectronPhononExchange(),
exchangeCoef_(0),
exponent_(1)
{
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") return;
else if (line[0] == "coefficient") {
exchangeCoef_ = str2dbl(line[1]);
parameters["electron_phonon_exchange_coefficient"] = exchangeCoef_;
}
else if (line[0] == "exponent") {
exponent_ = str2int(line[1]);
}
else {
throw ATC_Error(0, "unrecognized material function "+line[0]);
}
}
}
}

View File

@ -1,69 +0,0 @@
#ifndef ELECTRON_PHONON_EXCHANGE_H
#define ELECTRON_PHONON_EXCHANGE_H
#include <map>
#include <string>
using std::map;
using std::string;
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
namespace ATC {
class ElectronPhononExchange
{
public:
ElectronPhononExchange() {};
virtual ~ElectronPhononExchange() {};
/** computes heat capacity */
virtual void electron_phonon_exchange(const FIELDS &fields,
DENS_MAT &flux)=0;
};
//-------------------------------------------------------------------
class ElectronPhononExchangeLinear : public ElectronPhononExchange
{
public:
ElectronPhononExchangeLinear(fstream &matfile,
map<string,double> & parameters);
virtual ~ElectronPhononExchangeLinear() {};
virtual void electron_phonon_exchange(const FIELDS &fields,
DENS_MAT &flux)
{
// flux = g * ( T- Te)
const FIELD & T = (fields.find(TEMPERATURE))->second;
const FIELD & Te = (fields.find(ELECTRON_TEMPERATURE))->second;
flux = Te;
flux -= T;
flux *= exchangeCoef_;
};
protected:
double exchangeCoef_;
};
//-------------------------------------------------------------------
class ElectronPhononExchangePowerLaw : public ElectronPhononExchange
{
public:
ElectronPhononExchangePowerLaw(fstream &matfile,
map<string,double> & parameters);
virtual ~ElectronPhononExchangePowerLaw() {};
virtual void electron_phonon_exchange(const FIELDS &fields,
DENS_MAT &flux)
{
// flux = g c_e T_e (T_e - T_p)^5 / T_e
const FIELD & T = (fields.find(TEMPERATURE))->second;
const FIELD & Te = (fields.find(ELECTRON_TEMPERATURE))->second;
flux = Te;
flux -= T;
flux = flux.pow(exponent_);
flux *= exchangeCoef_;
};
protected:
double exchangeCoef_;
int exponent_;
};
}
#endif

View File

@ -1,290 +0,0 @@
// ATC_Transfer Headers
#include "ExtrinsicModel.h"
#include "ExtrinsicModelTwoTemperature.h"
#include "ATC_Error.h"
#include "TimeIntegrator.h"
#include "ATC_Transfer.h"
#include "LammpsInterface.h"
#include "PrescribedDataManager.h"
#include "PhysicsModel.h"
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class ExtrinsicModelManager
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ExtrinsicModelManager::ExtrinsicModelManager(ATC_Transfer * atcTransfer) :
atcTransfer_(atcTransfer)
{
// do nothing
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
ExtrinsicModelManager::~ExtrinsicModelManager()
{
vector<ExtrinsicModel *>::iterator imodel;
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
delete *(imodel);
}
//--------------------------------------------------------
// modify
//--------------------------------------------------------
bool ExtrinsicModelManager::modify(int narg, char **arg)
{
FieldName thisField;
int thisIndex;
int argIndx = 0;
bool foundMatch = false;
// loop over models with command
vector<ExtrinsicModel *>::iterator imodel;
for(imodel=extrinsicModels_.begin();
imodel!=extrinsicModels_.end(); imodel++) {
foundMatch = (*imodel)->modify(narg,arg);
if (foundMatch) break;
}
return foundMatch;
}
//--------------------------------------------------------
// create_model
//--------------------------------------------------------
void ExtrinsicModelManager::create_model(ExtrinsicModelType modelType,
string matFileName)
{
string typeName;
bool validModel = model_to_string(modelType,typeName);
if (!validModel) {
throw ATC_Error(0,"Could not create extrinsic model");
return;
}
ExtrinsicModel * myModel;
if (modelType==TWO_TEMPERATURE) {
cout << "ATC: creating two_temperature extrinsic model \n";
myModel = new ExtrinsicModelTwoTemperature
(this,modelType,matFileName);
}
extrinsicModels_.push_back(myModel);
// add new fields to fields data
map<FieldName,int> fieldSizes;
myModel->get_num_fields(fieldSizes);
atcTransfer_->add_fields(fieldSizes);
}
//--------------------------------------------------------
// initialize
//--------------------------------------------------------
void ExtrinsicModelManager::initialize()
{
vector<ExtrinsicModel *>::iterator imodel;
for(imodel=extrinsicModels_.begin();
imodel!=extrinsicModels_.end(); imodel++) {
// initialize models
(*imodel)->initialize();
}
}
//--------------------------------------------------------
// size_vector
//--------------------------------------------------------
int ExtrinsicModelManager::size_vector(int intrinsicSize)
{
int extrinsicSize = 0;
vector<ExtrinsicModel *>::iterator imodel;
for(imodel=extrinsicModels_.begin();
imodel!=extrinsicModels_.end(); imodel++) {
// query all models for LAMMPS display
int currentSize = intrinsicSize + extrinsicSize;
extrinsicSize += (*imodel)->size_vector(currentSize);
}
return extrinsicSize;
}
//--------------------------------------------------------
// compute_vector
//--------------------------------------------------------
double ExtrinsicModelManager::compute_vector(int n)
{
double value = 0.;
vector<ExtrinsicModel *>::iterator imodel;
for(imodel=extrinsicModels_.begin();
imodel!=extrinsicModels_.end(); imodel++) {
// query all models for LAMMPS display
if ((*imodel)->compute_vector(n,value))
break;
}
return value;
}
//--------------------------------------------------------
// finish
//--------------------------------------------------------
void ExtrinsicModelManager::finish()
{
// do nothing
}
//--------------------------------------------------------
// pre_init_integrate
//--------------------------------------------------------
void ExtrinsicModelManager::pre_init_integrate(ExtrinsicModelType modelType)
{
vector<ExtrinsicModel *>::iterator imodel;
if (modelType == NUM_MODELS) {// execute all the models
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->pre_init_integrate();
}
else { // execute only requested type of model
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
if ((*imodel)->get_model_type() == modelType)
(*imodel)->pre_init_integrate();
}
}
//--------------------------------------------------------
// mid_init_integrate
//--------------------------------------------------------
void ExtrinsicModelManager::mid_init_integrate(ExtrinsicModelType modelType)
{
vector<ExtrinsicModel *>::iterator imodel;
if (modelType == NUM_MODELS) {// execute all the models
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->mid_init_integrate();
}
else { // execute only requested type of model
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
if ((*imodel)->get_model_type() == modelType)
(*imodel)->mid_init_integrate();
}
}
//--------------------------------------------------------
// post_init_integrate
//--------------------------------------------------------
void ExtrinsicModelManager::post_init_integrate(ExtrinsicModelType modelType)
{
vector<ExtrinsicModel *>::iterator imodel;
if (modelType == NUM_MODELS) {// execute all the models
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->post_init_integrate();
}
else { // execute only requested type of model
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
if ((*imodel)->get_model_type() == modelType)
(*imodel)->post_init_integrate();
}
}
//--------------------------------------------------------
// pre_final_integrate
//--------------------------------------------------------
void ExtrinsicModelManager::pre_final_integrate(ExtrinsicModelType modelType)
{
vector<ExtrinsicModel *>::iterator imodel;
if (modelType == NUM_MODELS) {// execute all the models
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->pre_final_integrate();
}
else { // execute only requested type of model
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
if ((*imodel)->get_model_type() == modelType)
(*imodel)->pre_final_integrate();
}
}
//--------------------------------------------------------
// post_final_integrate
//--------------------------------------------------------
void ExtrinsicModelManager::post_final_integrate(ExtrinsicModelType modelType)
{
vector<ExtrinsicModel *>::iterator imodel;
if (modelType == NUM_MODELS) {// execute all the models
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->post_final_integrate();
}
else { // execute only requested type of model
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
if ((*imodel)->get_model_type() == modelType)
(*imodel)->post_final_integrate();
}
}
//--------------------------------------------------------
// set_sources
//--------------------------------------------------------
void ExtrinsicModelManager::set_sources(FIELDS & fields, FIELDS & sources, ExtrinsicModelType modelType)
{
vector<ExtrinsicModel *>::iterator imodel;
if (modelType == NUM_MODELS) {// execute all the models
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->set_sources(fields,sources);
}
else { // execute only requested type of model
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
if ((*imodel)->get_model_type() == modelType)
(*imodel)->set_sources(fields,sources);
}
}
//--------------------------------------------------------
// output
//--------------------------------------------------------
void ExtrinsicModelManager::output(double dt,OUTPUT_LIST & outputData)
{
vector<ExtrinsicModel *>::iterator imodel;
for(imodel=extrinsicModels_.begin(); imodel!=extrinsicModels_.end(); imodel++)
(*imodel)->output(dt,outputData);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ExtrinsicModel
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ExtrinsicModel::ExtrinsicModel(ExtrinsicModelManager * modelManager,
ExtrinsicModelType modelType,
string matFileName) :
modelManager_(modelManager),
modelType_(modelType),
atc_(modelManager->get_atc_transfer()),
physicsModel_(NULL)
{
rhsMaskIntrinsic_.reset(NUM_FIELDS,NUM_FLUX);
rhsMaskIntrinsic_ = false;
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
ExtrinsicModel::~ExtrinsicModel()
{
if (physicsModel_) delete physicsModel_;
}
//--------------------------------------------------------
// get_num_fields
// - sets dict of fields
//--------------------------------------------------------
void ExtrinsicModel::get_num_fields(map<FieldName,int> & fieldSizes)
{
physicsModel_->get_num_fields(fieldSizes,atc_->fieldMask_); // NOTE clunky
}
};

View File

@ -1,228 +0,0 @@
#ifndef EXTRINSIC_MODEL
#define EXTRINSIC_MODEL
// ATC_Transfer headers
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
using namespace std;
namespace ATC {
// forward declarations
class ATC_Transfer;
class ExtrinsicModel;
class PhysicsModel;
/** enumeration for the model types avaiable */
enum ExtrinsicModelType {
NO_MODEL=0,
TWO_TEMPERATURE,
NUM_MODELS
};
/**
* @class ExtrinsicModelManager
* @brief Handles parsing and parameter storage extrinsic models
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ExtrinsicModelManager
//--------------------------------------------------------
//--------------------------------------------------------
class ExtrinsicModelManager {
public:
// constructor
ExtrinsicModelManager(ATC_Transfer * atcTransfer);
// destructor
~ExtrinsicModelManager();
/** parser/modifier */
bool modify(int narg, char **arg);
/** create_model */
void create_model(ExtrinsicModelType modelType, string matFileName);
/** pre time integration */
void initialize();
/** set up LAMMPS display variables */
int size_vector(int intrinsicSize);
/** get LAMMPS display variables */
double compute_vector(int n);
/** post integration run */
// is this called at end of run or simulation
void finish();
// calls during LAMMPS Velocity-Verlet integration
/** Predictor phase, executed before Verlet */
void pre_init_integrate(ExtrinsicModelType modelType = NUM_MODELS);
/** Predictor phase, executed between velocity and position Verlet */
void mid_init_integrate(ExtrinsicModelType modelType = NUM_MODELS);
/** Predictor phase, executed after Verlet */
void post_init_integrate(ExtrinsicModelType modelType = NUM_MODELS);
/** Corrector phase, executed before Verlet */
void pre_final_integrate(ExtrinsicModelType modelType = NUM_MODELS);
/** Corrector phase, executed after Verlet*/
void post_final_integrate(ExtrinsicModelType modelType = NUM_MODELS);
/** get source terms for AtC equations */
void set_sources(FIELDS & fields, FIELDS & sources,
ExtrinsicModelType modelType = NUM_MODELS);
/** return output data to main AtC */
void output(double dt,OUTPUT_LIST & outputData);
/** model name enum to string */
static bool model_to_string(const ExtrinsicModelType index, string & name)
{
switch (index) {
case NO_MODEL:
name = "no_model";
break;
case TWO_TEMPERATURE:
name = "two_temperature";
break;
default:
return false;
break;
}
return true;
};
/** string to model enum */
static bool string_to_model(const string & name, ExtrinsicModelType & index)
{
if (name=="no_model")
index = NO_MODEL;
else if (name=="two_temperature")
index = TWO_TEMPERATURE;
else
return false;
return true;
};
/** access to ATC transfer object */
ATC_Transfer * get_atc_transfer() {return atcTransfer_;};
protected:
/** associated ATC_Transfer object */
ATC_Transfer * atcTransfer_;
/** equation hanlder */
vector<ExtrinsicModel *> extrinsicModels_;
private:
ExtrinsicModelManager(); // DO NOT define this, only use constructor above
};
/**
* @class ExtrinsicModel
* @brief base class for functionality of all extrinsic models
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ExtrinsicModel
//--------------------------------------------------------
//--------------------------------------------------------
class ExtrinsicModel {
public:
// constructor
ExtrinsicModel(ExtrinsicModelManager * modelManager,
ExtrinsicModelType modelType,
string matFileName);
// destructor
virtual ~ExtrinsicModel();
/** parser/modifier */
virtual bool modify(int narg, char **arg) {return false;};
/** pre time integration */
virtual void initialize(){};
/** set up LAMMPS display variables */
virtual int size_vector(int externalSize) {return 0;};
/** get LAMMPS display variables */
virtual bool compute_vector(int n, double & value) {return false;};
/** post integration run */
// is this called at end of run or simulation
virtual void finish(){};
/** Predictor phase, executed before Verlet */
virtual void pre_init_integrate(){};
/** Predictor phase, executed between velocity and position Verlet */
virtual void mid_init_integrate(){};
/** Predictor phase, executed after Verlet */
virtual void post_init_integrate(){};
/** Corrector phase, executed before Verlet */
virtual void pre_final_integrate(){};
/** Corrector phase, Verlet second step for velocity */
virtual void final_integrate(){};
/** Corrector phase, executed after Verlet*/
virtual void post_final_integrate(){};
/** Set sources to AtC equation */
virtual void set_sources(FIELDS & fields, FIELDS & sources){};
/** Add model-specific output data */
virtual void output(double dt, OUTPUT_LIST & outputData){};
/** get the fields and their sizes */
void get_num_fields(map<FieldName,int> & fieldSizes);
/** return the type of model being used */
ExtrinsicModelType get_model_type() {return modelType_;};
protected:
ExtrinsicModel(){};
/** ATC transfer object */
ATC_Transfer * atc_;
/** model manager object */
ExtrinsicModelManager * modelManager_;
/** tag for model type */
ExtrinsicModelType modelType_;
/** list of model fields in this model */
std::map<FieldName, int> fieldSizes_;
/** definition for physics used in this model */
PhysicsModel * physicsModel_;
/** rhs */
FIELDS rhs_;
/** rhs mask for coupling with MD */
Array2D<bool> rhsMaskIntrinsic_;
GRAD_FIELDS fluxes_;
};
};
#endif

View File

@ -1,265 +0,0 @@
// ATC_Transfer Headers
#include "ExtrinsicModelTwoTemperature.h"
#include "ATC_Error.h"
#include "FieldEulerIntegrator.h"
#include "ATC_Transfer.h"
#include "LammpsInterface.h"
#include "PrescribedDataManager.h"
#include "PhysicsModelTwoTemperature.h"
#include "ImplicitSolveOperator.h"
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class ExtrinsicModelTwoTemperature
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ExtrinsicModelTwoTemperature::ExtrinsicModelTwoTemperature
(ExtrinsicModelManager * modelManager,
ExtrinsicModelType modelType,
string matFileName) :
ExtrinsicModel(modelManager,modelType,matFileName),
nsubcycle_(1),
electronTimeIntegration_(TimeIntegrator::IMPLICIT),
temperatureIntegrator_(NULL),
exchangeFlag_(true),
baseSize_(0)
{
physicsModel_ = new PhysicsModelTwoTemperature(matFileName,
modelManager->get_atc_transfer());
// set up correct masks for coupling
rhsMaskIntrinsic_.reset(NUM_FIELDS,NUM_FLUX);
rhsMaskIntrinsic_ = false;
rhsMaskIntrinsic_(TEMPERATURE,SOURCE) = true;
atc_->fieldMask_(TEMPERATURE,EXTRINSIC_SOURCE) = true;
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
ExtrinsicModelTwoTemperature::~ExtrinsicModelTwoTemperature()
{
}
//--------------------------------------------------------
// modify
//--------------------------------------------------------
bool ExtrinsicModelTwoTemperature::modify(int narg, char **arg)
{
bool match = false;
int argIndx = 0;
// energy exchange switch
/*! \page man_extrinsic_exchange fix_modify AtC extrinsic exchange
\section syntax
fix_modify AtC extrinsic exchange <on|off>
\section examples
<TT> fix_modify AtC extrinsic exchange on </TT> \n
\section description
Switches energy exchange between the MD system and electron system on and off
\section restrictions
Only valid for use with two_temperature type of AtC fix.
\section related
see \ref man_fix_atc
\section default
on
*/
if (strcmp(arg[argIndx],"exchange")==0) {
argIndx++;
if (strcmp(arg[argIndx],"off")==0) {
exchangeFlag_ = false;
rhsMaskIntrinsic_(TEMPERATURE,SOURCE) = false;
atc_->fieldMask_(ELECTRON_TEMPERATURE,SOURCE) = false;
atc_->fieldMask_(TEMPERATURE,EXTRINSIC_SOURCE) = false;
}
else {
exchangeFlag_ = true;
rhsMaskIntrinsic_(TEMPERATURE,SOURCE) = true;
atc_->fieldMask_(ELECTRON_TEMPERATURE,SOURCE) = true;
atc_->fieldMask_(TEMPERATURE,EXTRINSIC_SOURCE) = true;
}
match = true;
} // end "exchange"
// electron integration type
/*! \page man_electron_integration fix_modify AtC extrinsic electron_integration
\section syntax
fix_modify AtC extrinsic electron_integration <integration_type> <num_subcyle_steps(optional)> \n
- integration_type (string) = explicit | implicit | steady \n
- num_subcycle_steps (int), optional = number of subcycle steps for the electron time integration
\section examples
<TT> fix_modify AtC extrinsic electron_integration implicit </TT> \n
<TT> fix_modify AtC extrinsic electron_integration explicit 100 </TT> \n
\section description
Switches between integration scheme for the electron temperature. The number of subcyling steps used to integrate the electron temperature 1 LAMMPS timestep can be manually adjusted to capture fast electron dynamics.
\section restrictions
For use only with two_temperature type of AtC fix ( see \ref man_fix_atc ) \n
\section default
implicit\n
subcycle_steps = 1
*/
else if (strcmp(arg[argIndx],"electron_integration")==0) {
argIndx++;
nsubcycle_ = 1;
if (strcmp(arg[argIndx],"explicit")==0) {
electronTimeIntegration_ = TimeIntegrator::EXPLICIT;
match = true;
}
else if (strcmp(arg[argIndx],"implicit")==0) {
electronTimeIntegration_ = TimeIntegrator::IMPLICIT;
match = true;
}
else if (strcmp(arg[argIndx],"steady")==0) {
electronTimeIntegration_ = TimeIntegrator::STEADY;
match = true;
}
if (narg > ++argIndx) nsubcycle_ = atoi(arg[argIndx]);
} // end "electron_integration"
if (!match) {
match = ExtrinsicModel::modify(narg, arg);
}
return match;
}
//--------------------------------------------------------
// initialize
//--------------------------------------------------------
void ExtrinsicModelTwoTemperature::initialize()
{
int nNodes = atc_->get_fe_engine()->get_nNodes();
rhs_[TEMPERATURE].reset(nNodes,1);
rhs_[ELECTRON_TEMPERATURE].reset(nNodes,1);
// set up electron temperature integrator
Array2D <bool> rhsMask(NUM_FIELDS,NUM_FLUX);
rhsMask = false;
for (int i = 0; i < NUM_FLUX; i++) {
rhsMask(ELECTRON_TEMPERATURE,i) = atc_->fieldMask_(ELECTRON_TEMPERATURE,i);
}
if (temperatureIntegrator_) delete temperatureIntegrator_;
if (electronTimeIntegration_ == TimeIntegrator::STEADY) {
throw ATC_Error(0,"not implemented");
}
else if (electronTimeIntegration_ == TimeIntegrator::IMPLICIT) {
double alpha = 1; // backwards Euler
temperatureIntegrator_ = new FieldImplicitEulerIntegrator(
ELECTRON_TEMPERATURE, physicsModel_, atc_->get_fe_engine(), atc_,
rhsMask, alpha);
}
else {
temperatureIntegrator_ = new FieldExplicitEulerIntegrator(
ELECTRON_TEMPERATURE, physicsModel_, atc_->get_fe_engine(), atc_,
rhsMask);
}
// set up mass matrix
Array<FieldName> massMask(1);
massMask = ELECTRON_TEMPERATURE;
(atc_->feEngine_)->compute_lumped_mass_matrix(massMask,atc_->fields_,physicsModel_,atc_->elementToMaterialMap_,atc_->massMats_);
atc_->massMatInv_[ELECTRON_TEMPERATURE] = inv(atc_->massMats_[ELECTRON_TEMPERATURE]);
}
//--------------------------------------------------------
// pre initial integration
//--------------------------------------------------------
void ExtrinsicModelTwoTemperature::pre_init_integrate()
{
double dt = atc_->lammpsInterface_->dt();
double time = atc_->simTime_;
// integrate fast electron variable/s
// note: atc calls set_sources in pre_final_integrate
atc_->set_fixed_nodes();
double idt = dt/nsubcycle_;
for (int i = 0; i < nsubcycle_ ; ++i) {
temperatureIntegrator_->update(idt,time,atc_->fields_,rhs_);
}
}
//--------------------------------------------------------
// set coupling source terms
//--------------------------------------------------------
void ExtrinsicModelTwoTemperature::set_sources(FIELDS & fields, FIELDS & sources)
{
// compute source term with appropriate masking and physics model
atc_->evaluate_rhs_integral(rhsMaskIntrinsic_, fields,
sources,
atc_->FULL_DOMAIN, physicsModel_);
}
//--------------------------------------------------------
// output
//--------------------------------------------------------
void ExtrinsicModelTwoTemperature::output(double dt, OUTPUT_LIST & outputData)
{
// nodal data
outputData["dot_electron_temperature"]
= & rhs_[ELECTRON_TEMPERATURE];
// global data
if (atc_->lammpsInterface_->comm_rank() == 0) {
double T_mean = atc_->fields_[ELECTRON_TEMPERATURE].col_sum(0)/atc_->nNodes_;
atc_->feEngine_->add_global("electron_temperature_mean", T_mean);
double T_stddev = atc_->fields_[ELECTRON_TEMPERATURE].col_stdev(0);
atc_->feEngine_->add_global("electron_temperature_std_dev", T_stddev);
}
}
//--------------------------------------------------------
// size_vector
//--------------------------------------------------------
int ExtrinsicModelTwoTemperature::size_vector(int intrinsicSize)
{
baseSize_ = intrinsicSize;
return 2;
}
//--------------------------------------------------------
// compute_vector
//--------------------------------------------------------
bool ExtrinsicModelTwoTemperature::compute_vector(int n, double & value)
{
// output[1] = total electron energy
// output[2] = average electron temperature
if (n == baseSize_) {
Array<FieldName> mask(1);
FIELDS energy;
mask(0) = ELECTRON_TEMPERATURE;
(atc_->feEngine_)->compute_energy(mask,
atc_->fields_,
physicsModel_,
atc_->elementToMaterialMap_,
energy);
// convert to lammps energy units
double mvv2e = (atc_->lammpsInterface_)->mvv2e();
double electronEnergy = mvv2e * energy[ELECTRON_TEMPERATURE].col_sum();
value = electronEnergy;
return true;
}
else if (n == baseSize_+1) {
double electronTemperature = (atc_->fields_[ELECTRON_TEMPERATURE]).col_sum()/(atc_->nNodes_);
value = electronTemperature;
return true;
}
return false;
}
};

View File

@ -1,82 +0,0 @@
#ifndef EXTRINSIC_MODEL_TWO_TEMPERATURE
#define EXTRINSIC_MODEL_TWO_TEMPERATURE
// ATC_Transfer headers
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
#include "ExtrinsicModel.h"
#include "FieldEulerIntegrator.h"
using namespace std;
namespace ATC {
// forward declarations
class ATC_Transfer;
class PrescribedDataManager;
class ExtrinsicModel;
class PhysicsModel;
/**
* @class ExtrinsicModelTwoTemperature
* @brief add electron temperature physics to phonon physics
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ExtrinsicModelTwoTemperature
//--------------------------------------------------------
//--------------------------------------------------------
class ExtrinsicModelTwoTemperature : public ExtrinsicModel {
public:
// constructor
ExtrinsicModelTwoTemperature(ExtrinsicModelManager * modelManager,
ExtrinsicModelType modelType,
string matFileName);
// destructor
virtual ~ExtrinsicModelTwoTemperature();
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
/** set up LAMMPS display variables */
virtual int size_vector(int externalSize);
/** get LAMMPS display variables */
virtual bool compute_vector(int n, double & value);
/** Predictor phase, executed before Verlet */
virtual void pre_init_integrate();
/** Set sources to AtC equation */
virtual void set_sources(FIELDS & fields, FIELDS & sources);
/** Add model-specific output data */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
/** electron time integration flag */
TimeIntegrator::TimeIntegrationType electronTimeIntegration_;
/** electron time integration flag */
FieldEulerIntegrator * temperatureIntegrator_;
/** number of electron time integration subscycles */
int nsubcycle_;
/** flag for turning off exchange during equilibration */
bool exchangeFlag_;
/** offset/size for LAMMPS display output */
int baseSize_;
};
};
#endif

View File

@ -1,515 +0,0 @@
// ATC header files
#include "ATC_Error.h"
#include "FE_Element.h"
#include "FE_Mesh.h"
// Other headers
#include "math.h"
namespace ATC {
// -------------------------------------------------------------
// -------------------------------------------------------------
// class FE_Element
// -------------------------------------------------------------
// -------------------------------------------------------------
FE_Element::FE_Element(FE_Mesh * feMesh,
int nSD,
int numEltNodes,
int numIPs,
int numFaces,
int numFaceNodes,
int numFaceIPs)
: feMesh_(feMesh),
nSD_(nSD),
numEltNodes_(numEltNodes),
numIPs_(numIPs),
numFaces_(numFaces),
numFaceNodes_(numFaceNodes),
numFaceIPs_(numFaceIPs),
localCoords_(nSD,numEltNodes),
ipCoords_(nSD,numIPs),
N_(numIPs,numEltNodes),
ipWeights_(numIPs),
localFaceConn_(numFaces,numFaceNodes),
ipFace2DCoords_(nSD-1,numFaceIPs),
ipFaceCoords_(numFaces),
// localFaceCoords_(nSD-1,numFaceNodes),
NFace_(numFaces),
ipFaceWeights_(numFaceIPs)
{
for (int f = 0; f < numFaces; f++) {
ipFaceCoords_[f].reset(nSD,numFaceIPs);
NFace_[f].reset(numFaceIPs,numEltNodes);
}
}
FE_Element::~FE_Element()
{
// Nothing else to do
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// class FE_ElementHex
// -------------------------------------------------------------
// -------------------------------------------------------------
FE_ElementHex::FE_ElementHex(FE_Mesh * feMesh)
: FE_Element(feMesh, 3, 8, 8, 6, 4, 4)
{
// Matrix of local nodal coordinates
localCoords_(0,0) = -1; localCoords_(1,0) = -1; localCoords_(2,0) = -1;
localCoords_(0,1) = +1; localCoords_(1,1) = -1; localCoords_(2,1) = -1;
localCoords_(0,2) = +1; localCoords_(1,2) = +1; localCoords_(2,2) = -1;
localCoords_(0,3) = -1; localCoords_(1,3) = +1; localCoords_(2,3) = -1;
localCoords_(0,4) = -1; localCoords_(1,4) = -1; localCoords_(2,4) = +1;
localCoords_(0,5) = +1; localCoords_(1,5) = -1; localCoords_(2,5) = +1;
localCoords_(0,6) = +1; localCoords_(1,6) = +1; localCoords_(2,6) = +1;
localCoords_(0,7) = -1; localCoords_(1,7) = +1; localCoords_(2,7) = +1;
// 3 --- 2
// /| /|
// / 0 --/ 1 y
// 7 --- 6 / |
// | |/ |
// 4 --- 5 ---> x
// /
// /
// z
// Matrix of local face connectivity
// -x
localFaceConn_(0,0) = 0;
localFaceConn_(0,1) = 4;
localFaceConn_(0,2) = 7;
localFaceConn_(0,3) = 3;
// +x
localFaceConn_(1,0) = 1;
localFaceConn_(1,1) = 2;
localFaceConn_(1,2) = 6;
localFaceConn_(1,3) = 5;
// -y
localFaceConn_(2,0) = 0;
localFaceConn_(2,1) = 1;
localFaceConn_(2,2) = 5;
localFaceConn_(2,3) = 4;
// +y
localFaceConn_(3,0) = 2;
localFaceConn_(3,1) = 3;
localFaceConn_(3,2) = 7;
localFaceConn_(3,3) = 6;
// -z
localFaceConn_(4,0) = 0;
localFaceConn_(4,1) = 3;
localFaceConn_(4,2) = 2;
localFaceConn_(4,3) = 1;
// +z
localFaceConn_(5,0) = 4;
localFaceConn_(5,1) = 5;
localFaceConn_(5,2) = 6;
localFaceConn_(5,3) = 7;
/*
localFaceCoords_(0,0) = -1; localFaceCoords_(1,0) = -1;
localFaceCoords_(0,1) = +1; localFaceCoords_(1,1) = -1;
localFaceCoords_(0,2) = +1; localFaceCoords_(1,2) = +1;
localFaceCoords_(0,3) = -1; localFaceCoords_(1,3) = +1;
*/
set_quadrature(GAUSSIAN_QUADRATURE);
}
//-----------------------------------------------------------------
void FE_ElementHex::set_quadrature(int quadrature)
{
double a = 1./sqrt(3.);
if (quadrature == NODAL_QUADRATURE) {
a = 1.0;
}
// Matrix of integration point locations (Gaussian) & follows local conn
ipCoords_(0,0) = -a; ipCoords_(1,0) = -a; ipCoords_(2,0) = -a;
ipCoords_(0,1) = +a; ipCoords_(1,1) = -a; ipCoords_(2,1) = -a;
ipCoords_(0,2) = +a; ipCoords_(1,2) = +a; ipCoords_(2,2) = -a;
ipCoords_(0,3) = -a; ipCoords_(1,3) = +a; ipCoords_(2,3) = -a;
ipCoords_(0,4) = -a; ipCoords_(1,4) = -a; ipCoords_(2,4) = +a;
ipCoords_(0,5) = +a; ipCoords_(1,5) = -a; ipCoords_(2,5) = +a;
ipCoords_(0,6) = +a; ipCoords_(1,6) = +a; ipCoords_(2,6) = +a;
ipCoords_(0,7) = -a; ipCoords_(1,7) = +a; ipCoords_(2,7) = +a;
// Compute shape functions at ip's
for (int ip = 0; ip < numIPs_; ip++) {
double r = ipCoords_(0, ip);
double s = ipCoords_(1, ip);
double t = ipCoords_(2, ip);
for (int iNode = 0; iNode < numEltNodes_; iNode++) {
double rI = localCoords_(0, iNode);
double sI = localCoords_(1, iNode);
double tI = localCoords_(2, iNode);
N_(ip, iNode) = 0.125 * (1 + r*rI) * (1 + s*sI) * (1 + t*tI);
}
}
// Integration point weights
ipWeights_ = 1.0;
// integration points by face
ipFace2DCoords_(0,0)=-a; ipFace2DCoords_(1,0)=-a;
ipFace2DCoords_(0,1)= a; ipFace2DCoords_(1,1)=-a;
ipFace2DCoords_(0,2)= a; ipFace2DCoords_(1,2)= a;
ipFace2DCoords_(0,3)=-a; ipFace2DCoords_(1,3)= a;
ipFaceCoords_[0](0,0)=-1;ipFaceCoords_[0](1,0)=-a;ipFaceCoords_[0](2,0)=-a;
ipFaceCoords_[0](0,1)=-1;ipFaceCoords_[0](1,1)= a;ipFaceCoords_[0](2,1)=-a;
ipFaceCoords_[0](0,2)=-1;ipFaceCoords_[0](1,2)= a;ipFaceCoords_[0](2,2)= a;
ipFaceCoords_[0](0,3)=-1;ipFaceCoords_[0](1,3)=-a;ipFaceCoords_[0](2,3)= a;
ipFaceCoords_[1](0,0)= 1;ipFaceCoords_[1](1,0)=-a;ipFaceCoords_[1](2,0)=-a;
ipFaceCoords_[1](0,1)= 1;ipFaceCoords_[1](1,1)= a;ipFaceCoords_[1](2,1)=-a;
ipFaceCoords_[1](0,2)= 1;ipFaceCoords_[1](1,2)= a;ipFaceCoords_[1](2,2)= a;
ipFaceCoords_[1](0,3)= 1;ipFaceCoords_[1](1,3)=-a;ipFaceCoords_[1](2,3)= a;
ipFaceCoords_[2](0,0)=-a;ipFaceCoords_[2](1,0)=-1;ipFaceCoords_[2](2,0)=-a;
ipFaceCoords_[2](0,1)=-a;ipFaceCoords_[2](1,1)=-1;ipFaceCoords_[2](2,1)= a;
ipFaceCoords_[2](0,2)= a;ipFaceCoords_[2](1,2)=-1;ipFaceCoords_[2](2,2)= a;
ipFaceCoords_[2](0,3)= a;ipFaceCoords_[2](1,3)=-1;ipFaceCoords_[2](2,3)=-a;
ipFaceCoords_[3](0,0)=-a;ipFaceCoords_[3](1,0)= 1;ipFaceCoords_[3](2,0)=-a;
ipFaceCoords_[3](0,1)=-a;ipFaceCoords_[3](1,1)= 1;ipFaceCoords_[3](2,1)= a;
ipFaceCoords_[3](0,2)= a;ipFaceCoords_[3](1,2)= 1;ipFaceCoords_[3](2,2)= a;
ipFaceCoords_[3](0,3)= a;ipFaceCoords_[3](1,3)= 1;ipFaceCoords_[2](2,3)=-a;
ipFaceCoords_[4](0,0)=-a;ipFaceCoords_[4](1,0)=-a;ipFaceCoords_[4](2,0)=-1;
ipFaceCoords_[4](0,1)= a;ipFaceCoords_[4](1,1)=-a;ipFaceCoords_[4](2,1)=-1;
ipFaceCoords_[4](0,2)= a;ipFaceCoords_[4](1,2)= a;ipFaceCoords_[4](2,2)=-1;
ipFaceCoords_[4](0,3)=-a;ipFaceCoords_[4](1,3)= a;ipFaceCoords_[4](2,3)=-1;
ipFaceCoords_[5](0,0)=-a;ipFaceCoords_[5](1,0)=-a;ipFaceCoords_[5](2,0)= 1;
ipFaceCoords_[5](0,1)= a;ipFaceCoords_[5](1,1)=-a;ipFaceCoords_[5](2,1)= 1;
ipFaceCoords_[5](0,2)= a;ipFaceCoords_[5](1,2)= a;ipFaceCoords_[5](2,2)= 1;
ipFaceCoords_[5](0,3)=-a;ipFaceCoords_[5](1,3)= a;ipFaceCoords_[5](2,3)= 1;
// Compute shape functions at ip's
for (int f = 0; f < numFaces_; f++) {
for (int ip = 0; ip < numFaceIPs_; ip++) {
double r = ipFaceCoords_[f](0, ip);
double s = ipFaceCoords_[f](1, ip);
double t = ipFaceCoords_[f](2, ip);
for (int iNode = 0; iNode < numEltNodes_; iNode++) {
double rI = localCoords_(0, iNode);
double sI = localCoords_(1, iNode);
double tI = localCoords_(2, iNode);
NFace_[f](ip, iNode) = 0.125 * (1 + r*rI) * (1 + s*sI) * (1 + t*tI);
}
}
}
// integration points
ipFaceWeights_ = 1.0;
}
FE_ElementHex::~FE_ElementHex()
{
// Nothing to do here
}
// -------------------------------------------------------------
// shape_function
// -------------------------------------------------------------
void FE_ElementHex::shape_function(const int eltID,
DENS_MAT &N,
vector<DENS_MAT> &dN,
DIAG_MAT &weights)
{
// Get element node coordinates from mesh
DENS_MAT xCoords;
feMesh_->element_coordinates(eltID, xCoords);
// Transpose xCoords
DENS_MAT xCoordsT(transpose(xCoords));
// Shape functions are simply the canonical element values
N = N_;
// Set sizes of matrices and vectors
if ((int)dN.size() != nSD_) dN.resize(nSD_);
for (int isd = 0; isd < nSD_; isd++) dN[isd].resize(numIPs_, numEltNodes_);
weights.resize(numIPs_,numIPs_);
// Create some temporary matrices:
// Shape function deriv.'s w.r.t. element coords
DENS_MAT dNdr(nSD_, numEltNodes_, false);
// Jacobian matrix: [dx/dr dy/ds dz/dt | dx/ds ... ]
DENS_MAT dxdr, drdx, dNdx;
// Loop over integration points
for (int ip = 0; ip < numIPs_; ip++) {
const double &r = ipCoords_(0,ip);
const double &s = ipCoords_(1,ip);
const double &t = ipCoords_(2,ip);
// Fill dNdr
for (int inode = 0; inode < numEltNodes_; inode++) {
const double &rI = localCoords_(0,inode);
const double &sI = localCoords_(1,inode);
const double &tI = localCoords_(2,inode);
dNdr(0,inode) = 0.125 * rI * (1 + s*sI) * (1 + t*tI);
dNdr(1,inode) = 0.125 * sI * (1 + r*rI) * (1 + t*tI);
dNdr(2,inode) = 0.125 * tI * (1 + r*rI) * (1 + s*sI);
}
// Compute dx/dxi matrix
dxdr = dNdr * xCoordsT;
drdx = inv(dxdr);
// Compute dNdx and fill dN matrix
dNdx = drdx*dNdr;
for (int isd = 0; isd < nSD_; isd++)
for (int inode = 0; inode < numEltNodes_; inode++)
dN[isd](ip,inode) = dNdx(isd,inode);
// Compute jacobian determinant of dxdr at this ip
double J = dxdr(0,0) * ( dxdr(1,1)*dxdr(2,2) - dxdr(2,1)*dxdr(1,2) )
- dxdr(0,1) * ( dxdr(1,0)*dxdr(2,2) - dxdr(1,2)*dxdr(2,0) )
+ dxdr(0,2) * ( dxdr(1,0)*dxdr(2,1) - dxdr(1,1)*dxdr(2,0) );
// Compute ip weight
weights(ip,ip) = ipWeights_(ip)*J;
}
}
//-----------------------------------------------------------------
void FE_ElementHex::shape_function(const int eltID,
const VECTOR &xi,
DENS_VEC &N)
{
N.resize(numEltNodes_);
for (int inode = 0; inode < numEltNodes_; ++inode)
{
double shp = 0.125;
for (int i = 0; i < nSD_; ++i) shp *= (1 + xi(i)*localCoords_(i, inode));
N(inode) = shp;
}
}
//-----------------------------------------------------------------
void FE_ElementHex::shape_function(const int eltID,
const VECTOR &xi,
DENS_VEC &N,
DENS_MAT &dNdx)
{
N.resize(numEltNodes_);
// Get element node coordinates from mesh
DENS_MAT xCoords;
feMesh_->element_coordinates(eltID, xCoords);
DENS_MAT xCoordsT = transpose(xCoords);
DENS_MAT dNdr(3,8,false), dxdr(3,3,false), drdx;
double r = xi(0);
double s = xi(1);
double t = xi(2);
for (int inode = 0; inode < numEltNodes_; ++inode)
{
double rI = localCoords_(0,inode);
double sI = localCoords_(1,inode);
double tI = localCoords_(2,inode);
// Shape function
N(inode) = 0.125 * (1.0 + r*rI) * (1.0 + s*sI) * (1.0 + t*tI);
// Shape function derivative wrt (r,s,t)
dNdr(0,inode) = 0.125 * rI * (1.0 + s*sI) * (1.0 + t*tI);
dNdr(1,inode) = 0.125 * sI * (1.0 + r*rI) * (1.0 + t*tI);
dNdr(2,inode) = 0.125 * tI * (1.0 + r*rI) * (1.0 + s*sI);
}
// Derivatives wrt (x,y,z)
dxdr = dNdr * xCoordsT;
drdx = inv(dxdr);
dNdx = drdx*dNdr;
}
//-----------------------------------------------------------------
void FE_ElementHex::face_shape_function(const PAIR & face,
DENS_MAT &N,
vector<DENS_MAT> &dN,
vector<DENS_MAT> &Nn,
DIAG_MAT &weights)
{
int eltID = face.first;
int local_faceID = face.second;
// const double * face_normal = face.normal();
// double * normal = face_normal;
DENS_VEC normal(nSD_);
// Get element node coordinates from mesh
DENS_MAT xCoords;
feMesh_->element_coordinates(eltID, xCoords);
// Transpose xCoords
DENS_MAT xCoordsT = transpose(xCoords);
// Shape functions are simply the canonical element values
N.reset(numFaceIPs_, numEltNodes_);
N = NFace_[local_faceID];
// Set sizes of matrices and vectors
if ((int)dN.size() != nSD_) dN.resize(nSD_);
for (int isd = 0; isd < nSD_; isd++) dN[isd].reset(numFaceIPs_, numEltNodes_);
weights.reset(numFaceIPs_,numFaceIPs_);
// Create some temporary matrices:
// Shape function deriv.'s w.r.t. element coords
DENS_MAT dNdr(nSD_, numEltNodes_);
// Jacobian matrix: [dx/dr dy/ds dz/dt | dx/ds ... ]
DENS_MAT dxdr, drdx, dNdx;
// Loop over integration points
for (int ip = 0; ip < numFaceIPs_; ip++) {
double r = ipFaceCoords_[local_faceID](0,ip);
double s = ipFaceCoords_[local_faceID](1,ip);
double t = ipFaceCoords_[local_faceID](2,ip);
// Fill dNdr
for (int inode = 0; inode < numEltNodes_; inode++) {
double rI = localCoords_(0,inode);
double sI = localCoords_(1,inode);
double tI = localCoords_(2,inode);
dNdr(0,inode) = 0.125 * rI * (1 + s*sI) * (1 + t*tI);
dNdr(1,inode) = 0.125 * sI * (1 + r*rI) * (1 + t*tI);
dNdr(2,inode) = 0.125 * tI * (1 + r*rI) * (1 + s*sI);
}
// Compute dx/dxi matrix
dxdr = dNdr * xCoordsT;
drdx = inv(dxdr);
// Compute 2d jacobian determinant of dxdr at this ip
double J = face_normal(face, ip, normal);
// Compute dNdx and fill dN matrix
dNdx = drdx*dNdr;
for (int isd = 0; isd < nSD_; isd++) {
for (int inode = 0; inode < numEltNodes_; inode++) {
dN[isd](ip,inode) = dNdx(isd,inode);
Nn[isd](ip,inode) = N(ip,inode)*normal(isd);
}
}
// Compute ip weight
weights(ip,ip) = ipFaceWeights_(ip)*J;
}
}
//-----------------------------------------------------------------
void FE_ElementHex::face_shape_function(const PAIR & face,
DENS_MAT &N,
DENS_MAT &n,
DIAG_MAT &weights)
{
int eltID = face.first;
int local_faceID = face.second;
// const double * face_normal = face.normal();
// double * normal = face_normal;
DENS_VEC normal(nSD_);
// Get element node coordinates from mesh
DENS_MAT xCoords;
feMesh_->element_coordinates(eltID, xCoords);
// Transpose xCoords
DENS_MAT xCoordsT = transpose(xCoords);
// Shape functions are simply the canonical element values
N.reset(numFaceIPs_, numEltNodes_);
N = NFace_[local_faceID];
weights.reset(numFaceIPs_,numFaceIPs_);
// Create some temporary matrices:
// Shape function deriv.'s w.r.t. element coords
DENS_MAT dNdr(nSD_, numEltNodes_);
// Jacobian matrix: [dx/dr dy/ds dz/dt | dx/ds ... ]
DENS_MAT dxdr, drdx, dNdx;
// Loop over integration points
for (int ip = 0; ip < numFaceIPs_; ip++) {
double r = ipFaceCoords_[local_faceID](0,ip);
double s = ipFaceCoords_[local_faceID](1,ip);
double t = ipFaceCoords_[local_faceID](2,ip);
// Compute 2d jacobian determinant of dxdr at this ip
double J = face_normal(face, ip, normal);
// Copy normal at integration point
for (int isd = 0; isd < nSD_; isd++) {
n(isd,ip) = normal(isd);
}
// Compute ip weight
weights(ip,ip) = ipFaceWeights_(ip)*J;
}
}
// -------------------------------------------------------------
// face_normal
// -------------------------------------------------------------
double FE_ElementHex::face_normal(const PAIR & face,
int ip,
DENS_VEC &normal)
{
// Get element node coordinates from mesh
DENS_MAT xCoords;
feMesh_->face_coordinates(face, xCoords);
// Transpose xCoords
DENS_MAT xCoordsT = transpose(xCoords);
double r = ipFace2DCoords_(0,ip);
double s = ipFace2DCoords_(1,ip);
DENS_MAT dNdr(nSD_-1, numFaceNodes_);
for (int inode = 0; inode < numFaceNodes_; inode++) {
double rI = localCoords_(0,inode); // NOTE a little dangerous
double sI = localCoords_(1,inode);
dNdr(0,inode) = 0.25 * rI * (1 + s*sI);
dNdr(1,inode) = 0.25 * sI * (1 + r*rI);
}
DENS_MAT dxdr(2,3);
// Compute dx/dxi matrix
dxdr = dNdr * xCoordsT;
normal(0) = dxdr(0,1)*dxdr(1,2) - dxdr(0,2)*dxdr(1,1) ;
normal(1) = dxdr(0,2)*dxdr(1,0) - dxdr(0,0)*dxdr(1,2) ;
normal(2) = dxdr(0,0)*dxdr(1,1) - dxdr(0,1)*dxdr(1,0) ;
double J = sqrt(normal(0)*normal(0)+normal(1)*normal(1)+normal(2)*normal(2));
// double inv_J = normal_sense(face)/J;
double inv_J = 1.0/J;
normal(0) *= inv_J;
normal(1) *= inv_J;
normal(2) *= inv_J;
return J;
}
}; // namespace ATC_Transfer

View File

@ -1,204 +0,0 @@
#ifndef FE_ELEMENT_H
#define FE_ELEMENT_H
// ATC_Transfer headers
#include "MatrixLibrary.h"
#include "Array2D.h"
#include "ATC_TypeDefs.h"
using namespace std;
namespace ATC {
// Forward declarations
class FE_Mesh;
/**
* @class FE_Element
* @brief Base class for a finite element holding info for canonical element
*/
class FE_Element {
public:
FE_Element(FE_Mesh *feMesh,
int nSD,
int numEltNodes,
int numIPs,
int numFaces,
int numFaceNodes,
int numFaceIPs);
virtual ~FE_Element();
/** get number of element nodes */
int num_elt_nodes() { return numEltNodes_; }
/** get number of integration points */
int num_ips() { return numIPs_; }
/** get number of faces */
int num_faces() { return numFaces_; }
/** get number of face nodes */
int num_face_nodes() { return numFaceNodes_; }
/** get number of integration points */
int num_face_ips() { return numFaceIPs_; }
/** cannonical face numbering */
const Array2D<int> & local_face_conn(void) const {return localFaceConn_ ;}
/**
* compute shape functions at all ip's:
* indexed: N(ip,node)
* dN[nsd](ip,node)
* weights(ip)
*/
virtual void shape_function(const int eltID,
DENS_MAT &N,
vector<DENS_MAT> &dN,
DIAG_MAT &weights)=0;
/**
* compute shape functions at a single point, given the local coordinates
* indexed: N(node)
* dN[nsd](node)
*/
virtual void shape_function(const int eltID,
const VECTOR &xi,
DENS_VEC &N) = 0;
virtual void shape_function(const int eltID,
const VECTOR &xi,
DENS_VEC &N,
DENS_MAT &dN) = 0;
/**
* compute shape functions at all face ip's:
* indexed: N(ip,node)
* dN[nsd](ip,node)
* Nn[nsd](ip,node)
* weights(ip)
*/
virtual void face_shape_function(const PAIR &face,
DENS_MAT &N,
vector<DENS_MAT> &dN,
vector<DENS_MAT> &Nn,
DIAG_MAT &weights) = 0;
virtual void face_shape_function(const PAIR & face,
DENS_MAT &N,
DENS_MAT &n,
DIAG_MAT &weights) = 0;
virtual double face_normal(const PAIR & face,
const int ip,
DENS_VEC &normal) = 0;
enum FE_ElementQuadrature { GAUSSIAN_QUADRATURE, NODAL_QUADRATURE};
virtual void set_quadrature(int quadrature_type) = 0;
protected:
// Mesh
FE_Mesh * feMesh_;
// Number of spatial dimensions
int nSD_;
// Number of element nodes
int numEltNodes_;
// Number of integration points
int numIPs_;
// Number of faces
int numFaces_;
// Number of face nodes
int numFaceNodes_;
// Number of face integration points
int numFaceIPs_;
// local coords of nodes: localCoords_(isd, ip)
DENS_MAT localCoords_;
// quadrature scheme: localCoords_(isd, ip)
DENS_MAT ipCoords_; // local coordinates
// matrix of shape functions at ip's: N_(ip, node)
DENS_MAT N_;
// integration point weights: ipWeights_(ip)
DENS_VEC ipWeights_; // local coordinates
// local face numbering
Array2D<int> localFaceConn_;
// quadrature scheme: localCoords_(isd, ip)
vector<DENS_MAT> ipFaceCoords_;
DENS_MAT ipFace2DCoords_;
// matrix of shape functions at ip's: N_(ip, node)
vector<DENS_MAT> NFace_;
// integration point weights: ipWeights_(ip)
DENS_VEC ipFaceWeights_;
};
/**
* @class FE_ElementHex
* @author Greg Wagner
* @brief 3D, linear 8-node hex element with 2x2x2 quadrature
*/
class FE_ElementHex : public FE_Element {
public:
FE_ElementHex(FE_Mesh * feMesh);
// Dump state info to disk for later restart
void write_restart(FILE *);
~FE_ElementHex();
protected:
virtual void shape_function(const int eltID,
DENS_MAT &N,
vector<DENS_MAT> &dN,
DiagonalMatrix<double> &weights);
/**
* compute shape functions at a single point, given the local coordinates
* indexed: N(node)
* dN[nsd](node)
*/
virtual void shape_function(const int eltID,
const VECTOR &xi,
DENS_VEC &N);
virtual void shape_function(const int eltID,
const VECTOR &xi,
DENS_VEC &N,
DENS_MAT &dN);
virtual void face_shape_function(const PAIR &face,
DENS_MAT &N,
vector<DENS_MAT> &dN,
vector<DENS_MAT> &Nn,
DiagonalMatrix<double> &weights);
virtual void face_shape_function(const PAIR & face,
DENS_MAT &N,
DENS_MAT &n,
DIAG_MAT &weights);
virtual double face_normal(const PAIR &face, const int ip, DENS_VEC &normal);
virtual void set_quadrature(int quadrature_type);
};
}; // namespace ATC_Transfer
#endif // FE_ELEMENT_H

File diff suppressed because it is too large Load Diff

View File

@ -1,348 +0,0 @@
/** fe_engine :
* computes and assembles mass matrix, rhs vectors
* initial conditions handled in atc_transfer
*/
/** field structure:
a field is a dense matrix of numPoints X number of DOF in the field
a gradient is a std::vector of fields of length numSpatialDimensions
a set of fields is a map of fieldName->field of length numFields
a set of gradients is a map of fieldName->gradient of length numFields
Note: shape functions follow similar conventions with a shape function being
a field of numPoints X numNodes
and a shape function gradient being a std::vector of shape functions
of length numSpatialDimensions, although this is modified in calls when
numPoints = 1
Note: the convention between shape function format and field format allows
for shape functions to matmat nodal fields, creating matrices of
numPoints X numElementsInField for evaluating data at atomic/quadarture points
*/
/** current internal limitations:
* 3 spatial dimensions
* 8 node bricks
* structured mesh
* no stiffness matrix
(i.e. no implicit integration or special treatment of linear problems)
* lumped mass
*/
/** terminology:
density rate = flux
= Grad.FLUX(f,D_x f)
+ SOURCE(f,D_x f) + PRESCRIBED_SOURCE(x,t)
+ EXTRINSIC_SOURCE(f,D_x f,f_e,D_x f_e)
*/
#ifndef FE_ENGINE_H
#define FE_ENGINE_H
// Other headers
#include <vector>
#include <map>
// ATC_Transfer headers
#include "Array.h"
#include "Array2D.h"
#include "FE_Mesh.h"
#include "PhysicsModel.h"
#include "OutputManager.h"
using namespace std;
namespace ATC {
// Forward declarations
class ATC_Transfer;
class FE_Element;
class XT_Function;
class FE_Engine{
public:
/** constructor/s */
FE_Engine(ATC_Transfer * atcTransfer);
/** destructor */
~FE_Engine();
/** initialize */
void initialize();
/** parser/modifier */
bool modify(int narg, char **arg);
/** finish up */
void finish();
//----------------------------------------------------------------
/** \name output */
//----------------------------------------------------------------
/*@{*/
/** these assume the caller is handling the parallel collection */
void initialize_output(int rank,
string outputPrefix, OutputType otype = ENSIGHT);
/** write geometry */
void write_geometry(void);
/** write data: data is arrayed over _unique_ nodes
& then mapped by the engine */
void write_data(double time, FIELDS &soln, OUTPUT_LIST *data=NULL);
void write_data(double time, OUTPUT_LIST *data);
void write_restart_file(string fileName, OUTPUT_LIST *data)
{outputManager_.write_restart_file(fileName,data);};
void read_restart_file(string fileName, OUTPUT_LIST *data)
{outputManager_.read_restart_file(fileName,data);};
void delete_elements(const set<int> & elementList);
void add_global(string name, double value)
{outputManager_.add_global(name,value);}
void reset_globals() {outputManager_.reset_globals();}
/** pass through to access output manager */
OutputManager* output_manager() {return &outputManager_;}
/*@}*/
//----------------------------------------------------------------
/** \name assembled matrices and vectors */
//----------------------------------------------------------------
/*@{*/
/** compute a dimensionless stiffness matrix */
void compute_stiffness_matrix(SPAR_MAT &matrix) const;
/** compute a dimensionless mass matrix */
void compute_mass_matrix(SPAR_MAT &mass_matrix) const;
/** computes a dimensionless mass matrix for the given-quadrature */
void compute_mass_matrix(const DIAG_MAT &weights,
const SPAR_MAT &N,
SPAR_MAT &mass_matrix) const;
/** compute a single dimensionless mass matrix */
void compute_lumped_mass_matrix(DIAG_MAT &lumped_mass_matrix) const;
/** compute lumped mass matrix = diag (\int \rho N_I dV) */
void compute_lumped_mass_matrix(const Array<FieldName> &mask,
const FIELDS &fields,
const PhysicsModel * physicsModel,
const Array<int> & elementMaterials,
map<FieldName, DIAG_MAT> &mass_matrix,
const Array<bool> *element_mask=NULL) const;
/** compute dimensional lumped mass matrix using given quadrature */
void compute_lumped_mass_matrix(const Array<FieldName> &mask,
const FIELDS &fields,
const PhysicsModel * physicsModel,
const Array<set<int> > & pointMaterialGroups,
const DIAG_MAT &weights,
const SPAR_MAT &N,
map<FieldName, DIAG_MAT> &mass_matrix) const;
/** compute an approximation to a finite difference gradient from mesh */
void compute_gradient_matrix(GRAD_SHPFCN &grad_matrix) const;
/** compute energy */
void compute_energy(const Array<FieldName> &mask,
const FIELDS &fields,
const PhysicsModel * physicsModel,
const Array<int> & elementMaterials,
FIELDS &energy,
const Array<bool> *element_mask=NULL) const;
/** compute residual or RHS of the dynamic weak eqn */
void compute_rhs_vector(const Array2D<bool> &rhs_mask,
const FIELDS &fields,
const PhysicsModel * physicsModel,
const Array<int> & elementMaterials,
FIELDS &rhs,
const Array<bool> *element_mask=NULL) const;
/** compute RHS for given quadrature */
void compute_rhs_vector(const Array2D<bool> &rhs_mask,
const FIELDS &fields,
const PhysicsModel * physicsModel,
const Array<set<int> > & pointMaterialGroups,
const DIAG_MAT &weights,
const SPAR_MAT &N,
const GRAD_SHPFCN &dN,
FIELDS &rhs) const;
/** compute flux in domain i.e. N^T B_integrand */
void compute_flux(const Array2D<bool> & rhs_mask,
const FIELDS &fields,
const PhysicsModel * physicsModel,
const Array<int> & elementMaterials,
GRAD_FIELDS &flux,
const Array<bool> *element_mask=NULL) const;
/** compute the flux on the MD/FE boundary */
void compute_boundary_flux(
const Array2D<bool> & rhs_mask,
const FIELDS & fields,
const PhysicsModel * physicsModel,
const Array<int> & elementMaterials,
const set<PAIR> & faceSet,
FIELDS & rhs) const;
/** compute the flux on using an L2 interpolation of the flux */
void compute_boundary_flux(
const Array2D<bool> & rhs_mask,
const FIELDS & fields,
const PhysicsModel * physicsModel,
const Array<int> & elementMaterials,
const Array<set<int> > & pointMaterialGroups,
const DIAG_MAT & weights,
const SPAR_MAT & N,
const GRAD_SHPFCN & dN,
const DIAG_MAT & flux_mask,
FIELDS & rhs ) const;
/** compute prescribed flux given an array of functions of x & t */
void add_fluxes(const Array<bool> &fieldMask,
const double time,
const SURFACE_SOURCE & sourceFunctions,
FIELDS &nodalSources) const;
/** compute nodal vector of volume based sources */
void add_sources(const Array<bool> &fieldMask,
const double time,
const VOLUME_SOURCE &sourceFunctions,
FIELDS &nodalSources) const;
/** compute surface flux of a nodal field */
void field_surface_flux(const DENS_MAT & field,
const set<PAIR> &faceSet,
DENS_MAT & values,
const bool contour = false,
const int axis = 2) const;
/*@}*/
//----------------------------------------------------------------
/** \name shape functions */
//----------------------------------------------------------------
/*@{*/
/** evaluate shape function at a list of points in R^3 */
void evaluate_shape_functions(const MATRIX &coords,
SPAR_MAT &N,
Array<int> & pointToEltMap) const;
/** evaluate shape function & derivatives at a list of points in R^3 */
void evaluate_shape_functions( const MATRIX &coords,
SPAR_MAT &N,
GRAD_SHPFCN &dN,
Array<int> & pointToEltMap) const;
/** evaluate all shape function & derivatives at a specific R^3 location */
void evaluate_shape_functions(const VECTOR & x,
Array<int>& node_index,
DENS_VEC& shp,
DENS_MAT& dshp,
int & eltID) const;
/** pass through */
void shape_functions(const VECTOR &x,
DENS_VEC& shp,
int & eltID,
Array<int>& node_list) const
{ feMesh_->shape_functions(x,shp,eltID,node_list); }
void shape_functions(const VECTOR &x,
DENS_VEC& shp,
int & eltID,
Array<int>& node_list,
const Array<bool>& periodicity) const
{ feMesh_->shape_functions(x,shp,eltID,node_list, periodicity); }
/*@}*/
//----------------------------------------------------------------
/** \name accessors */
//----------------------------------------------------------------
/*@{*/
/** even though these are pass-throughs there is a necessary translation */
/** return number of unique nodes */
int get_nNodes() const { return feMesh_->get_nNodesUnique(); };
/** return number of total nodes */
int get_nNodesTotal() const { return feMesh_->get_nNodes(); };
/** return number of elements */
int get_nElements() const { return feMesh_->get_nElements(); };
/** return element connectivity */
void element_connectivity(const int eltID, Array<int> & nodes) const
{ feMesh_->element_connectivity_unique(eltID, nodes); }
/** return face connectivity */
void face_connectivity(const PAIR &faceID, Array<int> &nodes) const
{ feMesh_->face_connectivity_unique(faceID, nodes); }
/** in lieu of pass-throughs const accessors ... */
// return const ptr to mesh
const FE_Mesh* get_feMesh() const { return feMesh_;}
// return number of spatial dimensions
int get_nsd() const { return feMesh_->get_nSpatialDimensions(); }
// return if the FE mesh has been created
int fe_mesh_exist() const { return feMesh_!=NULL; }
// get nodal coordinates for a given element
void element_coordinates(const int eltIdx, DENS_MAT &coords)
{ feMesh_->element_coordinates(eltIdx,coords); }
// access list of elements to be deleted
set<int> & null_elements(void) { return nullElements_; }
/*@}*/
private:
//----------------------------------------------------------------
/** mesh setup commands (called from modify) */
//----------------------------------------------------------------
/*@{*/
/** initialized flag */
bool initialized_;
/** create a uniform, structured mesh */
void create_mesh(int nx, int ny, int nz, char * regionName,
int xperiodic, int yperiodic, int zperiodic);
/*@}*/
/** ATC transfer object */
ATC_Transfer * atcTransfer_;
/** finite element mesh */
FE_Mesh * feMesh_;
/** data that can be used for a subset of original mesh */
set<int> nullElements_;
bool amendedMeshData_;
const Array2D<int> * connectivity_;
const Array<int> * nodeMap_;
const DENS_MAT * coordinates_;
/** workspace */
int nNodesPerElement_;
int nIPsPerElement_;
int nIPsPerFace_;
int nSD_;
int nElems_;
/** output object */
OutputManager outputManager_;
/** base name for output files */
string outputPrefix_;
/** output frequency (NOTE will move to "Transfer") */
int outputFrequency_;
/** list of output timesteps */
vector<double> outputTimes_;
};
}; // end namespace ATC
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,387 +0,0 @@
#ifndef FE_MESH_H
#define FE_MESH_H
// ATC_Transfer headers
#include "Array.h"
#include "Array2D.h"
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
// Other headers
#include <vector>
#include <map>
#include <set>
#include <utility>
using namespace std;
namespace ATC {
// Forward declarations
class FE_Element;
/**
* @class FE_Mesh
* @brief Base class for a finite element mesh
*/
class FE_Mesh {
public:
/** constructor */
FE_Mesh();
/** destructor */
virtual ~FE_Mesh();
/** parser/modifier */
bool modify(int narg, char **arg);
/** evaluate shape function at real coordinates */
void shape_functions(const VECTOR &x,
DENS_VEC& shp,
int & eltID,
Array<int>& node_list) const;
/** evaluate shape function at real coordinates */
void shape_functions(const VECTOR &x,
DENS_VEC& shp,
int & eltID,
Array<int>& node_list,
const Array<bool>& periodicity) const;
/** evaluate shape function at real coordinates */
void shape_functions(const VECTOR &x,
DENS_VEC & shp,
DENS_MAT & dshp,
int & eltID,
Array<int>& node_list) const;
/** evaluate shape functions for all ip's on an element */
// N is numIPsInElement X numNodesInElement
void shape_function(const int eltID,
DENS_MAT &N,
DIAG_MAT &weights) const;
/** evaluate shape functions for all ip's on an element */
// N is numIPsInElement X numNodesInElement
void shape_function(const int eltID,
DENS_MAT &N,
vector<DENS_MAT> &dN,
DIAG_MAT &weights) const;
/** evaluate shape functions for all ip's on an face*/
// N is numIPsInFace X numNodesInElement
void face_shape_function(const PAIR & face,
DENS_MAT &N,
vector<DENS_MAT> &dN,
vector<DENS_MAT> &Nn,
DIAG_MAT &weights) const;
void face_shape_function(const PAIR & face,
DENS_MAT &N,
DENS_MAT &n,
DIAG_MAT &weights) const;
/** return connectivity (global ID numbers) for element eltID */
void element_connectivity_global(const int eltID,
Array<int> & nodes) const;
void element_connectivity_unique(const int eltID,
Array<int> & nodes) const;
void face_connectivity(const pair<int,int> & faceID,
Array<int> & nodes) const
{ int nNodesPerFace = get_nNodesPerFace();
nodes.reset(nNodesPerFace);
int eltID = faceID.first;
int localFace = faceID.second;
const Array2D<int> & localFaceConn = local_face_connectivity();
for(int i = 0; i < nNodesPerFace; ++i) {
nodes(i) = connectivity_(localFaceConn(localFace,i),eltID);
}
}
void face_connectivity_unique(const pair<int,int> & faceID,
Array<int> & nodes) const
{ int nNodesPerFace = get_nNodesPerFace();
nodes.reset(nNodesPerFace);
int eltID = faceID.first;
int localFace = faceID.second;
const Array2D<int> & localFaceConn = local_face_connectivity();
for(int i = 0; i < nNodesPerFace; ++i) {
nodes(i) = connectivityUnique_(localFaceConn(localFace,i),eltID);
}
}
/**
* return spatial coordinates for element nodes on eltID,
* indexed xCoords(isd,inode)
*/
void element_coordinates(const int eltID,
DENS_MAT & xCoords) const;
void face_coordinates(const pair <int,int> face,
DENS_MAT & xCoords) const;
/** access to the nodal coordinate values */
const DENS_MAT & nodal_coordinates(void) {return nodalCoords_ ;}
/** access to nodal coordinates of a unique node */
DENS_VEC nodal_coordinates(const int nodeID) const;
/** access to nodal coordinates of a node */
DENS_VEC global_coordinates(const int nodeID) const;
/** access to the element connectivity values */
const Array2D<int> & connectivity(void) {return connectivity_ ;}
/** map spatial location to element */
virtual int map_to_element(const DENS_VEC & x) const = 0;
/** map spatial location to element and local coordinates */
virtual int map_to_element(const DENS_VEC & x,
DENS_VEC & xi) const = 0;
/** map spatial location to element and local coordinates */
virtual int map_to_element(const DENS_VEC & x,
DENS_VEC & xi,
const Array<bool>& periodicity) const = 0;
/** map global node numbering to unique node numbering */
int map_global_to_unique(const int global_id) const {return globalToUniqueMap_(global_id);}
inline const int* global_to_unique_map_pointer(void) {return globalToUniqueMap_.get_data();}
inline const Array<int>& global_to_unique_map(void) {return globalToUniqueMap_;}
/** map unique node numbering a global node numbering */
int map_unique_to_global(const int unique_id)
{return uniqueToGlobalMap_(unique_id);}
inline const int* unique_to_global_map(void) {return uniqueToGlobalMap_.get_data();}
/** query whether a nodeset with the given name exists */
bool query_nodeset(const string & name) const;
/** get node set (unique ID's) from the string name assigned to the set */
const set<int> & get_nodeset(const string & name) const;
/** create node set with tag "name" from nodes in given spatial range */
void create_nodeset(const string & name,
double xmin, double xmax,
double ymin, double ymax,
double zmin, double zmax);
/** get element set from the string name assigned to the set */
const set<int> & get_elementset(const string & name) const;
/** create element set with tag "name" from nodes in given spatial range */
void create_elementset(const string & name,
double xmin, double xmax,
double ymin, double ymax,
double zmin, double zmax);
/** get the minimal element set from a nodeset by name */
void nodeset_to_minimal_elementset
(const string & name, set<int> & elemSet) const;
/** get the maximal element set from a nodeset by name */
void nodeset_to_maximal_elementset
(const string & name, set<int> & elemSet) const;
/** get complement of element set by name */
void elementset_complement(const string & name, set<int> & elemSet) const;
void elementset_complement(const set<int> & elemSet, set<int> & elemSetComplement) const;
/** get the node set from an element set by name */
void elementset_to_minimal_nodeset
(const string & name, set<int> & nodeSet) const;
void elementset_to_nodeset(const string & name, set<int> & nodeSet) const;
void elementset_to_nodeset(const set<int> & elemSet, set<int> & nodeSet) const;
/** convert faceset to nodeset in _unique_node numbering */
void faceset_to_nodeset(const string &name, set<int> &nodeSet) const;
void faceset_to_nodeset_global(const string &name, set<int> &nodeSet) const;
/** get face set from the string name assigned to the set */
const set< pair <int,int> > & get_faceset(const string & name) const;
/** create face set with tag "name" from faces aligned with box */
void create_faceset(const string & name,
double xmin, double xmax,
double ymin, double ymax,
double zmin, double zmax,
bool outward);
void create_faceset(const string & name, double x, int idir, int isgn);
/** return number of spatial dimensions */
int get_nSpatialDimensions() const { return nSD_; };
/** return total number of nodes */
int get_nNodes() const { return nNodes_; };
/** return number of unique nodes */
int get_nNodesUnique() const { return nNodesUnique_; };
/** return number of elements */
int get_nElements() const { return nElts_; };
/** return number of integration points per element */
int get_nIPsPerElement() const;
/** return number of nodes per element */
int get_nNodesPerElement() const;
/** return number of faces per element */
int get_nFacesPerElement() const;
/** return number of nodes per face */
int get_nNodesPerFace() const;
/** return number of integration points per face */
int get_nIPsPerFace() const;
/** return scale in x */
double get_xscale() const {return xscale_;}
/** return scale in y */
double get_yscale() const {return yscale_;}
/** return scale in z */
double get_zscale() const {return zscale_;}
/** local face connectivity */
const Array2D<int> & local_face_connectivity() const;
/** element size in each direction */
virtual void element_size(const int ielem,
double hx, double hy, double hz) = 0;
/** element size in each direction */
virtual double min_element_size(void) const = 0;
/** set quadrature on element : a pass-through */
void set_quadrature(int type);
/** output mesh subsets */
void output(string prefix) const;
protected:
/** number of spatial dimensions */
int nSD_;
/** number of elements */
int nElts_;
/** number of nodes */
int nNodes_;
int nNodesUnique_;
/** periodicity flags */
int periodicFlag_[3];
/** element type for this mesh */
FE_Element *feElement_;
/** Nodal coordinates: nodalCoords_(nsd, numnode) */
DENS_MAT nodalCoords_;
/** Element connectivity: connectivity_(neltnode, nelt) */
Array2D<int> connectivity_;
Array2D<int> connectivityUnique_;
/** map of global to unique node ID's */
Array<int> globalToUniqueMap_;
/** map of unique to global node ID's */
Array<int> uniqueToGlobalMap_;
/** map of string names to node sets */
NODE_SET_MAP nodeSetMap_;
/** maximal nodeset */
set<int> nodeSetAll_;
/** map of string names to node sets */
FACE_SET_MAP faceSetMap_;
/** map of string names to element sets */
ELEMENT_SET_MAP elementSetMap_;
/** maximal elementset */
set<int> elementSetAll_;
/** length scaling used by lammps */
double xscale_, yscale_, zscale_;
/** scratch memory for setting face connectivities */
Array<int> connScratch_;
};
/**
* @class FE_Uniform3DMesh
* @brief Derived class for a uniform mesh, a structured mesh with
* fixed element sizes in x, y, and z directions
*/
class FE_Uniform3DMesh : public FE_Mesh {
public:
/** constructor */
FE_Uniform3DMesh(const int nx,
const int ny,
const int nz,
double xmin, double xmax,
double ymin, double ymax,
double zmin, double zmax,
double xscale,
double yscale,
double zscale,
int xperiodic,
int yperiodic,
int zperiodic);
/** destructor */
~FE_Uniform3DMesh();
virtual void element_size(const int ielem,
double hx, double hy, double hz)
{ hx = Lx_[0]/nx_[0]; hy = Lx_[1]/nx_[1]; hz = Lx_[2]/nx_[2]; }
virtual double min_element_size(void) const
{return min(Lx_[0]/nx_[0], min(Lx_[1]/nx_[1], Lx_[2]/nx_[2])); }
/** map spatial location to element */
virtual int map_to_element(const DENS_VEC & x) const;
/** map spatial location to element and local coordinates */
virtual int map_to_element(const DENS_VEC & x,
DENS_VEC & xi) const;
/** map spatial location to element and local coordinates */
virtual int map_to_element(const DENS_VEC & x,
DENS_VEC & xi,
const Array<bool> & periodicity) const;
protected:
// Number of elements in each spatial direction
int nx_[3];
// Bounds of region on which mesh is defined
double borders_[2][3];
// Region size in each direction
double Lx_[3];
// Element size in each direction
double dx_[3];
/** create global-to-unique node mapping */
void setup_periodicity();
};
}; // namespace ATC_Transfer
#endif // FE_MESH_H

View File

@ -1,101 +0,0 @@
// Header file for this class
#include "FieldEulerIntegrator.h"
// Other ATC includes
#include "ATC_Transfer.h"
#include "FE_Engine.h"
#include "PhysicsModel.h"
#include "GMRES.h"
#include "ImplicitSolveOperator.h"
namespace ATC {
// ====================================================================
// FieldEulerIntegrator
// ====================================================================
FieldEulerIntegrator::FieldEulerIntegrator(
const FieldName fieldName,
const PhysicsModel * physicsModel,
/*const*/ FE_Engine * feEngine,
/*const*/ ATC_Transfer * atcTransfer,
const Array2D< bool > & rhsMask // copy
)
: atc_(atcTransfer),
feEngine_(feEngine),
physicsModel_(physicsModel),
fieldName_(fieldName),
rhsMask_(rhsMask)
{
nNodes_ = feEngine->get_nNodes();
}
// ====================================================================
// FieldImplicitIntegrator
// ====================================================================
FieldExplicitEulerIntegrator::FieldExplicitEulerIntegrator(
const FieldName fieldName,
const PhysicsModel * physicsModel,
/*const*/ FE_Engine * feEngine,
/*const*/ ATC_Transfer * atcTransfer,
const Array2D< bool > & rhsMask // copy
) : FieldEulerIntegrator(fieldName,physicsModel,feEngine,atcTransfer,rhsMask)
{
}
// --------------------------------------------------------------------
// update
// --------------------------------------------------------------------
void FieldExplicitEulerIntegrator::update(const double dt, double time,
FIELDS & fields, FIELDS & rhs)
{ // NOTE time is not used
atc_->compute_rhs_vector(rhsMask_, fields, rhs,
atc_->FULL_DOMAIN, physicsModel_);
atc_->apply_inverse_mass_matrix(rhs[fieldName_],fieldName_);
fields[fieldName_] += dt*rhs[fieldName_];
}
// ====================================================================
// FieldImplicitEulerIntegrator
// ====================================================================
FieldImplicitEulerIntegrator::FieldImplicitEulerIntegrator(
const FieldName fieldName,
const PhysicsModel * physicsModel,
/*const*/ FE_Engine * feEngine,
/*const*/ ATC_Transfer * atcTransfer,
const Array2D< bool > & rhsMask, // copy
const double alpha
) : FieldEulerIntegrator(fieldName,physicsModel,feEngine,atcTransfer,rhsMask),
alpha_(alpha),
dT_(1.0e-6),
maxRestarts_(50),
maxIterations_(200),
tol_(1.0e-8)
{
}
// --------------------------------------------------------------------
// update
// --------------------------------------------------------------------
void FieldImplicitEulerIntegrator::update(const double dt, double time,
FIELDS & fields, FIELDS & rhs)
{ // solver handles bcs
FieldImplicitSolveOperator solver(atc_, feEngine_, // NOTE make persistent
fields, fieldName_, rhsMask_, physicsModel_,
time, dt, alpha_);
DiagonalMatrix<double> preconditioner = solver.get_preconditioner(fields);
DENS_VEC myRhs = solver.get_rhs();
DENS_VEC dT(nNodes_); dT = dT_;
DENS_MAT H(maxRestarts_+1, maxRestarts_);
double tol = tol_; // tol returns the residual
int iterations = maxIterations_; // iterations returns number of iterations
int restarts = maxRestarts_;
int convergence = GMRES(solver,
dT, myRhs, preconditioner, H, restarts, iterations, tol);
if (convergence != 0) {
throw ATC_Error(0,field_to_string(fieldName_) + " evolution did not converge");
}
fields[fieldName_] += dT;
rhs[fieldName_] = myRhs;
}
} // namespace ATC

View File

@ -1,138 +0,0 @@
#ifndef FIELD_EULER_INTEGRATOR_H
#define FIELD_EULER_INTEGRATOR_H
// ATC includes
#include "Array2D.h"
#include "MatrixLibrary.h"
#include "PhysicsModel.h"
#include "TimeIntegrator.h"
#include "ImplicitSolveOperator.h"
// other includes
#include <vector>
#include <map>
namespace ATC {
// Forward class declarations
class ATC_Transfer;
class FE_Engine;
/**
* @class FieldEulerIntegrator
* @brief method for integrating fast fields
*/
//class FieldEulerIntegrator : public TimeIntegrator { // NOTE need to construct
class FieldEulerIntegrator {
public:
/** Constructor */
FieldEulerIntegrator(
const FieldName fieldName,
const PhysicsModel * physicsModel,
/*const*/ FE_Engine * feEngine,
/*const*/ ATC_Transfer * atcTransfer,
const Array2D< bool > & rhsMask // copy
);
/** Destructor */
virtual ~FieldEulerIntegrator() {};
/** update */
virtual void update(const double dt, const double time,
FIELDS & fields, FIELDS & rhs) = 0;
protected:
/** Pointer to ATC_Tranfer */
ATC_Transfer * atc_;
/** Pointer to FE_Engine */
/*const*/ FE_Engine * feEngine_;
/** Pointer to PhysicsModel */
const PhysicsModel * physicsModel_;
/** field name */
FieldName fieldName_;
/** rhs mask */
Array2D <bool> rhsMask_;
/** number of nodes */
int nNodes_;
};
/**
* @class FieldExplicitEulerIntegrator
* @brief explicit Euler method for integrating fast electron fields
*/
class FieldExplicitEulerIntegrator : public FieldEulerIntegrator {
public:
/** Constructor */
FieldExplicitEulerIntegrator(
const FieldName fieldName,
const PhysicsModel * physicsModel,
/*const*/ FE_Engine * feEngine,
/*const*/ ATC_Transfer * atcTransfer,
const Array2D< bool > & rhsMask // copy
);
/** Destructor */
virtual ~FieldExplicitEulerIntegrator() {};
/** update */
void update(const double dt, const double time,
FIELDS & fields, FIELDS & rhs);
};
/**
* @class FieldImplicitEulerIntegrator
* @brief explicit Euler method for integrating fast electron fields
*/
class FieldImplicitEulerIntegrator : public FieldEulerIntegrator {
public:
/** Constructor */
FieldImplicitEulerIntegrator(
const FieldName fieldName,
const PhysicsModel * physicsModel,
/*const*/ FE_Engine * feEngine,
/*const*/ ATC_Transfer * atcTransfer,
const Array2D< bool > & rhsMask, // copy
const double alpha = 0.5 // default to trap/midpt
);
/** Destructor */
virtual ~FieldImplicitEulerIntegrator() {};
/** update */
void update(const double dt, const double time,
FIELDS & fields, FIELDS & rhs);
protected:
/** euler update factor */
double alpha_;
/** perturbation */
double dT_;
/** max number of restarts = size of basis */
int maxRestarts_;
/** max number of iterations */
int maxIterations_;
/** convergence tolerance */
double tol_;
};
} // namespace ATC
#endif

View File

@ -1,150 +0,0 @@
//*****************************************************************
// Iterative template routine -- GMRES
//
// GMRES solves the unsymmetric linear system Ax = b using the
// Generalized Minimum Residual method
//
// GMRES follows the algorithm described on p. 20 of the
// SIAM Templates book.
//
// The return value indicates convergence within max_iter (input)
// iterations (0), or no convergence within max_iter iterations (1).
//
// Upon successful return, output arguments have the following values:
//
// x -- approximate solution to Ax = b
// max_iter -- the number of iterations performed before the
// tolerance was reached
// tol -- the residual after the final iteration
//
//*****************************************************************
template < class Matrix, class Vector >
void
Update(Vector &x, int k, Matrix &h, Vector &s, Vector v[])
{
Vector y(s);
// Backsolve:
for (int i = k; i >= 0; i--) {
y(i) /= h(i,i);
for (int j = i - 1; j >= 0; j--)
y(j) -= h(j,i) * y(i);
}
for (int j = 0; j <= k; j++)
x += v[j] * y(j);
}
template < class Real >
Real
abs(Real x)
{
return (x > 0 ? x : -x);
}
#include <math.h>
template<class Real>
void GeneratePlaneRotation(Real &dx, Real &dy, Real &cs, Real &sn)
{
if (dy == 0.0) {
cs = 1.0;
sn = 0.0;
} else if (abs(dy) > abs(dx)) {
Real temp = dx / dy;
sn = 1.0 / sqrt( 1.0 + temp*temp );
cs = temp * sn;
} else {
Real temp = dy / dx;
cs = 1.0 / sqrt( 1.0 + temp*temp );
sn = temp * cs;
}
}
template<class Real>
void ApplyPlaneRotation(Real &dx, Real &dy, Real &cs, Real &sn)
{
Real temp = cs * dx + sn * dy;
dy = -sn * dx + cs * dy;
dx = temp;
}
template < class Operator, class Vector, class Preconditioner,
class Matrix, class Real >
int
GMRES(const Operator &A, Vector &x, const Vector &b,
const Preconditioner &M, Matrix &H, int &m, int &max_iter,
Real &tol)
{
Real resid;
int i, j = 1, k;
Vector s(m+1), cs(m+1), sn(m+1), w;
Vector p = inv(M)*b;
Real normb = p.norm();
Vector r = inv(M) * (b - A * x);
Real beta = r.norm();
if (normb == 0.0)
normb = 1;
if ((resid = r.norm() / normb) <= tol) {
tol = resid;
max_iter = 0;
return 0;
}
Vector *v = new Vector[m+1];
while (j <= max_iter) {
v[0] = r * (1.0 / beta); // ??? r / beta
s = 0.0;
s(0) = beta;
for (i = 0; i < m && j <= max_iter; i++, j++) {
w = inv(M) * (A * v[i]);
for (k = 0; k <= i; k++) {
H(k, i) = w.dot(v[k]);
w -= H(k, i) * v[k];
}
H(i+1, i) = w.norm();
v[i+1] = w * (1.0 / H(i+1, i)); // ??? w / H(i+1, i)
for (k = 0; k < i; k++)
ApplyPlaneRotation(H(k,i), H(k+1,i), cs(k), sn(k));
GeneratePlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
ApplyPlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
ApplyPlaneRotation(s(i), s(i+1), cs(i), sn(i));
if ((resid = abs(s(i+1)) / normb) < tol) {
Update(x, i, H, s, v);
tol = resid;
max_iter = j;
delete [] v;
return 0;
}
}
Update(x, m - 1, H, s, v);
r = inv(M) * (b - A * x);
beta = r.norm();
if ((resid = beta / normb) < tol) {
tol = resid;
max_iter = j;
delete [] v;
return 0;
}
}
tol = resid;
delete [] v;
return 1;
}

View File

@ -1,160 +0,0 @@
// Header file for this class
#include "ImplicitSolveOperator.h"
// Other ATC includes
#include "ATC_Transfer.h"
#include "FE_Engine.h"
#include "PhysicsModel.h"
#include "PrescribedDataManager.h"
namespace ATC {
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// ImplicitSolveOperator
// --------------------------------------------------------------------
// --------------------------------------------------------------------
ImplicitSolveOperator::
ImplicitSolveOperator(ATC_Transfer * atcTransfer,
/*const*/ FE_Engine * feEngine,
const PhysicsModel * physicsModel)
: atcTransfer_(atcTransfer),
feEngine_(feEngine),
physicsModel_(physicsModel)
{
// Nothing else to do here
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// FieldImplicitSolveOperator
// --------------------------------------------------------------------
// --------------------------------------------------------------------
FieldImplicitSolveOperator::
FieldImplicitSolveOperator(ATC_Transfer * atcTransfer,
/*const*/ FE_Engine * feEngine,
FIELDS & fields,
const FieldName fieldName,
const Array2D< bool > & rhsMask,
const PhysicsModel * physicsModel,
double simTime,
double dt,
double alpha)
: ImplicitSolveOperator(atcTransfer, feEngine, physicsModel),
fields_(fields), // ref to fields
fieldName_(fieldName),
simTime_(simTime),
dt_(dt),
alpha_(alpha),
epsilon0_(1.0e-8)
{
// find field associated with ODE
rhsMask_.reset(NUM_FIELDS,NUM_FLUX);
rhsMask_ = false;
for (int i = 0; i < rhsMask.nCols(); i++) {
rhsMask_(fieldName_,i) = rhsMask(fieldName_,i);
}
massMask_.reset(1);
massMask_(0) = fieldName_;
// Save off current field
TnVect_ = column(fields_[fieldName_],0); // NOTE assuming 1 dof ?
// Allocate vectors for fields and rhs
int nNodes = atcTransfer_->get_nNodes();
// copy fields
fieldsNp1_ = fields_;
// size rhs
int dof = fields_[fieldName_].nCols();
RnMap_ [fieldName_].reset(nNodes,dof);
RnpMap_[fieldName_].reset(nNodes,dof);
// Compute the RHS vector R(T^n)
// Set BCs on Rn, multiply by inverse mass and then extract its vector
atcTransfer_->compute_rhs_vector(rhsMask_, fields_, RnMap_,
atcTransfer_->FULL_DOMAIN, physicsModel_);
DENS_MAT & Rn = RnMap_[fieldName_];
atcTransfer_->get_prescribed_data_manager()
->set_fixed_dfield(simTime_, fieldName_, Rn);
atcTransfer_->apply_inverse_mass_matrix(Rn,fieldName_);
RnVect_ = column(Rn,0);
}
// --------------------------------------------------------------------
// operator *(Vector)
// --------------------------------------------------------------------
DENS_VEC
FieldImplicitSolveOperator::operator * (DENS_VEC x) const
{
// This method uses a matrix-free approach to approximate the
// multiplication by matrix A in the matrix equation Ax=b, where the
// matrix equation results from an implicit treatment of the
// fast field solve for the Two Temperature Model. In
// brief, if the ODE for the fast field can be written:
//
// dT/dt = R(T)
//
// A generalized discretization can be written:
//
// 1/dt * (T^n+1 - T^n) = alpha * R(T^n+1) + (1-alpha) * R(T^n)
//
// Taylor expanding the R(T^n+1) term and rearranging gives the
// equation to be solved for dT at each timestep:
//
// [1 - dt * alpha * dR/dT] * dT = dt * R(T^n)
//
// The operator defined in this method computes the left-hand side,
// given a vector dT. It uses a finite difference, matrix-free
// approximation of dR/dT * dT, giving:
//
// [1 - dt * alpha * dR/dT] * dT = dt * R(T^n)
// ~= dT - dt*alpha/epsilon * ( R(T^n + epsilon*dT) - R(T^n) )
//
// Compute epsilon
double epsilon = (x.norm() > 0.0) ? epsilon0_ * TnVect_.norm()/x.norm() : epsilon0_;
// Compute incremented vector = T + epsilon*dT
fieldsNp1_[fieldName_] = TnVect_ + epsilon * x;
// Evaluate R(b)
atcTransfer_->compute_rhs_vector(rhsMask_, fieldsNp1_, RnpMap_,
atcTransfer_->FULL_DOMAIN, physicsModel_);
DENS_MAT & Rnp = RnpMap_[fieldName_];
atcTransfer_->get_prescribed_data_manager()
->set_fixed_dfield(simTime_, fieldName_, Rnp);
atcTransfer_->apply_inverse_mass_matrix(Rnp,fieldName_);
RnpVect_ = column(Rnp,0);
// Compute full left hand side and return it
DENS_VEC Ax = x - dt_ * alpha_ / epsilon * (RnpVect_ - RnVect_);
return Ax;
}
// --------------------------------------------------------------------
// get_rhs
// --------------------------------------------------------------------
DENS_VEC
FieldImplicitSolveOperator::get_rhs()
{
// Return dt * R(T^n)
return dt_ * RnVect_;
}
// --------------------------------------------------------------------
// get_preconditioner
// --------------------------------------------------------------------
DIAG_MAT
FieldImplicitSolveOperator::get_preconditioner(FIELDS & fields)
{
// Just create and return identity matrix
int nNodes = atcTransfer_->get_nNodes();
DENS_VEC ones(nNodes);
ones = 1.0;
DIAG_MAT identity(ones);
return identity;
}
} // namespace ATC

View File

@ -1,129 +0,0 @@
#ifndef IMPLICIT_SOLVE_OPERATOR_H
#define IMPLICIT_SOLVE_OPERATOR_H
// ATC includes
#include "Array2D.h"
#include "MatrixLibrary.h"
#include "PhysicsModel.h"
// other includes
#include <vector>
#include <map>
namespace ATC {
// Forward class declarations
class ATC_Transfer;
class FE_Engine;
/**
* @class ImplicitSolveOperator
* @brief Helper class to compute matrix-free product for use with IML++ solvers
*/
class ImplicitSolveOperator {
public:
/** Constructor */
ImplicitSolveOperator(ATC_Transfer * atcTransfer,
/*const*/ FE_Engine * feEngine,
const PhysicsModel * physicsModel);
/** Destructor */
virtual ~ImplicitSolveOperator() {};
/** pure virtual operator to compute Ax, for equation Ax=b */
virtual DENS_VEC operator * (DENS_VEC x) const = 0;
/** pure virtual method to return the rhs vector b */
virtual DENS_VEC get_rhs() = 0;
/** pure virtual method to return preconditioner */
virtual DiagonalMatrix<double> get_preconditioner(FIELDS & fields) = 0;
protected:
/** Pointer to ATC_Tranfer */
ATC_Transfer * atcTransfer_;
/** Pointer to FE_Engine */
/*const*/ FE_Engine * feEngine_;
/** Pointer to PhysicsModel */
const PhysicsModel * physicsModel_;
};
/**
* @class FieldImplicitSolveOperator
* @brief Class to perform A*x operation for electron temperature solution
*/
class FieldImplicitSolveOperator : public ImplicitSolveOperator {
public:
/** Constructor */
FieldImplicitSolveOperator(ATC_Transfer * atc_Transfer,
/*const*/ FE_Engine * fe_Engine,
FIELDS & fields,
const FieldName electronField,
const Array2D< bool > & rhsMask,
const PhysicsModel * physicsModel,
double simTime,
double dt,
double alpha);
/** Destructor */
virtual ~FieldImplicitSolveOperator() {};
/** operator to compute A*x for the electron temperature equation */
virtual DENS_VEC operator * (DENS_VEC x) const;
/** method to return the rhs vector b */
virtual DENS_VEC get_rhs();
/** method to return preconditioner (identity matrix) */
virtual DIAG_MAT get_preconditioner(FIELDS & fields);
protected:
// field name of ODE to solve
FieldName fieldName_;
// Reference to current fields (passed in constructor)
FIELDS & fields_;
// Local fields
mutable FIELDS fieldsNp1_;
// Vector to hold current temperature
DENS_VEC TnVect_;
// Old and new RHS maps (not including inverse mass)
FIELDS RnMap_;
mutable FIELDS RnpMap_;
// Matrices/vectors to hold electron temperature components of RHS
// vectors (including inverse mass)
DENS_VEC RnVect_;
mutable DENS_VEC RnpVect_;
Array2D<bool> rhsMask_;
Array<FieldName> massMask_;
// simulation time
double simTime_;
// timestep
double dt_;
// implicit/explicit parameter (0 -> explicit, else implicit)
double alpha_;
// small parameter to compute increment
double epsilon0_;
};
} // namespace ATC
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,488 +0,0 @@
#ifndef KINETOSTAT_H
#define KINETOSTAT_H
// ATC_Transfer headers
#include "AtomicRegulator.h"
// other headers
#include <map>
#include <set>
namespace ATC {
/**
* @class Kinetostat
* @brief Manager class for atom-continuum control of momentum and position
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class Kinetostat
//--------------------------------------------------------
//--------------------------------------------------------
class Kinetostat : public AtomicRegulator {
public:
/** kinetostat types */
enum KinetostatType {
NONE=0,
GLC_DISPLACEMENT,
GLC_VELOCITY,
FORCE
};
enum KinetostatCouplingType {
UNCOUPLED=0,
FLUX,
FIXED
};
// constructor
Kinetostat(ATC_Transfer *atcTransfer);
// destructor
~Kinetostat(){};
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
// data access, intended for method objects
/** reset the nodal force to a prescribed value */
void reset_lambda_force(DENS_MAT & target);
/** return the nodal force induced by lambda */
DENS_MAT & get_nodal_atomic_lambda_force() { return nodalAtomicLambdaForce_;}
/** return value of filtered lambda */
DENS_MAT & get_lambda_force_filtered() { return lambdaForceFiltered_;}
/** access to kinetostat type */
KinetostatType get_kinetostat_type() const
{ return kinetostatType_;};
KinetostatCouplingType get_coupling_mode() const
{ return couplingMode_;};
protected:
/** kinetostat type flag */
KinetostatType kinetostatType_;
/** kinetostat copuling type flag */
KinetostatCouplingType couplingMode_;
// kinetostat data
/** lambda force applied to atoms */
DENS_MAT nodalAtomicLambdaForce_;
/** filtered lambda force */
DENS_MAT lambdaForceFiltered_;
private:
// DO NOT define this
Kinetostat();
};
/**
* @class GlcKinetostat
* @brief Base class for implementation of kinetostat algorithms based on Gaussian least constraints (GLC)
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class GlcKinetostat
// base class for all thermostats of general form of a
// Gaussian least constraint (GLC)
//--------------------------------------------------------
//--------------------------------------------------------
class GlcKinetostat : public RegulatorShapeFunction {
public:
GlcKinetostat(Kinetostat *kinetostat);
~GlcKinetostat(){};
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal();
protected:
// methods
/** apply forces to atoms */
virtual void apply_to_atoms(double ** atomicQuantity,
const DENS_MAT & lambdaAtom,
double dt=0.);
/** set weighting factor for in matrix Nhat^T * weights * Nhat */
virtual void set_weights(DIAG_MAT & weights);
/** apply any required corrections for localized kinetostats */
virtual void apply_localization_correction(const DENS_MAT & source,
DENS_MAT & nodalField,
double weight = 1.){};
// member data
/** pointer to thermostat object for data */
Kinetostat * kinetostat_;
/** pointer to a time filtering object */
TimeFilter * timeFilter_;
/** stress induced by lambda */
DENS_MAT & nodalAtomicLambdaForce_;
/** filtered lambda force */
DENS_MAT & lambdaForceFiltered_;
/** atomic force induced by lambda */
DENS_MAT & lambdaForce_;
/** MD mass matrix */
MATRIX & mdMassMatrix_;
/** mass of ATC internal atoms on this processor */
DENS_VEC atomicMass_;
/** reference to ATC map from global nodes to overlap nodes */
Array<int> & nodeToOverlapMap_;
/** nodeset corresponding to Hoover coupling */
set<pair<int,int> > hooverNodes_;
private:
// DO NOT define this
GlcKinetostat();
};
/**
* @class DisplacementGlc
* @brief Enforces GLC on atomic position based on FE displacement
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class DisplacementGlc
//--------------------------------------------------------
//--------------------------------------------------------
class DisplacementGlc : public GlcKinetostat {
public:
DisplacementGlc(Kinetostat * kinetostat);
~DisplacementGlc(){};
/** applies kinetostat to atoms */
virtual void apply_post_predictor(double dt);
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
// methods
/** set weighting factor for in matrix Nhat^T * weights * Nhat */
virtual void set_weights(DIAG_MAT & weights);
/** does initial filtering operations before main computation */
virtual void apply_pre_filtering(double dt);
/** compute force induced by lambda */
virtual void compute_lambda_force(DENS_MAT & lambdaForce, DENS_MAT & lambdaAtom, double dt);
/** sets up and solves kinetostat equations */
virtual void compute_kinetostat(double dt);
/** sets up appropriate rhs for kinetostat equations */
virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
/** computes the nodal FE force applied by the kinetostat */
virtual void compute_nodal_lambda_force(double dt);
/** apply any required corrections for localized kinetostats */
virtual void apply_localization_correction(const DENS_MAT & source,
DENS_MAT & nodalField,
double weight = 1.);
// data
/** clone of FE displacement field */
DENS_MAT & nodalDisplacements_;
/** pointer to lammps atomic positions */
double ** x_;
private:
// DO NOT define this
DisplacementGlc();
};
/**
* @class DisplacementGlcFiltered
* @brief Enforces GLC on time filtered atomic position based on FE displacement
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class DisplacementGlcFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class DisplacementGlcFiltered : public DisplacementGlc {
public:
DisplacementGlcFiltered(Kinetostat * kinetostat);
~DisplacementGlcFiltered(){};
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
// methods
/** does initial filtering operations before main computation */
virtual void apply_pre_filtering(double dt);
/** sets up appropriate rhs for kinetostat equations */
virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
/** computes the nodal FE force applied by the kinetostat */
virtual void compute_nodal_lambda_force(double dt);
// data
/** clone of FE nodal atomic displacement field */
DENS_MAT & nodalAtomicDisplacements_;
private:
// DO NOT define this
DisplacementGlcFiltered();
};
/**
* @class VelocityGlc
* @brief Enforces GLC on atomic velocity based on FE velocity
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class VelocityGlc
//--------------------------------------------------------
//--------------------------------------------------------
class VelocityGlc : public GlcKinetostat {
public:
VelocityGlc(Kinetostat * kinetostat);
~VelocityGlc(){};
/** applies kinetostat to atoms */
virtual void apply_mid_predictor(double dt);
/** applies kinetostat to atoms */
virtual void apply_post_corrector(double dt);
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
// methods
/** set weighting factor for in matrix Nhat^T * weights * Nhat */
virtual void set_weights(DIAG_MAT & weights);
/** compute force induced by lambda */
virtual void compute_lambda_force(DENS_MAT & lambdaForce, DENS_MAT & lambdaAtom, double dt);
/** does initial filtering operations before main computation */
virtual void apply_pre_filtering(double dt);
/** sets up and solves kinetostat equations */
virtual void compute_kinetostat(double dt);
/** sets up appropriate rhs for kinetostat equations */
virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
/** computes the nodal FE force applied by the kinetostat */
virtual void compute_nodal_lambda_force(double dt);
/** apply any required corrections for localized kinetostats */
virtual void apply_localization_correction(const DENS_MAT & source,
DENS_MAT & nodalField,
double weight = 1.);
// data
/** clone of FE velocity field */
DENS_MAT & nodalVelocities_;
/** pointer to lammps atomic velocities */
double ** v_;
private:
// DO NOT define this
VelocityGlc();
};
/**
* @class VelocityGlcFiltered
* @brief Enforces GLC on time filtered atomic velocity based on FE velocity
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class VelocityGlcFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class VelocityGlcFiltered : public VelocityGlc {
public:
VelocityGlcFiltered(Kinetostat * kinetostat);
~VelocityGlcFiltered(){};
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
// methods
/** does initial filtering operations before main computation */
virtual void apply_pre_filtering(double dt);
/** sets up appropriate rhs for kinetostat equations */
virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
/** computes the nodal FE force applied by the kinetostat */
virtual void compute_nodal_lambda_force(double dt);
// data
/** clone of FE nodal atomic velocity field */
DENS_MAT & nodalAtomicVelocities_;
private:
// DO NOT define this
VelocityGlcFiltered();
};
/**
* @class StressFlux
* @brief Enforces GLC on atomic forces based on FE stresses or accelerations
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class StressFlux
//--------------------------------------------------------
//--------------------------------------------------------
class StressFlux : public GlcKinetostat {
public:
StressFlux(Kinetostat * kinetostat);
~StressFlux();
/** applies kinetostat to atoms in the mid-predictor phase */
virtual void apply_mid_predictor(double dt);
/** applies kinetostat to atoms in the pre-corrector phase */
virtual void apply_pre_corrector(double dt);
/** applies kinetostat to atoms in the post-corrector phase */
virtual void apply_post_corrector(double dt);
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
/** sets filtered ghost force to prescribed value */
void reset_filtered_ghost_force(DENS_MAT & targetForce);
/** returns reference to filtered ghost force */
DENS_MAT & get_filtered_ghost_force() {return nodalGhostForceFiltered_;};
protected:
// data
/** nodal force */
DENS_MAT & nodalForce_;
/** nodal force due to atoms */
DENS_MAT & nodalAtomicForce_;
/** nodal ghost force */
DENS_MAT nodalGhostForce_;
/** filtered ghost force */
DENS_MAT nodalGhostForceFiltered_;
/** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
DENS_MAT & momentumSource_;
/** pointer to lammps atomic velocities */
double ** v_;
/** pointer to lammps atomic forces */
double ** f_;
#if false
/** initial lammps atomic forces */
double ** f0_;
#endif
// methods
/** compute force induced by lambda */
virtual void compute_lambda_force(DENS_MAT & lambdaForce);
/** does initial filtering operations before main computation */
virtual void apply_pre_filtering(double dt);
/** sets up and solves kinetostat equations */
virtual void compute_kinetostat(double dt);
/** sets up appropriate rhs for kinetostat equations */
virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
/** computes the nodal FE force applied by the kinetostat */
virtual void compute_nodal_lambda_force(double dt);
/** apply forces to atoms */
virtual void apply_to_atoms(double ** atomicVelocity,
const DENS_MAT & lambdaForce,
double dt);
/** adds in finite element rhs contributions */
virtual void add_to_rhs(FIELDS & rhs);
/** computes restricted force on ghost atoms */
void compute_ghost_force(DENS_MAT & nodalGhostForce);
private:
// DO NOT define this
StressFlux();
};
/**
* @class StressFluxFiltered
* @brief Enforces GLC on time filtered atomic forces based on FE stresses or accelerations
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class StressFluxFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class StressFluxFiltered : public StressFlux {
public:
StressFluxFiltered(Kinetostat * kinetostat);
~StressFluxFiltered(){};
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
// data
DENS_MAT & nodalAtomicVelocity_;
// methods
/** sets up appropriate rhs for kinetostat equations */
virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
/** adds in finite element rhs contributions */
virtual void add_to_rhs(FIELDS & rhs);
/** apply forces to atoms */
virtual void apply_to_atoms(double ** atomicVelocity,
const DENS_MAT & lambdaForce,
double dt);
private:
// DO NOT define this
StressFluxFiltered();
};
};
#endif

View File

@ -1,671 +0,0 @@
// Header file for this class
#include "LammpsInterface.h"
// LAMMPS includes
#include "lammps.h"
#include "lmptype.h"
#include "atom.h" // x, v, f
#include "domain.h" // for basing locations on regions
#include "region.h" // region bounding box and style
#include "force.h" // boltzman constant
#include "group.h" // atom masks
#include "memory.h" // grow atom information
#include "compute.h" // computes
#include "modify.h" //
#include "neighbor.h" // neighbors
#include "neigh_list.h" // neighbor list
#include "update.h" // timestepping information
#include "pair.h" // pair potentials
#include "lattice.h" // lattice parameters
#include "comm.h" //
// ATC includes
#include "ATC_Error.h"
#include "MatrixLibrary.h"
// Other include files
#include "mpi.h"
#include <cstring>
namespace ATC {
LammpsInterface * LammpsInterface::myInstance_ = NULL;
// -----------------------------------------------------------------
// instance()
// -----------------------------------------------------------------
LammpsInterface * LammpsInterface::instance()
{
if (myInstance_ == NULL) {
myInstance_ = new LammpsInterface();
}
return myInstance_;
}
// -----------------------------------------------------------------
// constructor
// -----------------------------------------------------------------
LammpsInterface::LammpsInterface()
: lammps_(NULL),
atomPE_(NULL),
commRank_(0)
{
}
// -----------------------------------------------------------------
// general interface methods
// -----------------------------------------------------------------
MPI_Comm LammpsInterface::world() { return lammps_->world; }
// -----------------------------------------------------------------
// atom interface methods
// -----------------------------------------------------------------
int LammpsInterface::nlocal() { return lammps_->atom->nlocal; }
int LammpsInterface::nghost() { return lammps_->atom->nghost; }
double LammpsInterface::natoms() { return lammps_->atom->natoms; }
int LammpsInterface::nmax() { return lammps_->atom->nmax; }
int LammpsInterface::ntypes() { return lammps_->atom->ntypes; }
double ** LammpsInterface::xatom() { return lammps_->atom->x; }
const double ** LammpsInterface::xatom() const { return (const double**)(lammps_->atom->x); }
double ** LammpsInterface::vatom() { return lammps_->atom->v; }
double ** LammpsInterface::fatom() { return lammps_->atom->f; }
int * LammpsInterface::atom_mask() { return lammps_->atom->mask; }
int * LammpsInterface::atom_type() { return lammps_->atom->type; }
int * LammpsInterface::atom_tag() { return lammps_->atom->tag; }
double * LammpsInterface::atom_mass() { return lammps_->atom->mass; }
double LammpsInterface::atom_mass(int iType) { return lammps_->atom->mass[iType]; }
double * LammpsInterface::atom_rmass() { return lammps_->atom->rmass; }
double * LammpsInterface::atom_charge() { return lammps_->atom->q; }
// -----------------------------------------------------------------
// domain interface methods
// -----------------------------------------------------------------
int LammpsInterface::dimension() { return lammps_->domain->dimension; }
int LammpsInterface::nregion() { return lammps_->domain->nregion; }
void LammpsInterface::get_box_bounds(double & boxxlo, double & boxxhi,
double & boxylo, double & boxyhi,
double & boxzlo, double &boxzhi)
{
if (lammps_->domain->triclinic == 0) {
boxxlo = lammps_->domain->boxlo[0];
boxxhi = lammps_->domain->boxhi[0];
boxylo = lammps_->domain->boxlo[1];
boxyhi = lammps_->domain->boxhi[1];
boxzlo = lammps_->domain->boxlo[2];
boxzhi = lammps_->domain->boxhi[2];
}
else {
boxxlo = lammps_->domain->boxlo_bound[0];
boxxhi = lammps_->domain->boxhi_bound[0];
boxylo = lammps_->domain->boxlo_bound[1];
boxyhi = lammps_->domain->boxhi_bound[1];
boxzlo = lammps_->domain->boxlo_bound[2];
boxzhi = lammps_->domain->boxhi_bound[2];
}
}
int LammpsInterface::xperiodic() { return lammps_->domain->xperiodic; }
int LammpsInterface::yperiodic() { return lammps_->domain->yperiodic; }
int LammpsInterface::zperiodic() { return lammps_->domain->zperiodic; }
int LammpsInterface::nperiodic()
{
int nprd = 0;
if ( lammps_->domain->xperiodic > 0 ) { nprd++ ; }
if ( lammps_->domain->yperiodic > 0 ) { nprd++ ; }
if ( lammps_->domain->zperiodic > 0 ) { nprd++ ; }
return nprd;
}
double LammpsInterface::domain_xprd() { return lammps_->domain->xprd; }
double LammpsInterface::domain_yprd() { return lammps_->domain->yprd; }
double LammpsInterface::domain_zprd() { return lammps_->domain->zprd; }
double LammpsInterface::domain_xy() { return lammps_->domain->xy; }
double LammpsInterface::domain_xz() { return lammps_->domain->xz; }
double LammpsInterface::domain_yz() { return lammps_->domain->yz; }
int LammpsInterface::domain_triclinic() { return lammps_->domain->triclinic; }
void LammpsInterface::get_box_periodicity(int & xperiodic,
int & yperiodic,
int & zperiodic)
{
xperiodic = lammps_->domain->xperiodic;
yperiodic = lammps_->domain->yperiodic;
zperiodic = lammps_->domain->zperiodic;
}
int LammpsInterface::get_region_id(const char * regionName) {
int nregion = this->nregion();
for (int iregion = 0; iregion < nregion; iregion++) {
if (strcmp(regionName, region_name(iregion)) == 0) {
return iregion;
}
}
throw ATC_Error(0,"Region has not been defined");
return -1;
}
// -----------------------------------------------------------------
// update interface methods
// -----------------------------------------------------------------
LammpsInterface::UnitsType LammpsInterface::units_style(void)
{
if (strcmp(lammps_->update->unit_style,"lj") == 0) return LJ;
else if (strcmp(lammps_->update->unit_style,"real") == 0) return REAL;
else if (strcmp(lammps_->update->unit_style,"metal") == 0) return METAL;
else return UNKNOWN;
}
// -----------------------------------------------------------------
// lattice interface methods
// -----------------------------------------------------------------
double LammpsInterface::xlattice() { return lammps_->domain->lattice->xlattice; }
double LammpsInterface::ylattice() { return lammps_->domain->lattice->ylattice; }
double LammpsInterface::zlattice() { return lammps_->domain->lattice->zlattice; }
LammpsInterface::LatticeType LammpsInterface::lattice_style()
{
if (lammps_->domain->lattice)
return (LammpsInterface::LatticeType)lammps_->domain->lattice->style;
else
throw ATC_Error(0,"Lattice has not been defined");
}
//* retuns the number of basis vectors
int LammpsInterface::get_n_basis()
{
return lammps_->domain->lattice->nbasis;
}
//* returns the basis vectors, transformed to the box coords
void LammpsInterface::get_basis(double **basis)
{
LAMMPS_NS::Lattice *lattice = lammps_->domain->lattice;
int i,j;
double origin[3] = {0.0, 0.0, 0.0};
lattice->lattice2box(origin[0], origin[1], origin[2]);
for (i=0; i<get_n_basis(); i++)
{
memcpy(basis[i],lattice->basis[i],3*sizeof(double));
lattice->lattice2box(basis[i][0], basis[i][1], basis[i][2]);
for (j=0; j<3; j++) basis[i][j] -= origin[j];
}
}
//* gets the unit cell vectors
void LammpsInterface::get_unit_cell(double *a1, double *a2, double *a3)
{
int i, j;
double *a[3] = {a1,a2,a3};
double origin[3] = {0.0,0.0,0.0};
LAMMPS_NS::Lattice *lattice = lammps_->domain->lattice;
// transform origin
lattice->lattice2box(origin[0], origin[1], origin[2]);
// copy reference lattice vectors
memcpy(a[0], lattice->a1, 3*sizeof(double));
memcpy(a[1], lattice->a2, 3*sizeof(double));
memcpy(a[2], lattice->a3, 3*sizeof(double));
for (i=0; i<3; i++)
{
lattice->lattice2box(a[i][0], a[i][1], a[i][2]);
for (j=0; j<3; j++) a[i][j] -= origin[j];
}
}
//* gets number of atoms in a unit cell
int LammpsInterface::num_atoms_per_cell(void)
{
int naCell = 0;
LatticeType type = lattice_style();
if (type == LammpsInterface::SC) naCell = 1;
else if (type == LammpsInterface::BCC) naCell = 2;
else if (type == LammpsInterface::FCC) naCell = 4;
else if (type == LammpsInterface::DIAMOND) naCell = 8;
else if (comm_rank()==0) {
//{throw ATC_Error(0,"lattice style not currently supported by ATC");}
cout << "ATC WARNING: Cannot get number of atoms per cell from lattice\n";
naCell = 1; //HACK to enable us to keep going since this is only used to compute volume per atom
// ATC modes with a user specified atomic volume or using only volumetric quantities are fine
}
return naCell;
}
//* gets tributary volume for an atom
double LammpsInterface::volume_per_atom(void)
{
double naCell = num_atoms_per_cell();
double volPerAtom =
xlattice() * ylattice() * zlattice() / naCell;
return volPerAtom;
}
//* gets lattice basis
void LammpsInterface::get_lattice(MATRIX &N, MATRIX &B)
{
int nbasis = get_n_basis();
double **basis = new double*[nbasis];
N.reset(3,3);
B.reset(3,nbasis);
for (int i=0; i<nbasis; i++) basis[i] = column(B,i).get_ptr();
get_basis(basis);
get_unit_cell(column(N,0).get_ptr(),
column(N,1).get_ptr(),
column(N,2).get_ptr());
delete [] basis;
}
// -----------------------------------------------------------------
// force interface methods
// -----------------------------------------------------------------
double LammpsInterface::boltz() { return lammps_->force->boltz; }
double LammpsInterface::mvv2e() { return lammps_->force->mvv2e; }
double LammpsInterface::ftm2v() { return lammps_->force->ftm2v; }
double LammpsInterface::nktv2p() { return lammps_->force->nktv2p; }
double LammpsInterface::qqr2e() { return lammps_->force->qqr2e; }
double LammpsInterface::qe2f() { return lammps_->force->qe2f; }
double LammpsInterface::dielectric() { return lammps_->force->dielectric; }
double LammpsInterface::qqrd2e() { return lammps_->force->qqrd2e; }
double LammpsInterface::pair_force(int i, int j, double rsq,
double & fmag_over_rmag)
{
int itype = (lammps_->atom->type)[i];
int jtype = (lammps_->atom->type)[j];
// return value is the energy
if (rsq < (lammps_->force->pair->cutsq)[itype][jtype]) {
return lammps_->force->pair->single(i,j,itype,jtype,
rsq,1.0,1.0,fmag_over_rmag);
}
return 0.0;
}
double LammpsInterface::pair_cutoff()
{
return lammps_->force->pair->cutforce;
}
int LammpsInterface::single_enable()
{
return lammps_->force->pair->single_enable;
}
//* Boltzmann's constant in M,L,T,t units
double LammpsInterface::kBoltzmann() {
return (lammps_->force->boltz)/(lammps_->force->mvv2e);
}
//* Dulong-Petit heat capacity
double LammpsInterface::heat_capacity() {
double rhoCp = dimension()*kBoltzmann()/volume_per_atom();
return rhoCp;
}
//* reference mass density
double LammpsInterface::mass_density()
{
const int ntypes = lammps_->atom->ntypes;
const int *mass_setflag = lammps_->atom->mass_setflag;
const int *type = lammps_->atom->type;
const double *mass = lammps_->atom->mass;
const double *rmass = lammps_->atom->rmass;
// NOTE currently assumes all atoms have same mass and volume
// in the future, mass and volume will be different but density should be
// an atom indepedent quantity
if (mass) {
if (type) return mass[type[0]]/volume_per_atom();
// no type array - just use first type that has a set mass
for (int i=1; i<=ntypes; i++) {
if (mass_setflag[i]) return mass[i]/volume_per_atom();
}
// NOTE: no masses specified in input file should we warn the user of this?
return 0.0;
}
// NOTE is this valid - lammps likes to not use 0 index
if (rmass) return rmass[0]/volume_per_atom();
return 0.0;
}
// -----------------------------------------------------------------
// group interface methods
// -----------------------------------------------------------------
int LammpsInterface::ngroup() { return lammps_->group->ngroup; }
int LammpsInterface::group_bit(int iGroup) { return lammps_->group->bitmask[iGroup]; }
int LammpsInterface::find_group(const char * c) { return lammps_->group->find(c); }
int LammpsInterface::group_inverse_mask(int iGroup)
{
return lammps_->group->inversemask[iGroup];
}
char * LammpsInterface::group_name(int iGroup)
{
return lammps_->group->names[iGroup];
}
void LammpsInterface::group_bounds(int iGroup, double * b)
{
lammps_->group->bounds(iGroup, b);
}
// -----------------------------------------------------------------
// memory interface methods
// -----------------------------------------------------------------
double * LammpsInterface::create_1d_double_array(int nlo, int nhi, const char *name) {
double *array;
return lammps_->memory->create1d_offset(array, nlo, nhi, name);
}
void LammpsInterface::destroy_1d_double_array(double * d, int i) {
lammps_->memory->destroy1d_offset(d, i);
}
double ** LammpsInterface::create_2d_double_array(int n1, int n2, const char *name) {
double **array;
return lammps_->memory->create(array, n1, n2, name);
}
void LammpsInterface::destroy_2d_double_array(double **d) {
lammps_->memory->destroy(d);
}
double **LammpsInterface::grow_2d_double_array(double **array,
int n1,
int n2,
const char *name)
{
return lammps_->memory->grow(array, n1, n2, name);
}
int ** LammpsInterface::create_2d_int_array(int n1, int n2, const char *name) {
int **array;
return lammps_->memory->create(array, n1, n2, name);
}
void LammpsInterface::destroy_2d_int_array(int **i) {
lammps_->memory->destroy(i);
}
int ** LammpsInterface::grow_2d_int_array(int **array, int n1, int n2, const char *name) {
return lammps_->memory->grow(array, n1, n2, name);
}
// -----------------------------------------------------------------
// update interface methods
// -----------------------------------------------------------------
double LammpsInterface::dt() { return lammps_->update->dt; }
int LammpsInterface::ntimestep() { return lammps_->update->ntimestep; }
int LammpsInterface::nsteps() { return lammps_->update->nsteps; }
// -----------------------------------------------------------------
// neighbor list interface methods
// -----------------------------------------------------------------
void LammpsInterface::init_list(int id, LAMMPS_NS::NeighList *ptr) { list_ = ptr; }
int LammpsInterface::neighbor_list_inum() { return list_->inum; }
int * LammpsInterface::neighbor_list_numneigh() { return list_->numneigh; }
int * LammpsInterface::neighbor_list_ilist() { return list_->ilist; }
int ** LammpsInterface::neighbor_list_firstneigh() { return list_->firstneigh; }
int LammpsInterface::neighbor_ago() { return lammps_->neighbor->ago; }
// -----------------------------------------------------------------
// region interface methods
// -----------------------------------------------------------------
char * LammpsInterface::region_name(int iRegion)
{
return lammps_->domain->regions[iRegion]->id;
}
char * LammpsInterface::region_style(int iRegion)
{
return lammps_->domain->regions[iRegion]->style;
}
double LammpsInterface::region_xlo(int iRegion)
{
return lammps_->domain->regions[iRegion]->extent_xlo;
}
double LammpsInterface::region_xhi(int iRegion)
{
return lammps_->domain->regions[iRegion]->extent_xhi;
}
double LammpsInterface::region_ylo(int iRegion)
{
return lammps_->domain->regions[iRegion]->extent_ylo;
}
double LammpsInterface::region_yhi(int iRegion)
{
return lammps_->domain->regions[iRegion]->extent_yhi;
}
double LammpsInterface::region_zlo(int iRegion)
{
return lammps_->domain->regions[iRegion]->extent_zlo;
}
double LammpsInterface::region_zhi(int iRegion)
{
return lammps_->domain->regions[iRegion]->extent_zhi;
}
double LammpsInterface::region_xscale(int iRegion)
{
return lammps_->domain->regions[iRegion]->xscale;
}
double LammpsInterface::region_yscale(int iRegion)
{
return lammps_->domain->regions[iRegion]->yscale;
}
double LammpsInterface::region_zscale(int iRegion)
{
return lammps_->domain->regions[iRegion]->zscale;
}
int LammpsInterface::region_match(int iRegion, double x, double y, double z) {
return lammps_->domain->regions[iRegion]->match(x,y,z);
}
// -----------------------------------------------------------------
// compute methods
// -----------------------------------------------------------------
int LammpsInterface::find_compute(const char* tag)
{
// a clunky way to safely get rid of the const
int n = strlen(tag) + 1;
char* tag_copy = new char[n];
strcpy(tag_copy,tag);
int icompute = lammps_->modify->find_compute(tag_copy);
if (icompute < 0) {
string msg("Could not find compute ");
msg += tag;
throw ATC_Error(0,msg);
}
return icompute;
}
LAMMPS_NS::Compute* LammpsInterface::get_compute(const char* tag)
{
int icompute = find_compute(tag);
LAMMPS_NS::Compute* cmpt = lammps_->modify->compute[icompute];
return cmpt;
}
double** LammpsInterface::compute_vector_data(const char* tag)
{
LAMMPS_NS::Compute* cmpt = get_compute(tag);
if (!(cmpt->invoked_flag & INVOKED_PERATOM)) {
cmpt->compute_peratom();
cmpt->invoked_flag |= INVOKED_PERATOM;
}
return cmpt->array_atom;
}
double* LammpsInterface::compute_scalar_data(const char* tag)
{
LAMMPS_NS::Compute* cmpt = get_compute(tag);
if (!(cmpt->invoked_flag & INVOKED_PERATOM)) {
cmpt->compute_peratom();
cmpt->invoked_flag |= INVOKED_PERATOM;
}
return cmpt->vector_atom;
}
int LammpsInterface::compute_ncols(const char* tag)
{
int icompute = find_compute(tag);
int ncols = lammps_->modify->compute[icompute]->size_peratom_cols;
if (ncols == 0) ncols = 1; // oddity of lammps, used as flag for scalar
return ncols;
}
// -----------------------------------------------------------------
// compute pe/atom interface methods
// -----------------------------------------------------------------
int LammpsInterface::atomPE_create(void)
{
//char * list[3] = {"atcPE","all","pe/atom"};
char * list[4] = {"atcPE","all","pe/atom","pair"};
int icompute = lammps_->modify->find_compute(list[0]);
if (icompute < 0) {
lammps_->modify->add_compute(3,list);
icompute = lammps_->modify->find_compute(list[0]);
}
if (! atomPE_ ) {
atomPE_ = lammps_->modify->compute[icompute];
}
return icompute;
}
void LammpsInterface::atomPE_init(void)
{
if (atomPE_) {
atomPE_->init();
}
else {
throw ATC_Error(0,"no atomPE compute");
}
}
void LammpsInterface::atomPE_addstep(LAMMPS_NS::bigint step)
{
atomPE_->addstep(step);
}
double * LammpsInterface::atomPE_compute(void)
{
if (atomPE_) {
atomPE_->compute_peratom();
return atomPE_->vector_atom;
}
else {
return NULL;
}
}
/* ---------------------------------------------------------------------- */
void LammpsInterface::unwrap_coordinates(int iatom, double* xatom)
{
double **x = lammps_->atom->x;
int *mask = lammps_->atom->mask;
int *image = lammps_->atom->image;
int nlocal = lammps_->atom->nlocal;
double *h = lammps_->domain->h;
double xprd = lammps_->domain->xprd;
double yprd = lammps_->domain->yprd;
double zprd = lammps_->domain->zprd;
int xbox,ybox,zbox;
// for triclinic, need to unwrap current atom coord via h matrix
// NOTE: Using current box dimensions.
if (lammps_->domain->triclinic == 0) {
xbox = (image[iatom] & 1023) - 512;
ybox = (image[iatom] >> 10 & 1023) - 512;
zbox = (image[iatom] >> 20) - 512;
xatom[0] = x[iatom][0] + xbox*xprd;
xatom[1] = x[iatom][1] + ybox*yprd;
xatom[2] = x[iatom][2] + zbox*zprd;
} else {
xbox = (image[iatom] & 1023) - 512;
ybox = (image[iatom] >> 10 & 1023) - 512;
zbox = (image[iatom] >> 20) - 512;
xatom[0] = x[iatom][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox;
xatom[1] = x[iatom][1] + h[1]*ybox + h[3]*zbox;
xatom[2] = x[iatom][2] + h[2]*zbox;
}
}
// -----------------------------------------------------------------
// other methods
// -----------------------------------------------------------------
/** Return lammps pointer -- only as a last resort! */
LAMMPS_NS::LAMMPS * LammpsInterface::get_lammps_ptr() { return lammps_; }
}

View File

@ -1,295 +0,0 @@
#ifndef LAMMPS_INTERFACE_H
#define LAMMPS_INTERFACE_H
#include <iostream>
#include <stdlib.h>
#include "mpi.h"
#include "../../src/lammps.h"
#include "../../src/lmptype.h"
#include "ATC_TypeDefs.h"
// Forward class declarations for LAMMPS_NS namespace
namespace LAMMPS_NS {
class LAMMPS;
class NeighList;
class Compute;
}
namespace ATC {
/**
* @class LammpsInterface
* @brief Singleton class that handles all interfacing with the lammps code
*/
class LammpsInterface {
public:
// Enumeration for lattice type. this MUST match the enum in src/lattice.cpp
enum LatticeType {
NONE=0,
SC,
BCC,
FCC,
HCP,
DIAMOND,
SQ,
SQ2,
HEX,
CUSTOM
};
// Enumeration for units type. this is internal to ATC
enum UnitsType {
UNKNOWN=0,
LJ,
REAL,
METAL
};
/** Static instance of this class */
static LammpsInterface * instance();
/** Set lammps pointer */
void set_lammps(LAMMPS_NS::LAMMPS * lammps)
{
lammps_ = lammps;
MPI_Comm_rank(lammps_->world, & commRank_);
}
/** \name Methods that interface with Lammps base class */
/*@{*/
MPI_Comm world();
void allsum(double * send_buf, double * rec_buf, int count = 1)
{
MPI_Allreduce(send_buf, rec_buf, count, MPI_DOUBLE, MPI_SUM,
lammps_->world);
MPI_Barrier(lammps_->world);
}
void int_allsum(int * send_buf, int * rec_buf, int count = 1)
{
MPI_Allreduce(send_buf, rec_buf, count, MPI_INT, MPI_SUM,
lammps_->world);
MPI_Barrier(lammps_->world);
}
void allmax(double * send_buf, double * rec_buf, int count = 1)
{
MPI_Allreduce(send_buf, rec_buf, count, MPI_DOUBLE, MPI_MAX,
lammps_->world);
MPI_Barrier(lammps_->world);
}
void int_allmax(int * send_buf, int * rec_buf, int count = 1)
{
MPI_Allreduce(send_buf, rec_buf, count, MPI_INT, MPI_MAX,
lammps_->world);
MPI_Barrier(lammps_->world);
}
void logical_or(int * send_buf, int * rec_buf, int count = 1)
{
MPI_Allreduce(send_buf, rec_buf, count, MPI_INT, MPI_LOR,
lammps_->world);
MPI_Barrier(lammps_->world);
}
int comm_rank(void) { return commRank_;}
/*@}*/
/** \name Methods that interface with Atom class */
/*@{*/
int nlocal();
int nghost();
int nmax();
double natoms();
double ** xatom();
int ntypes();
const double ** xatom() const;
double ** vatom();
double ** fatom();
int * atom_mask();
int * atom_type();
int * atom_tag();
double * atom_mass();
double atom_mass(int iType);
double * atom_rmass();
double * atom_charge();
void unwrap_coordinates(int iatom, double* xatom);
/*@}*/
/** \name Methods that interface with Domain class */
/*@{*/
int dimension();
int nregion();
void get_box_bounds(double & boxxlo, double & boxxhi,
double & boxylo, double & boxyhi,
double & boxzlo, double &boxzhi);
int xperiodic();
int yperiodic();
int zperiodic();
int nperiodic();
void get_box_periodicity(int & xperiodic,
int & yperiodic,
int & zperiodic);
int get_region_id(const char * regionName);
double domain_xprd();
double domain_yprd();
double domain_zprd();
double domain_xy();
double domain_xz();
double domain_yz();
int domain_triclinic();
/*@}*/
/** \name Methods that interface with Update class */
UnitsType units_style();
/*@}*/
/** \name Methods that interface with Lattice class */
/*@{*/
double xlattice();
double ylattice();
double zlattice();
LatticeType lattice_style();
int get_n_basis();
void get_basis(double **basis);
void get_unit_cell(double *a1, double *a2, double *a3);
/** these functions are more than just simple pass throughs */
int num_atoms_per_cell(void);
double volume_per_atom(void);
void get_lattice(MATRIX &N, MATRIX &B);
/*@}*/
/** \name Methods that interface with Force class */
/*@{*/
double boltz();
double mvv2e();
double ftm2v();
double nktv2p();
double qqr2e();
double qe2f();
double dielectric();
double qqrd2e();
double pair_force(int i, int j, double rsq, double& fmag_over_rmag);
double pair_cutoff();
int single_enable();
/** these functions are more than just simple pass throughs */
/** Boltzmann's constant in M,L,T,t units */
double kBoltzmann(void);
/** Dulong-Petit heat capacity per volume in M,L,T,t units */
double heat_capacity(void);
/** mass per volume in reference configuraturation in M,L units */
double mass_density(void);
/** ratio of permittivity of free space over elemental charge in V, L units */
double epsilon0(void) {return 0.00552635; } // [V A]^-1
// NOTE this won't work for LJ/SI/CGS units where [L] != A
/*@}*/
/** \name Methods that interface with Group class */
/*@{*/
int ngroup();
int group_bit(int iGroup);
int find_group(const char * c);
int group_inverse_mask(int iGroup);
char * group_name(int iGroup);
void group_bounds(int iGroup, double * b);
/*@}*/
/** \name Methods that interface with Memory class */
/*@{*/
double * create_1d_double_array(int nlo, int nhi, const char *name);
void destroy_1d_double_array(double * d, int i);
double ** create_2d_double_array(int n1, int n2, const char *name);
void destroy_2d_double_array(double **d);
double **grow_2d_double_array(double **array, int n1, int n2, const char *name);
int ** create_2d_int_array(int n1, int n2, const char *name);
void destroy_2d_int_array(int **i);
int ** grow_2d_int_array(int **array, int n1, int n2, const char *name);
/*@}*/
/** \name Methods that interface with Update class */
/*@{*/
double dt();
int ntimestep();
int nsteps();
/*@}*/
/** \name Methods that interface with neighbor list */
/*@{*/
void init_list(int id, LAMMPS_NS::NeighList *ptr);
int neighbor_list_inum();
int * neighbor_list_numneigh();
int * neighbor_list_ilist();
int ** neighbor_list_firstneigh();
int neighbor_ago();
/*@}*/
/** \name Methods that interface with Region class */
/*@{*/
char * region_name(int iRegion);
char * region_style(int iRegion);
double region_xlo(int iRegion);
double region_xhi(int iRegion);
double region_ylo(int iRegion);
double region_yhi(int iRegion);
double region_zlo(int iRegion);
double region_zhi(int iRegion);
double region_xscale(int iRegion);
double region_yscale(int iRegion);
double region_zscale(int iRegion);
int region_match(int iRegion, double x, double y, double z);
/*@}*/
/** \name Methods that interface with compute class */
enum COMPUTE_INVOKED
{DUMMY0,INVOKED_SCALAR,INVOKED_VECTOR,DUMMMY3,INVOKED_PERATOM};
int find_compute(const char* tag);
LAMMPS_NS::Compute* get_compute(const char* tag);
double* compute_scalar_data(const char* tag);
double** compute_vector_data(const char* tag);
int compute_ncols(const char* tag);
/*@}*/
/** \name Methods that interface with compute pe/atom class */
/*@{*/
int atomPE_create(void);
void atomPE_init(void);
void atomPE_addstep(LAMMPS_NS::bigint step);
double * atomPE_compute(void);
/*@}*/
/** Return lammps pointer -- only as a last resort! */
LAMMPS_NS::LAMMPS * get_lammps_ptr();
protected:
LAMMPS_NS::LAMMPS * lammps_;
/** access to neighbor list */
LAMMPS_NS::NeighList *list_;
/** constructor */
LammpsInterface();
/** comm rank */
int commRank_;
/** compute pe/atom */
LAMMPS_NS::Compute * atomPE_;
private:
static LammpsInterface * myInstance_;
};
} // end namespace ATC
#endif

5
lib/atc/Makefile.lammps Normal file
View File

@ -0,0 +1,5 @@
# Settings that the LAMMPS build will import when this package library is used
user-atc_SYSINC =
user-atc_SYSLIB = -lblas -llapack
user-atc_SYSPATH =

29
lib/atc/Makefile.mpic++ Normal file
View File

@ -0,0 +1,29 @@
SHELL = /bin/sh
# ------ FILES ------
SRC = $(wildcard *.cpp)
INC = $(wildcard *.h)
# ------ DEFINITIONS ------
LIB = libatc.a
OBJ = $(SRC:.cpp=.o)
# ------ SETTINGS ------
CC = mpic++
CCFLAGS = -O -g -I../../src -fPIC -DMPICH_IGNORE_CXX_SEEK
ARCHIVE = ar
ARCHFLAG = -rc
DEPFLAGS = -M
LINK = ${CC}
LINKFLAGS = -O
# ------ MAKE PROCEDURE ------
lib: $(OBJ)
$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
@cp Makefile.lammps.installed Makefile.lammps
# ------ COMPILE RULES ------
%.o:%.cpp
$(CC) $(CCFLAGS) -c $<
%.d:%.cpp
$(CC) $(CCFLAGS) $(DEPFLAGS) $< > $@
# ------ DEPENDENCIES ------
DEPENDS = $(OBJ:.o=.d)
# ------ CLEAN ------
clean:
@rm *.o *.d $(LIB)

View File

@ -1,349 +0,0 @@
#include "Material.h"
#include "ATC_Transfer.h"
#include "LammpsInterface.h"
#include "ElectronHeatCapacity.h"
#include "ElectronHeatFlux.h"
#include "ElectronPhononExchange.h"
namespace ATC {
using namespace ATC_STRING;
Material::Material()
: rhoCp_(0),
rho_(0),
heatCapacity_(0),
massDensity_(0),
chargeDensity_(0),
electronHeatCapacity_(NULL),
heatConductivity_(0),
electronHeatFlux_(NULL),
stress_(NULL),
electronPhononExchange_(NULL),
permittivity_(1.),
electronEquilibriumDensity_(0),
electronRecombinationInvTau_(0),
donorConcentration_(0)
{
}
//--------------------------------------------------------------
// Constructor (parser)
//--------------------------------------------------------------
// Example:
// material Cu
// heat_capacity constant
// capacity 1.0
// end
// heat_flux linear
// conductivity 1.0
// end
// electron_heat_flux linear
// conductivity 1.0
// end
// electron_heat_capacity linear
// capacity 1.0
// end
// electron_phonon_exchange linear
// coefficient 0.1
// end
// end
Material::Material(string & tag, fstream &fileId)
: tag_(tag),
rhoCp_(0),
rho_(0),
heatCapacity_(0),
massDensity_(0),
chargeDensity_(0),
electronHeatCapacity_(NULL),
heatConductivity_(0),
electronHeatFlux_(NULL),
stress_(NULL),
electronPhononExchange_(NULL),
permittivity_(1.),
electronEquilibriumDensity_(0),
electronRecombinationInvTau_(0),
donorConcentration_(0)
{
linearFlux_.reset(NUM_FIELDS);
linearFlux_ = false;
linearSource_.reset(NUM_FIELDS);
linearSource_ = true;
constantDensity_.reset(NUM_FIELDS);
constantDensity_ = false;
// NOTE these next two rely on many assumptions
rhoCp_ = ATC::LammpsInterface::instance()->heat_capacity();
parameters_["heat_capacity"] = rhoCp_;
heatCapacity_ = rhoCp_;
registry_.insert("heat_capacity");
constantDensity_(TEMPERATURE) = true;
rho_ = ATC::LammpsInterface::instance()->mass_density();
parameters_["mass_density"] = rho_;
massDensity_ = rho_;
registry_.insert("mass_density");
constantDensity_(DISPLACEMENT) = true;
constantDensity_(VELOCITY) = true;
vector<string> line;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line.size() == 1) {
if (line[0] == "end") {
return;
}
}
if (line[0] == "heat_capacity") { // over-ride default
registry_. insert("heat_capacity");
registry_. insert("thermal_energy");
if (line[1] == "constant") {
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") break;
double value = str2dbl(line[1]);
if (line[0] == "capacity") {
heatCapacity_ = value;
parameters_["heat_capacity"] = heatCapacity_;
}
}
}
}
else if (line[0] == "heat_flux") {
registry_. insert("heat_flux");
if (line[1] == "linear") {
linearFlux_(TEMPERATURE) = true;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") break;
double value = str2dbl(line[1]);
if (line[0] == "conductivity") {
heatConductivity_ = value;
}
}
}
}
else if (line[0] == "electron_heat_flux") {
registry_. insert("electron_heat_flux");
if (line[1] == "linear") {
linearFlux_(ELECTRON_TEMPERATURE) = true;
electronHeatFlux_ = new ElectronHeatFluxLinear(fileId, parameters_);
}
else if (line[1] == "power_law") {
electronHeatFlux_ = new ElectronHeatFluxPowerLaw(fileId, parameters_);
}
}
else if (line[0] == "electron_heat_capacity") {
registry_. insert("electron_heat_capacity");
registry_. insert("electron_thermal_energy");
if (line[1] == "constant") {
constantDensity_(ELECTRON_TEMPERATURE) = true;
electronHeatCapacity_ = new ElectronHeatCapacityConstant(fileId,
parameters_);
}
else if (line[1] == "linear") {
electronHeatCapacity_ = new ElectronHeatCapacityLinear(fileId,
parameters_);
}
}
else if (line[0] == "electron_phonon_exchange") {
registry_. insert("electron_phonon_exchange");
if (line[1] == "linear") {
electronPhononExchange_ = new ElectronPhononExchangeLinear(fileId,
parameters_);
}
else if (line[1] == "power_law") {
linearSource_(TEMPERATURE) = false;
linearSource_(ELECTRON_TEMPERATURE) = false;
electronPhononExchange_ = new ElectronPhononExchangePowerLaw(fileId,
parameters_);
}
}
else if (line[0] == "mass_density") { // over-ride default
registry_. insert("mass_density");
registry_. insert("kinetic_energy");
if (line[1] == "constant") {
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") break;
double value = str2dbl(line[1]);
if (line[0] == "density") {
massDensity_ = value;
parameters_["mass_density"] = massDensity_;
}
}
}
}
else if (line[0] == "electron_recombination") {
registry_. insert("electron_recombination");
if (line[1] == "linear") {
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") break;
double value = str2dbl(line[1]);
if (line[0] == "inv_relaxation_time") {
electronRecombinationInvTau_ = value;
parameters_["inv_relaxation_time"] = electronRecombinationInvTau_;
}
else if (line[0] == "equilibrium_carrier_density") {
electronEquilibriumDensity_ = value;
parameters_["equilibrium_carrier_density"]
= electronEquilibriumDensity_;
}
}
}
}
else if (line[0] == "charge_density") {
registry_. insert("charge_density");
if (line[1] == "constant") {
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0) continue;
if (line[0] == "end") break;
double value = str2dbl(line[1]);
if (line[0] == "donor_concentration") {
donorConcentration_ = value;
parameters_["donor_concentration"] = donorConcentration_;
}
else if (line[0] == "density") {
chargeDensity_ = value;
parameters_["charge_density"] = chargeDensity_;
}
}
}
}
else {
throw ATC_Error(0, "unrecognized material function: "+line[0]);
}
}
}
//---------------------------------------------------------------------
void Material::heat_capacity(
const FIELDS & fields,
FIELD & capacity)
{
const FIELD & T = (fields.find(TEMPERATURE))->second;
int nNodes = T.nRows();
capacity.reset(nNodes,1);
capacity = heatCapacity_;
};
//---------------------------------------------------------------------
void Material::thermal_energy(
const FIELDS &fields,
FIELD &energy)
{
const FIELD & T = (fields.find(TEMPERATURE))->second;
energy = heatCapacity_ * T;
};
//---------------------------------------------------------------------
void Material::electron_heat_capacity(
const FIELDS & fields,
FIELD & capacity)
{
electronHeatCapacity_->electron_heat_capacity(fields,capacity);
};
//---------------------------------------------------------------------
void Material::electron_thermal_energy(
const FIELDS &fields,
FIELD &energy)
{
electronHeatCapacity_->electron_thermal_energy(fields,energy);
};
//---------------------------------------------------------------------
void Material::mass_density(
const FIELDS &fields,
FIELD &density)
{
int nNodes = 0;
FIELDS::const_iterator field = fields.find(MASS_DENSITY);
if (field != fields.end()) {
const FIELD & d = field->second;
nNodes = d.nRows();
}
else {
FIELDS::const_iterator field = fields.find(VELOCITY);
if (field != fields.end()) {
const FIELD & v = field->second;
nNodes = v.nRows();
}
}
density.reset(nNodes,1);
density = massDensity_;
};
//---------------------------------------------------------------------
void Material::kinetic_energy(
const FIELDS &fields,
FIELD &energy)
{
FIELDS::const_iterator field = fields.find(VELOCITY);
if (field != fields.end()) {
const FIELD & v = field->second;
energy = 0.5*massDensity_*v;
energy *= v;
}
else {
energy = 0.;
}
};
//---------------------------------------------------------------------
void Material::heat_flux(
const FIELDS & fields,
const GRAD_FIELDS & gradFields,
GRAD_FIELD & flux)
{
const GRAD_FIELD & dT = (gradFields.find(TEMPERATURE))->second;
flux.push_back(-heatConductivity_* dT[0]);
flux.push_back(-heatConductivity_* dT[1]);
flux.push_back(-heatConductivity_* dT[2]);
}
//---------------------------------------------------------------------
void Material::electron_heat_flux(
const FIELDS & fields,
const GRAD_FIELDS & gradFields,
GRAD_FIELD & flux)
{
electronHeatFlux_->electron_heat_flux(fields,gradFields,flux);
}
//---------------------------------------------------------------------
void Material::electron_phonon_exchange(
const FIELDS & fields,
FIELD & flux)
{
electronPhononExchange_->electron_phonon_exchange(fields,flux);
}
//---------------------------------------------------------------------
void Material::electron_recombination(
const FIELDS &fields,
const GRAD_FIELDS &gradFields,
FIELD & flux)
{
// 1/tau (n - n0)
const FIELD & n = (fields.find(ELECTRON_DENSITY))->second;
flux = n;
flux -= electronEquilibriumDensity_;
flux *= -electronRecombinationInvTau_;
}
//---------------------------------------------------------------------
void Material::charge_density(
const FIELDS &fields,
const GRAD_FIELDS &gradFields,
FIELD & flux)
{
// Extrinsic/electron charge density
FIELDS::const_iterator field = fields.find(ELECTRON_DENSITY);
if (field != fields.end()) {
// (n - nD) , where n > 0
const FIELD & n = field->second;
flux = n;
flux -= donorConcentration_;// NOTE uniform
flux *= -1.0; // account for negative charge
}
};
} // end namespace

View File

@ -1,185 +0,0 @@
#ifndef MATERIAL_H
#define MATERIAL_H
#include <map>
#include <set>
#include <string>
#include "MatrixLibrary.h"
#include "ATC_TypeDefs.h"
#include "ATC_Error.h"
#include "LammpsInterface.h"
namespace ATC
{
class ATC_Transfer;
class Stress;
class ElectronHeatCapacity;
class ElectronHeatFlux;
class ElectronFlux;
class ElectronPhononExchange;
class Material
{
public:
Material();
virtual ~Material() {};
/** this constructor parses material file */
Material(string & tag, fstream & fileId);
/** return label */
string label(void) {return tag_;}
/** check material has required interfaces */
bool check_registry(const set<string> functionList) const
{
set<string>::const_iterator itr;
for (itr=functionList.begin(); itr!=functionList.end(); itr++) {
if (registry_.find(*itr) == registry_.end()) return false;
}
return true;
}
/** access to material parameters */
bool get_parameter(const string name, double & value) const
{
map<string,double>::const_iterator iter = parameters_.find(name);
if ( iter == parameters_.end()) {
value = 0.0;
return false;
}
value = iter->second;
return true;
}
/** true if rhs flux is linear (per field) */
bool linear_flux(FieldName name) {
return linearFlux_(name);
};
/** true if rhs source is linear (per field) */
bool linear_source(FieldName name) {
return linearSource_(name);
};
/** true if lhs density is constant (per field) */
bool constant_density(FieldName name) {
return constantDensity_(name);
};
/** each of these is a field function computed at a set of points */
/** if there is only one function it is in the base class
** otherwise, a subsidary class is setup */
/* -----------------------------------------------------------------*/
/** densitities */
/* -----------------------------------------------------------------*/
/** thermal energy */
void thermal_energy(const FIELDS & fields,
FIELD & energy);
/** heat capacity */
void heat_capacity(const FIELDS & fields,
FIELD & capacity);
/** thermal energy */
void electron_thermal_energy(const FIELDS & fields,
FIELD & energy);
/** electron heat capacity */
void electron_heat_capacity(const FIELDS &fields,
FIELD &capacity);
/** kinetic energy */
void kinetic_energy(const FIELDS & fields,
FIELD & energy);
/** mass density */
void mass_density(const FIELDS &fields,
FIELD &density);
/** elastic energy */
void elastic_energy(const FIELDS & fields,
const GRAD_FIELDS & gradFields,
FIELD & energy);
/* -----------------------------------------------------------------*/
/** fluxes */
/* -----------------------------------------------------------------*/
/** heat_flux */
void heat_flux(const FIELDS & fields,
const GRAD_FIELDS & gradFields,
GRAD_FIELD & heatFlux);
/** electron conduction flux */
void electron_heat_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux);
/** stress */
void stress(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &stress);
/** computes electron flux */
void electron_flux(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux);
/** computes electric displacement */
void electric_displacement(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux);
/** computes electric field */
void electric_field(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
GRAD_FIELD &flux);
/* -----------------------------------------------------------------*/
/** sources */
/* -----------------------------------------------------------------*/
/** electron-phonon exchange flux */
void electron_phonon_exchange(const FIELDS &fields,
FIELD &flux);
/** computes net generation */
virtual void electron_recombination(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
FIELD &flux);
/** computes drift diffusion charge density */
virtual void charge_density(const FIELDS &fields,
const GRAD_FIELDS &gradFields,
FIELD &flux);
protected:
/** material's label */
string tag_;
/** dictionary of material parameters */
map<string,double> parameters_;
/** dictionary of instantiated functions */
set<string> registry_;
/** per eqn flag of constant density */
Array<bool> constantDensity_;
/** per eqn flag of linearity/nonlinearity */
Array<bool> linearFlux_, linearSource_;
/** default heat capacity */
double rhoCp_;
/** default mass density */
double rho_;
/** heat capacity */
double heatCapacity_;
/** electron heat capacity */
ElectronHeatCapacity * electronHeatCapacity_;
/** mass density */
double massDensity_;
/** charge density */
double chargeDensity_;
/** thermal conductivity */
double heatConductivity_;
/** electron heat flux */
ElectronHeatFlux * electronHeatFlux_;
/** stress */
Stress * stress_;
/** electron-phonon exchange */
ElectronPhononExchange * electronPhononExchange_;
/** electron heat flux */
ElectronFlux * electronFlux_;
/** electric permittivity */
double permittivity_;
/** equilibrium carrier density */
double electronEquilibriumDensity_;
/** relaxation time */
double electronRecombinationInvTau_;
/** uniform donor concentration */
double donorConcentration_; // NOTE only for uniform
};
}
#endif // Material.h

View File

@ -1,146 +0,0 @@
#include "DenseMatrix.h"
#include "Solver.h"
//-----------------------------------------------------------------------------
//* performs a matrix-matrix multiply with optional transposes BLAS version
// C = b*C + a*A*B
//-----------------------------------------------------------------------------
void MultAB(const MATRIX &A, const MATRIX &B, DENS_MAT &C,
const bool At, const bool Bt, double a, double b)
{
static char t[2] = {'N','T'};
char *ta=t+At, *tb=t+Bt;
int sA[2] = {A.nRows(), A.nCols()}; // sizes of A
int sB[2] = {B.nRows(), B.nCols()}; // sizes of B
GCK(A, B, sA[!At]!=sB[Bt], "MultAB<double>: matrix-matrix multiply");
if (!C.is_size(sA[At],sB[!Bt]))
{
C.resize(sA[At],sB[!Bt]);
if (b != 0.0) C.zero();
}
// get pointers to the matrix sizes needed by BLAS
int *M = sA+At; // # of rows in op[A] (op[A] = A' if At='T' else A)
int *N = sB+!Bt; // # of cols in op[B]
int *K = sA+!At; // # of cols in op[A] or # of rows in op[B]
double *pa=A.get_ptr(), *pb=B.get_ptr(), *pc=C.get_ptr();
#ifdef COL_STORAGE
dgemm_(ta, tb, M, N, K, &a, pa, sA, pb, sB, &b, pc, M);
#else
dgemm_(tb, ta, N, M, K, &a, pb, sB+1, pa, sA+1, &b, pc, N);
#endif
}
//-----------------------------------------------------------------------------
//* returns the inverse of a double precision matrix
//-----------------------------------------------------------------------------
DenseMatrix<double> inv(const MATRIX& A)
{
SQCK(A, "DenseMatrix::inv(), matrix not square"); // check matrix is square
DENS_MAT invA(A); // Make copy of A to invert
// setup for call to BLAS
int m, info, lwork=-1;
m = invA.nRows();
int *ipiv = new int[m<<1]; // need 2m storage
int *iwork=ipiv+m;
dgetrf_(&m,&m,invA.get_ptr(),&m,ipiv,&info); // compute LU factorization
GCK(A,A,info<0,"DenseMatrix::inv() dgetrf error: Argument had bad value.");
GCK(A,A,info>0,"DenseMatrix::inv() dgetrf error: Matrix not invertable.");
// LU factorization succeeded
// Compute 1-norm of original matrix for use with dgecon
char norm = '1'; // Use 1-norm
double rcond, anorm, *workc = new double[4*m];
anorm = dlange_(&norm,&m,&m,A.get_ptr(),&m,workc);
// Condition number estimation (warn if bad)
dgecon_(&norm,&m,invA.get_ptr(),&m,&anorm,&rcond,workc,iwork,&info);
GCK(A,A,info<0, "DenseMatrix::inv(): dgecon error: Argument had bad value.");
GCK(A,A,rcond<1e-14,"DenseMatrix::inv(): Matrix nearly singular, RCOND<e-14");
// Now determine optimal work size for computation of matrix inverse
double work_dummy[2] = {0.0,0.0};
dgetri_(&m, invA.get_ptr(), &m, ipiv, work_dummy, &lwork, &info);
GCK(A,A,info<0,"DenseMatrix::inv() dgetri error: Argument had bad value.");
GCK(A,A,info>0,"DenseMatrix::inv() dgetri error: Matrix not invertable.");
// Work size query succeded
lwork = (int)work_dummy[0];
double *work = new double[lwork]; // Allocate vector of appropriate size
// Compute and store matrix inverse
dgetri_(&m,invA.get_ptr(),&m,ipiv,work,&lwork,&info);
GCK(A,A,info<0,"DenseMatrix::inv() dgetri error: Argument had bad value.");
GCK(A,A,info>0,"DenseMatrix::inv() dgetri error: Matrix not invertable.");
// Clean-up
delete [] ipiv;
delete [] workc;
delete [] work;
return invA;
}
//-----------------------------------------------------------------------------
//* computes the determinant of a square matrix by LU decomposition (if n>3)
//-----------------------------------------------------------------------------
double det(const MATRIX& A)
{
static const double sign[2] = {1.0, -1.0};
SQCK(A, "Matrix::det(), matrix not square"); // check matrix is square
int m = A.nRows();
switch (m) // explicit determinant for small matrix sizes
{
case 1: return A(0,0);
case 2: return A(0,0)*A(1,1)-A(0,1)*A(1,0);
case 3:
return A(0,0)*(A(1,1)*A(2,2)-A(1,2)*A(2,1))
+ A(0,1)*(A(1,2)*A(2,0)-A(1,0)*A(2,2))
+ A(0,2)*(A(1,0)*A(2,1)-A(1,1)*A(2,0));
default: break;
}
// First compute LU factorization
int info, *ipiv = new int[m];
double det = 1.0;
DENS_MAT PLUA(A);
dgetrf_(&m,&m,PLUA.get_ptr(),&m,ipiv,&info);
GCK(A,A,info>0,"Matrix::det() dgetrf error: Bad argument value.");
if (!info) // matrix is non-singular
{
// Compute det(A) = det(P)*det(L)*det(U) = +/-1 * det(U)
int i, OddNumPivots;
det = PLUA(0,0);
OddNumPivots = ipiv[0]!=(1);
for(i=1; i<m; i++)
{
det *= PLUA(i,i);
OddNumPivots += (ipiv[i]!=(i+1)); // # pivots even/odd
}
det *= sign[OddNumPivots&1];
}
delete [] ipiv; // Clean-up
return det;
}
//-----------------------------------------------------------------------------
//* Returns the maximum eigenvalue of a matrix.
//-----------------------------------------------------------------------------
double max_eigenvalue(const Matrix<double>& A)
{
GCK(A,A,!is_size(3,3), "max_eigenvalue only implimented for 3x3");
const double c0 = det(A);
const double c1 = A(1,0)*A(0,1) + A(2,0)*A(0,2) + A(1,2)*A(2,1)
- A(0,0)*A(1,1) - A(0,0)*A(2,2) - A(1,1)*A(2,2);
const double c2 = trace(A);
double c[4] = {c0, c1, c2, -1.0}, x[3];
int num_roots = ATC::solve_cubic(c, x);
double max_root = 0.0;
for (int i=0; i<num_roots; i++) max_root = std::max(x[i], max_root);
return max_root;
}

View File

@ -1,664 +0,0 @@
#ifndef MATRIX_H
#define MATRIX_H
#include "MatrixDef.h"
/*******************************************************************************
* abstract class Matrix - base class for linear algebra subsystem
*******************************************************************************/
template<typename T>
class Matrix
{
protected:
Matrix(const Matrix &c);
public:
Matrix() {}
virtual ~Matrix() {}
//* stream output functions
void print(ostream &o) const { o << tostring(); }
void print(ostream &o, const string &name) const;
friend ostream& operator<<(ostream &o, const Matrix<T> &m){m.print(o); return o;}
void print() const;
virtual void print(const string &name) const;
virtual string tostring() const;
// element by element operations
DenseMatrix<T> operator/(const Matrix<T>& B) const;
DenseMatrix<T> pow(int n) const;
DenseMatrix<T> pow(double n) const;
// functions that return a copy
DenseMatrix<T> transpose() const;
// matrix to scalar functions
T sum() const;
T stdev() const;
T max() const;
T min() const;
T maxabs() const;
T minabs() const;
T norm() const;
T mean() const;
T dot(const Matrix<T> &r) const;
T trace() const;
// row and column operations
T row_sum (INDEX i=0) const { return row(*this,i).sum(); }
T row_mean (INDEX i=0) const { return row(*this,i).mean(); }
T row_norm (INDEX i=0) const { return row(*this,i).norm(); }
T row_stdev(INDEX i=0) const { return row(*this,i).stdev(); }
T col_sum (INDEX i=0) const { return column(*this,i).sum(); }
T col_mean (INDEX i=0) const { return column(*this,i).mean(); }
T col_norm (INDEX i=0) const { return column(*this,i).norm(); }
T col_stdev(INDEX i=0) const { return column(*this,i).stdev(); }
// pure virtual functions (required to implement these) ---------------------
//* reference index operator
virtual T& operator()(INDEX i, INDEX j)=0;
//* value index operator
virtual T operator()(INDEX i, INDEX j)const=0;
//* value flat index operator
virtual T& operator [](INDEX i)=0;
//* reference flat index operator
virtual T operator [](INDEX i) const=0;
//* returns the # of rows
virtual INDEX nRows() const=0;
//* returns the # of columns
virtual INDEX nCols() const=0;
//* returns a pointer to the data (dangerous)
virtual T * get_ptr() const=0;
//* resizes the matrix, copy what fits default to OFF
virtual void resize(INDEX nRows, INDEX nCols=1, bool copy=false)=0;
//* resizes the matrix, zero it out default to ON
virtual void reset(INDEX nRows, INDEX nCols=1, bool zero=true)=0;
//* resizes and copies data
virtual void copy(const T * ptr, INDEX nRows, INDEX nCols=1)=0;
//* create restart file
virtual void write_restart(FILE *f) const=0;
//* writes a matlab command to recreate this in a variable named s
virtual void matlab(ostream &o, const string &s="M") const;
// output to matlab, with variable name s
void matlab(const string &s="M") const;
Matrix<T>& operator+=(const Matrix &r);
Matrix<T>& operator-=(const Matrix &r);
//* NOTE these two functions are scaling operations not A.B
Matrix<T>& operator*=(const Matrix<T>& R);
Matrix<T>& operator/=(const Matrix<T>& R);
Matrix<T>& operator+=(const T v);
Matrix<T>& operator-=(const T v);
Matrix<T>& operator*=(const T v);
Matrix<T>& operator/=(T v);
Matrix<T>& operator=(const T &v);
Matrix<T>& operator=(const Matrix<T> &c);
virtual void set_all_elements_to(const T &v);
//* adds a matrix scaled by factor s to this one.
void add_scaled(const Matrix<T> &A, const T& s);
//* sets all elements to zero
Matrix& zero();
//* returns the total number of elements
virtual INDEX size() const;
//* returns true if (i,j) is within the range of the matrix
bool in_range(INDEX i, INDEX j) const;
//* returns true if the matrix size is rs x cs
bool is_size(INDEX rs, INDEX cs) const;
//* returns true if the matrix is square and not empty
bool is_square() const;
//* returns true if Matrix, m, is the same size as this
bool same_size(const Matrix &m) const;
//* returns true if Matrix a and Matrix b are the same size
static bool same_size(const Matrix<T> &a, const Matrix<T> &b);
//* checks if memory is contiguous, only can be false for clone vector
virtual bool memory_contiguous() const { return true; }
protected:
virtual void _set_equal(const Matrix<T> &r);
};
//* Matrix operations
//@{
//* Sets C as b*C + a*A[tranpose?]*B[transpose?]
template<typename T>
void MultAB(const Matrix<T> &A, const Matrix<T> &B, DenseMatrix<T> &C,
bool At=0, bool Bt=0, T a=1, T b=0);
//* performs a matrix-vector multiply
template<typename T>
void MultMv(const Matrix<T> &A, const Vector<T> &v, DenseVector<T> &c,
const bool At, T a, T b);
// returns the inverse of a double precision matrix
DenseMatrix<double> inv(const Matrix<double>& A);
//* returns the trace of a matrix
template<typename T>
T trace(const Matrix<T>& A) { return A.trace(); }
//* computes the determinant of a square matrix
double det(const Matrix<double>& A);
//* Returns the maximum eigenvalue of a matrix.
double max_eigenvalue(const Matrix<double>& A);
//@}
//-----------------------------------------------------------------------------
// computes the sum of the difference squared of each element.
//-----------------------------------------------------------------------------
template<typename T>
double sum_difference_squared(const Matrix<T>& A, const Matrix<T> &B)
{
SSCK(A, B, "sum_difference_squared");
double v=0.0;
for (unsigned i=0; i<A.size(); i++) {
double d = A[i]-B[i];
v += d*d;
}
return v;
}
//-----------------------------------------------------------------------------
//* Operator for Matrix-matrix product
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> operator*(const Matrix<T> &A, const Matrix<T> &B)
{
DenseMatrix<T> C(0,0,false);
MultAB(A,B,C);
return C;
}
//-----------------------------------------------------------------------------
//* Multiply a Matrix by a scalar
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> operator*(const Matrix<T> &M, const T s)
{
DenseMatrix<T> R(M);
return R*=s;
}
//-----------------------------------------------------------------------------
//* Multiply a Matrix by a scalar
template<typename T>
DenseMatrix<T> operator*(const T s, const Matrix<T> &M)
{
DenseMatrix<T> R(M);
return R*=s;
}
//-----------------------------------------------------------------------------
//* inverse scaling operator - must always create memory
template<typename T>
DenseMatrix<T> operator/(const Matrix<T> &M, const T s)
{
DenseMatrix<T> R(M);
return R*=(1.0/s); // for integer types this may be worthless
}
//-----------------------------------------------------------------------------
//* Operator for Matrix-matrix sum
template<typename T>
DenseMatrix<T> operator+(const Matrix<T> &A, const Matrix<T> &B)
{
DenseMatrix<T> C(A);
return C+=B;
}
//-----------------------------------------------------------------------------
//* Operator for Matrix-matrix subtraction
template<typename T>
DenseMatrix<T> operator-(const Matrix<T> &A, const Matrix<T> &B)
{
DenseMatrix<T> C(A);
return C-=B;
}
/******************************************************************************
* Template definitions for class Matrix
******************************************************************************/
//-----------------------------------------------------------------------------
//* performs a matrix-matrix multiply with general type implementation
template<typename T>
void MultAB(const Matrix<T> &A, const Matrix<T> &B, DenseMatrix<T> &C,
const bool At, const bool Bt, T a, T b)
{
const INDEX sA[2] = {A.nRows(), A.nCols()}; // m is sA[At] k is sA[!At]
const INDEX sB[2] = {B.nRows(), B.nCols()}; // k is sB[Bt] n is sB[!Bt]
const INDEX M=sA[At], K=sB[Bt], N=sB[!Bt];
GCK(A, B, sA[!At]!=K, "MultAB<T> shared index not equal size");
if (!C.is_size(M,N))
{
C.resize(M,N); // set size of C
C.zero();
}
else C *= b;
for (INDEX p=0; p<M; p++)
for (INDEX q=0; q<N; q++)
for (INDEX r=0; r<K; r++)
C(p,q) += A(p*!At+r*At, p*At+r*!At) * B(r*!Bt+q*Bt, r*Bt+q*!Bt);
}
//-----------------------------------------------------------------------------
//* output operator
template<typename T>
string Matrix<T>::tostring() const
{
string s;
for (INDEX i=0; i<nRows(); i++)
{
if (i) s += '\n';
for (INDEX j=0; j<nCols(); j++)
{
if (j) s+= '\t';
s += ATC_STRING::tostring(MIDX(i,j),5)+" ";
}
}
return s;
}
//-----------------------------------------------------------------------------
//* output operator that wraps the matrix in a nice labeled box
template<typename T>
void Matrix<T>::print(ostream &o, const string &name) const
{
o << "------- Begin "<<name<<" -----------------\n";
this->print(o);
o << "\n------- End "<<name<<" -------------------\n";
}
//-----------------------------------------------------------------------------
//* print operator, use cout by default
template<typename T>
void Matrix<T>::print() const
{
print(cout);
}
//-----------------------------------------------------------------------------
//* named print operator, use cout by default
template<typename T>
void Matrix<T>::print(const string &name) const
{
print(cout, name);
}
//-----------------------------------------------------------------------------
//* element by element division
template<typename T>
DenseMatrix<T> Matrix<T>::operator/ (const Matrix<T>& B) const
{
SSCK(*this, B, "Matrix<T>::Operator/");
DenseMatrix<T> R(*this);
R /= B;
return R;
}
//-----------------------------------------------------------------------------
//* element-wise raise to a power
template<typename T>
DenseMatrix<T> Matrix<T>::pow(int n) const
{
DenseMatrix<T> R(*this);
FORi
{
double val = R[i];
for (int k=1; k<n; k++) val *= R[i];
for (int k=n; k<1; k++) val /= R[i];
R[i] = val;
}
return R;
}
//-----------------------------------------------------------------------------
//* element-wise raise to a power
template<typename T>
DenseMatrix<T> Matrix<T>::pow(double n) const
{
DenseMatrix<T> R(*this);
FORi
{
double val = R[i];
R[i] = pow(val,n);
}
return R;
}
//-----------------------------------------------------------------------------
//* returns the transpose of this matrix (makes a copy)
template <typename T>
DenseMatrix<T> Matrix<T>::transpose() const
{
DenseMatrix<T> t(this->nCols(), this->nRows());
FORij t(j,i) = (*this)(i,j);
return t;
}
//-----------------------------------------------------------------------------
//* returns the transpose of a matrix (makes a copy)
template <typename T>
DenseMatrix<T> transpose(const Matrix<T> &A)
{
return A.transpose();
}
//-----------------------------------------------------------------------------
//* Returns the sum of all matrix elements
template<typename T>
T Matrix<T>::sum() const
{
if (!size()) return T(0);
T v = VIDX(0);
for (INDEX i=1; i<this->size(); i++) v += VIDX(i);
return v;
}
//-----------------------------------------------------------------------------
//* Returns the standard deviation of the matrix
template<typename T>
T Matrix<T>::stdev() const
{
GCHK(this->size()<2, "Matrix::stdev() size must be > 1");
T mean = this->mean();
T diff = VIDX(0)-mean;
T stdev = diff*diff;
for (INDEX i=1; i<this->size(); i++)
{
diff = VIDX(i)-mean;
stdev += diff*diff;
}
return sqrt(stdev/T(this->size()-1));
}
//-----------------------------------------------------------------------------
//* Returns the maximum of the matrix
template<typename T>
T Matrix<T>::max() const
{
GCHK(!this->size(), "Matrix::max() size must be > 0");
T v = VIDX(0);
for (INDEX i=1; i<this->size(); i++) v = std::max(v, VIDX(i));
return v;
}
//-----------------------------------------------------------------------------
//* Returns the minimum of the matrix
template<typename T>
T Matrix<T>::min() const
{
GCHK(!this->size(), "Matrix::min() size must be > 0");
T v = VIDX(0);
for (INDEX i=1; i<this->size(); i++) v = std::min(v, VIDX(i));
return v;
}
//-----------------------------------------------------------------------------
//* Returns the maximum absolute value of the matrix
template<typename T>
T Matrix<T>::maxabs() const
{
GCHK(!this->size(), "Matrix::maxabs() size must be > 0");
T v = VIDX(0);
for (INDEX i=1; i<this->size(); i++) v = Utility::MaxAbs(v, VIDX(i));
return v;
}
//-----------------------------------------------------------------------------
//* Returns the minimum absoute value of the matrix
template<typename T>
T Matrix<T>::minabs() const
{
GCHK(!this->size(), "Matrix::minabs() size must be > 0");
T v = VIDX(0);
for (INDEX i=1; i<this->size(); i++) v = Utility::MinAbs(v, VIDX(i));
return v;
}
//-----------------------------------------------------------------------------
//* returns the L2 norm of the matrix
template<typename T>
T Matrix<T>::norm() const
{
GCHK(!this->size(), "Matrix::norm() size must be > 0");
return sqrt(dot(*this));
}
//-----------------------------------------------------------------------------
//* returns the average of the matrix
template<typename T>
T Matrix<T>::mean() const
{
GCHK(!this->size(), "Matrix::mean() size must be > 0");
return sum()/T(this->size());
}
//-----------------------------------------------------------------------------
//* Returns the dot product of two vectors
template<typename T>
T Matrix<T>::dot(const Matrix<T>& r) const
{
SSCK(*this, r, "Matrix<T>::dot");
if (!this->size()) return T(0);
T v = r[0]*VIDX(0);
for (INDEX i=1; i<this->size(); i++) v += r[i]*VIDX(i);
return v;
}
//-----------------------------------------------------------------------------
// returns the sum of the matrix diagonal
//-----------------------------------------------------------------------------
template<typename T>
T Matrix<T>::trace() const
{
const INDEX N = std::min(nRows(),nCols());
if (!N) return T(0);
T r = MIDX(0,0);
for (INDEX i=0; i<N; i++)
r += MIDX(i,i);
return r;
}
//-----------------------------------------------------------------------------
//* Adds a matrix to this one
template<typename T>
Matrix<T>& Matrix<T>::operator+=(const Matrix &r)
{
SSCK(*this, r, "operator+= or operator +");
FORi VIDX(i)+=r[i];
return *this;
}
//-----------------------------------------------------------------------------
// subtracts a matrix from this one
//-----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator-=(const Matrix &r)
{
SSCK(*this, r, "operator-= or operator -");
FORi VIDX(i)-=r[i];
return *this;
}
//-----------------------------------------------------------------------------
// multiplies each element in this by the corresponding element in R
//-----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator*=(const Matrix<T>& R)
{
SSCK(*this, R, "operator*=");
FORi
{
VIDX(i) *= R[i];
}
return *this;
}
//-----------------------------------------------------------------------------
// divides each element in this by the corresponding element in R
//-----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator/=(const Matrix<T>& R)
{
SSCK(*this, R, "operator/= or operator/");
FORi
{
GCHK(fabs(R[i])>0,"Operator/: division by zero");
VIDX(i) /= R[i];
}
return *this;
}
//-----------------------------------------------------------------------------
// scales this matrix by a constant
//-----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator*=(const T v)
{
FORi VIDX(i)*=v;
return *this;
}
//-----------------------------------------------------------------------------
// adds a constant to this matrix
//-----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator+=(const T v)
{
FORi VIDX(i)+=v;
return *this;
}
//-----------------------------------------------------------------------------
// substracts a constant to this matrix
//-----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator-=(const T v)
{
FORi VIDX(i)-=v;
return *this;
}
//-----------------------------------------------------------------------------
//* scales this matrix by the inverse of a constant
template<typename T>
Matrix<T>& Matrix<T>::operator/=(T v)
{
return (*this)*=(1.0/v);
}
//----------------------------------------------------------------------------
// Assigns one matrix to another
//----------------------------------------------------------------------------
template<typename T>
Matrix<T>& Matrix<T>::operator=(const Matrix<T> &r)
{
this->_set_equal(r);
return *this;
}
//----------------------------------------------------------------------------
// general matrix assignment (for densely packed matrices)
//----------------------------------------------------------------------------
template<typename T>
void Matrix<T>::_set_equal(const Matrix<T> &r)
{
this->resize(r.nRows(), r.nCols());
const Matrix<T> *pr = &r;
if (const SparseMatrix<T> *ps = sparse_cast(pr))
copy_sparse_to_matrix(ps, *this);
else if (diag_cast(pr)) // r is Diagonal?
{
this->zero();
for (INDEX i=0; i<r.size(); i++) MIDX(i,i) = r[i];
}
else memcpy(this->get_ptr(), r.get_ptr(), r.size()*sizeof(T));
}
//-----------------------------------------------------------------------------
//* sets all elements to a constant
template<typename T>
inline Matrix<T>& Matrix<T>::operator=(const T &v)
{
set_all_elements_to(v);
return *this;
}
//-----------------------------------------------------------------------------
//* sets all elements to a constant
template<typename T>
void Matrix<T>::set_all_elements_to(const T &v)
{
FORi VIDX(i) = v;
}
//----------------------------------------------------------------------------
// adds a matrix scaled by factor s to this one.
//----------------------------------------------------------------------------
template <typename T>
void Matrix<T>::add_scaled(const Matrix<T> &A, const T& s)
{
SSCK(A, *this, "Matrix::add_scaled");
FORi VIDX(i) += A[i]*s;
}
//-----------------------------------------------------------------------------
//* writes a matlab command to the console
template<typename T>
void Matrix<T>::matlab(const string &s) const
{
this->matlab(cout, s);
}
//-----------------------------------------------------------------------------
//* Writes a matlab script defining the vector to the stream
template<typename T>
void Matrix<T>::matlab(ostream &o, const string &s) const
{
o << s <<"=zeros(" << nRows() << ","<<nCols()<<");\n";
FORij o << s << "("<<i+1<<","<<j+1<<")=" << MIDX(i,j) << ";\n";
}
//-----------------------------------------------------------------------------
//* sets all matrix elements to zero
template<typename T>
inline Matrix<T>& Matrix<T>::zero()
{
set_all_elements_to(T(0));
return *this;
}
//-----------------------------------------------------------------------------
//* returns the total number of elements
template<typename T>
inline INDEX Matrix<T>::size() const
{
return nRows()*nCols();
}
//-----------------------------------------------------------------------------
//* returns true if (i,j) is within the range of the matrix
template<typename T>
inline bool Matrix<T>::in_range(INDEX i, INDEX j) const
{
return i<nRows() && j<nCols();
}
//-----------------------------------------------------------------------------
//* returns true if the matrix size is rs x cs
template<typename T>
inline bool Matrix<T>::is_size(INDEX rs, INDEX cs) const
{
return nRows()==rs && nCols()==cs;
}
//-----------------------------------------------------------------------------
//* returns true if the matrix is square and not empty
template<typename T>
inline bool Matrix<T>::is_square() const
{
return nRows()==nCols() && nRows();
}
//-----------------------------------------------------------------------------
//* returns true if Matrix, m, is the same size as this
template<typename T>
inline bool Matrix<T>::same_size(const Matrix<T> &m) const
{
return is_size(m.nRows(), m.nCols());
}
//-----------------------------------------------------------------------------
//* returns true if Matrix a and Matrix b are the same size
template<typename T>
inline bool Matrix<T>::same_size(const Matrix<T> &a, const Matrix<T> &b)
{
return a.same_size(b);
}
//-----------------------------------------------------------------------------
//* Displays indexing error message and quits
template<typename T>
void ierror(const Matrix<T> &a, const char *FILE, int LINE, INDEX i, INDEX j)
{
cout << "Error: Matrix indexing failure ";
cout << "in file: " << FILE << ", line: "<< LINE <<"\n";
cout << "Tried accessing index (" << i << ", " << j <<")\n";
cout << "Matrix size was "<< a.nRows() << "x" << a.nCols() << "\n";
exit(EXIT_FAILURE);
}
//-----------------------------------------------------------------------------
//* Displays custom message and indexing error and quits
template<typename T>
void ierror(const Matrix<T> &a, INDEX i, INDEX j, const string m)
{
cout << m << "\n";
cout << "Tried accessing index (" << i << ", " << j <<")\n";
cout << "Matrix size was "<< a.nRows() << "x" << a.nCols() << "\n";
exit(EXIT_FAILURE);
}
//-----------------------------------------------------------------------------
//* Displays matrix compatibility error message
template<typename T>
void merror(const Matrix<T> &a, const Matrix<T> &b, const string m)
{
cout << "Error: " << m << "\n";
cout << "Matrix sizes were " << a.nRows() << "x" << a.nCols();
if (&a != &b) cout << ", and "<< b.nRows() << "x" << b.nCols();
cout << "\n";
exit(EXIT_FAILURE);
}
#endif

View File

@ -1,184 +0,0 @@
#ifndef MATRIXDEF_H
#define MATRIXDEF_H
/******************************************************************************
* Common definitions for Matrix and Vector classes
* This header file contains macros and inline functions needed for the matrix
* classes. All error checking should be defined here as a macro so that it is
* neatly disabled when EXTENDED_ERROR_CHECKING is not defined
******************************************************************************/
/******************************************************************************
* Headers and namespaces used by Matrix and Vector classes
******************************************************************************/
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <cstring>
#include <string>
#include <iomanip>
#include <cmath>
#include "StringManip.h"
#include "Utility.h"
using std::cout;
using std::ostream;
using std::fstream;
using std::map;
using std::vector;
using std::string;
using std::scientific;
using std::showbase;
/******************************************************************************
* Typedefs used by Matrix and Vector classes
******************************************************************************/
//* @typedef INDEX
//* @brief indexing type (default: unsigned) for matrix classes
typedef unsigned INDEX;
//* @typedef CLONE_TYPE
//* @brief dimension of matrix to clone
enum CLONE_TYPE { CLONE_ROW=0, CLONE_COL=1, CLONE_DIAG=2 };
//* @struct TRIPLET
//* @brief Triplet output entity
template <typename T>
struct TRIPLET { TRIPLET<T>(int _i=0, int _j=0, T _v=T(0)) : i(_i), j(_j), v(_v) {}
INDEX i, j; T v; };
/******************************************************************************
* Definitions for row/column major storage
******************************************************************************/
#define COL_STORAGE /* <--- comment out this line for row-major storage*/
#ifdef COL_STORAGE
#define DATA(i,j) _data[(i)+_nRows*(j)]
#else
#define ROW_STORAGE
#define DATA(i,j) _data[(i)*_nCols+(j)]
#endif
/******************************************************************************
* error checking macros
* MICK: checks if index (i,j) is in range MATRIX ONLY
* VICK: checks if index (i) is in range VECTOR ONLY
* MICM: checks if index (i,j) is in range, displays message MATRIX ONLY
* VICM: checks if index (i) is in range, displays message VECTOR ONLY
* SQCK: checks if matrix is square, displays message MATRIX ONLY
* SSCK: checks if a has the same size as b VECTOR/MATRIX
* GCK: generic two object check, checks if c is true VECTOR/MATRIX
* GCHK: generic check, checks if c is true ANYTHING
******************************************************************************/
#define MICK(i,j) /**/
#define VICK(i) /**/
#define MICM(i,j,m) /**/
#define VICM(i,m) /**/
#define SQCK(a,m) /**/
#define SSCK(a,b,m) /**/
#define SSCK(a,b,m) /**/
#define GCK(a,b,c,m) /**/
#define GCHK(c,m) /**/
// the following two convert __LINE__ to a string
#define STRING2(x) #x
#define STRING(x) STRING2(x)
// prints file and line number for error messages
#define ERROR(x) __FILE__":"STRING(__LINE__)" "x
/******************************************************************************
* Shortcuts for Vector and Matrix indexing
******************************************************************************/
#define MIDX(i,j) (*this)(i,j)
#define VIDX(i) (*this)[i]
/******************************************************************************
* Shortcuts for Vector and Matrix loops over all elements
******************************************************************************/
#define FORi for(INDEX i=0; i<this->size(); i++)
#define FORij for(INDEX i=0; i<nRows(); i++) for (INDEX j=0; j<nCols(); j++)
/******************************************************************************
* BLAS and LAPACK definitions
******************************************************************************/
#ifdef MKL
#include "mkl.h"
#define dgemv_ dgemv
#define dgemm_ dgemm
#define dgetrf_ dgetrf
#define dgetri_ dgetri
#define dgecon_ dgecon
#define dlange_ dlange
#else
extern "C"
{
extern void dgemv_(char*,int*,int*,double*,const double*,int*,const double*,int *,double*,double*,int*);
extern void dgemm_(char*,char*,int*,int*,int*,double*,const double*,int*,const double*,int*,double*,double*,int*);
extern void dgetrf_(int*,int*,double*,int*,int*,int*);
extern void dgetri_(int*,double*,int*,int*,double*,int*,int*);
extern void dgecon_(char*,int*,double*,int*,double*,double*,double*,int*,int*);
extern double dlange_(char*,int*,int*,const double*,int*,double*);
};
#endif
// forward declarations of matrix and vector classes
template<typename T> class Matrix;
template<typename T> class DenseMatrix;
template<typename T> class SparseMatrix;
template<typename T> class SparseVector;
template<typename T> class DiagonalMatrix;
template<typename T> class Vector;
template<typename T> class DenseVector;
template<typename T> class CloneVector;
//* forward declaration of operations
//@{
template<class T> DenseVector<T> operator*(const Matrix<T> &M, const SparseVector<T> &v);
template<class T> DenseVector<T> operator*(const SparseVector<T> &v, const Matrix<T> &M);
template<class T> SparseVector<T> operator*(const SparseMatrix<T> &M, const SparseVector<T> &v);
template<class T> SparseVector<T> operator*(const SparseVector<T> &v, const SparseMatrix<T> &M);
template<class T> DenseVector<T> operator*(const SparseMatrix<T> &A, const Vector<T>& x);
template<class T> DenseVector<T> operator*(const Vector<T> &A, const SparseMatrix<T>& x);
template<class T> DenseMatrix<T> operator*(const SparseMatrix<T> &A, const Matrix<T>& D);
template<class T> SparseMatrix<T> operator*(const SparseMatrix<T> &A, const DiagonalMatrix<T>& D);
template<class T> SparseMatrix<T> operator*(const SparseMatrix<T> &A, const SparseMatrix<T> &B);
template<class T> T dot(const SparseVector<T> &a, const SparseVector<T> &b);
//@}
template<class T> CloneVector<T> column(Matrix<T> &c, INDEX i) {
return CloneVector<T>(c, CLONE_COL, i);
}
template<class T> CloneVector<T> row(Matrix<T> &c, INDEX i) {
return CloneVector<T>(c, CLONE_ROW, i);
}
template<class T> CloneVector<T> diagonal(Matrix<T> &c) {
return CloneVector<T>(c, CLONE_DIAG);
}
template<class T> const CloneVector<T> column(const Matrix<T> &c, INDEX i) {
return CloneVector<T>(c, CLONE_COL, i);
}
template<class T> const CloneVector<T> row(const Matrix<T> &c, INDEX i) {
return CloneVector<T>(c, CLONE_ROW, i);
}
template<class T> const CloneVector<T> diagonal(const Matrix<T> &c) {
return CloneVector<T>(c, CLONE_DIAG);
}
template<class T> const SparseMatrix<T> *sparse_cast(const Matrix<T> *m);
template<class T> const DiagonalMatrix<T> *diag_cast(const Matrix<T> *m);
template<class T> void copy_sparse_to_matrix(const SparseMatrix<T> *s, Matrix<T> &m);
// double precision shortcuts
typedef Matrix<double> MATRIX; // matrix of double
typedef Vector<double> VECTOR; // vector of double
typedef DenseMatrix<double> DENS_MAT; // dense matrix of double type
typedef CloneVector<double> CLON_VEC; // cloned vector of double type
typedef DenseVector<double> DENS_VEC; // dense vector of double type
typedef DiagonalMatrix<double> DIAG_MAT; // diagonal matrix of double type
typedef SparseMatrix<double> SPAR_MAT; // sparse matrix of double type
typedef SparseVector<double> SPAR_VEC; // sparse matrix of double type
typedef Vector<INDEX> IVECTOR; // general Vector of INDEX type
// forward declaration of error messages
template<typename T> void ierror(const Matrix<T> &a, const char *FILE, int LINE, INDEX i, INDEX j=0);
template<typename T> void ierror(const Matrix<T> &a, INDEX i, INDEX j, const string m);
template<typename T> void merror(const Matrix<T> &a, const Matrix<T> &b, const string m);
inline void gerror(const string m) { cout<<"Error: "<<m<<"\n"; exit(EXIT_FAILURE); }
#endif

View File

@ -1,29 +0,0 @@
#ifndef MATRIXLIBRARY_H
#define MATRIXLIBRARY_H
#include "DenseMatrix.h"
#include "DenseVector.h"
#include "CloneVector.h"
#include "DiagonalMatrix.h"
#include "SparseMatrix.h"
#include "SparseVector.h"
template<typename T>
const SparseMatrix<T> *sparse_cast(const Matrix<T> *m)
{
return dynamic_cast<const SparseMatrix<T>*>(m);
}
template<typename T>
void copy_sparse_to_matrix(const SparseMatrix<T> *s, Matrix<T> &m)
{
m.zero();
TRIPLET<T> triplet;
for (INDEX i=0; i<s->size(); i++)
{
triplet = s->get_triplet(i);
m(triplet.i, triplet.j) = triplet.v;
}
}
#endif

View File

@ -1,706 +0,0 @@
#include <string>
#include <fstream>
#include <stdio.h>
#include <sstream>
#include "OutputManager.h"
#include "ATC_Error.h"
//#define EXTENDED_ERROR_CHECKING
namespace ATC {
static const int kFieldPrecison = 12;
static const int kFieldWidth = kFieldPrecison + 6;
static const int kFileNameSize = 26;
static string tensor_component_names[9] = {"11","12","13",
"21","22","23",
"31","32","33"};
static string sym_tensor_component_names[6] = {"11","22","33","12","13","23"};
static string vector_component_names[3] = {"_X","_Y","_Z"};
static string list_component_names[26] = {"_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z"};
string* get_component_names(int type) {
string* componentNames = list_component_names;
if (type==VECTOR_OUTPUT)
componentNames = vector_component_names;
else if (type == SYM_TENSOR_OUTPUT)
componentNames = sym_tensor_component_names;
else if (type == TENSOR_OUTPUT)
componentNames = tensor_component_names;
return componentNames;
}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
OutputManager::OutputManager(string outputPrefix, OutputType otype)
: outputPrefix_(outputPrefix),
dataType_(POINT),
outputType_(otype),
firstStep_(true),
writeGlobalsHeader_(true),
firstGlobalsWrite_(true),
tensorToComponents_(false), // paraview does not support tensors
vectorToComponents_(false),
initialized_(false)
{}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
OutputManager::OutputManager()
: outputPrefix_("NULL"),
dataType_(POINT),
outputType_(ENSIGHT),
firstStep_(true),
writeGlobalsHeader_(true),
firstGlobalsWrite_(true),
tensorToComponents_(false), // paraview does not support tensors
vectorToComponents_(false),
initialized_(false)
{}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
OutputManager::~OutputManager() {}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
void OutputManager::set_option(OutputOption option, bool value) {
if (option == OUTPUT_VECTOR_COMPONENTS) vectorToComponents_ = value;
else if (option == OUTPUT_TENSOR_COMPONENTS) tensorToComponents_ = value;
else throw ATC_Error(0,"unsupported output option");
};
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
void OutputManager::initialize(string outputPrefix, OutputType otype)
{
if (outputPrefix_ != outputPrefix ) { // new stream with existing object
outputPrefix_ = outputPrefix;
initialized_ = false;
}
outputTimes_.clear();
outputType_ = otype;
firstStep_ = true;
firstGlobalsWrite_ = true;
writeGlobalsHeader_ = true;
}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
// Dump text-based fields to disk for later restart
void OutputManager::write_restart_file(string fileName, OUTPUT_LIST *data)
{
FILE * fp=NULL;
fp=fopen(fileName.c_str(),"wb"); // open
OUTPUT_LIST::iterator iter;
for (iter = data->begin(); iter != data->end(); iter++) {
const MATRIX* field_data = iter->second;
for (int i = 0; i < field_data->nRows(); ++i) {
for (int j = 0; j < field_data->nCols(); ++j) {
double x = (*field_data)(i,j);
fwrite(&x,sizeof(double),1,fp);
}
}
}
fclose(fp);
}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
// Read a file corresponding to a write by write_restart_file
void OutputManager::read_restart_file(string fileName, OUTPUT_LIST *data)
{
FILE * fp=NULL;
fp=fopen(fileName.c_str(),"rb"); // open
OUTPUT_LIST::iterator iter;
for (iter = data->begin(); iter != data->end(); iter++) {
MATRIX* field_data = iter->second;
for (int i = 0; i < field_data->nRows(); ++i) {
for (int j = 0; j < field_data->nCols(); ++j) {
double myVal;
fread(&myVal,sizeof(double),1,fp);
(*field_data)(i,j) = myVal;
}
}
}
fclose(fp);
}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
void OutputManager::write_globals(void)
{
if ( outputPrefix_ == "NULL") return;
string file = outputPrefix_ + ".GLOBALS";
ofstream text;
if ( firstGlobalsWrite_ ) text.open(file.c_str(),ios_base::out);
else text.open(file.c_str(),ios_base::app);
firstGlobalsWrite_ = false;
map<string, double>::iterator iter;
// header
if ( firstStep_ || writeGlobalsHeader_) {
text << "# time:1 ";
int index = 2;
for (iter = globalData_.begin(); iter != globalData_.end(); iter++)
{
string name = iter->first;
string str; stringstream out; out << ":" << index++;
str = out.str();
name.append(str);
text.width(kFieldWidth); text << name << " ";
}
text << '\n';
}
writeGlobalsHeader_ = false;
// data
text.width(kFieldWidth); text << outputTimes_[outputTimes_.size()-1] << " ";
for (iter = globalData_.begin();
iter != globalData_.end(); iter++) {
double value = iter->second;
text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << value << " ";
}
text << "\n";
}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
void OutputManager::write_geometry(const MATRIX &coordinates,
const Array2D<int> *connectivities)
{
if ( outputPrefix_ == "NULL") return;
// geometry based on a reference configuration
string geom_file_name = outputPrefix_ + ".geo";
string geom_file_text = outputPrefix_ + ".XYZ";
// open file
FILE * fp=NULL;
ofstream text;
char buffer[80];
if ( ! initialized_ ) {
fp=fopen(geom_file_name.c_str(),"wb"); // open
strcpy(buffer,"C Binary");
fwrite(buffer,sizeof(char),80,fp);
// write geometry once
if (outputType_ == GNUPLOT) text.open(geom_file_text.c_str(),ios_base::out);
}
else {
fp=fopen(geom_file_name.c_str(),"ab"); // append
// if (outputType_ == GNUPLOT) text.open(geom_file_text.c_str(),ios_base::app);
}
if (fp == NULL) {
throw ATC_Error(0,"can not create Ensight geometry file");
}
// write preamble
strcpy(buffer,"BEGIN TIME STEP");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"Ensight geometry file");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"description");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"node id assign");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"element id assign");
fwrite(buffer,sizeof(char),80,fp);
// per part
strcpy(buffer,"part");
fwrite(buffer,sizeof(char),80,fp);
int part_number=1;
fwrite(&part_number,sizeof(int),1,fp);
strcpy(buffer,"description");
fwrite(buffer,sizeof(char),80,fp);
// write coordinates
strcpy(buffer,"coordinates");
fwrite(buffer,sizeof(char),80,fp);
number_of_nodes_ = coordinates.nCols();
fwrite(&number_of_nodes_,sizeof(int),1,fp);
int number_of_spatial_dimensions = coordinates.nRows();
if (number_of_spatial_dimensions != 3)
throw ATC_Error(0,"Ensight writer needs a 3D geometry");
for (int i = 0; i < number_of_spatial_dimensions; ++i)
{
for (int j = 0; j < number_of_nodes_; ++j)
{
float x = (float) coordinates(i,j);
fwrite(&x,sizeof(float),1,fp);
}
}
// write mesh connectivities or point "connectivities"
if (connectivities)
{
dataType_ = MESH;
strcpy(buffer,"hexa8");
fwrite(buffer,sizeof(char),80,fp);
int number_of_elements = connectivities->nCols();
fwrite(&number_of_elements,sizeof(int),1,fp);
int number_of_nodes_per_element = connectivities->nRows();
for (int j = 0; j < number_of_elements; ++j)
{
for (int i = 0; i < number_of_nodes_per_element; ++i)
{
int inode = (*connectivities)(i,j) +1; // 1 based numbering
fwrite(&inode,sizeof(int),1,fp);
}
}
}
else
{
strcpy(buffer,"point");
fwrite(buffer,sizeof(char),80,fp);
int number_of_elements = number_of_nodes_;
fwrite(&number_of_elements,sizeof(int),1,fp);
int number_of_nodes_per_element = 1;
for (int j = 0; j < number_of_elements; ++j)
{
int inode = j +1; // 1 based numbering
fwrite(&inode,sizeof(int),1,fp);
}
}
// end per part
strcpy(buffer,"END TIME STEP");
fwrite(buffer,sizeof(char),80,fp);
fclose(fp);
// text output
if (outputType_ == GNUPLOT )
{
for (int j = 0; j < number_of_nodes_; ++j)
{
for (int i = 0; i < number_of_spatial_dimensions; ++i)
{
text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << coordinates(i,j) << " ";
}
text << "\n";
}
text << "\n";
}
if (!initialized_) initialized_ = true;
}
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
void OutputManager::write_geometry(OUTPUT_LIST &part_coordinates)
{
if ( outputPrefix_ == "NULL") return;
// geometry based on a reference configuration
string geom_file_name = outputPrefix_ + ".geo";
string geom_file_text = outputPrefix_ + ".XYZ";
// open file
FILE * fp =NULL;
ofstream text;
char buffer[80];
if ( ! initialized_ )
{
fp=fopen(geom_file_name.c_str(),"wb"); // open
strcpy(buffer,"C Binary");
fwrite(buffer,sizeof(char),80,fp);
if (outputType_ == GNUPLOT) text.open(geom_file_text.c_str(),ios_base::out);
}
else
{
fp=fopen(geom_file_name.c_str(),"ab"); // append
if (outputType_ == GNUPLOT) text.open(geom_file_text.c_str(),ios_base::app);
}
if (fp == NULL) {
throw ATC_Error(0,"can not create Ensight geometry file");
}
// write preamble
strcpy(buffer,"BEGIN TIME STEP");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"Ensight geometry file");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"description");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"node id assign");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"element id assign");
fwrite(buffer,sizeof(char),80,fp);
// per part
int part_number=1;
OUTPUT_LIST::iterator iter;
for (iter = part_coordinates.begin(); iter != part_coordinates.end(); iter++)
{
string part_name = iter->first;
DenseMatrix<double> coordinates = *(iter->second);
strcpy(buffer,"part");
fwrite(buffer,sizeof(char),80,fp);
fwrite(&part_number,sizeof(int),1,fp);
strcpy(buffer,part_name.c_str());
fwrite(buffer,sizeof(char),80,fp);
// write coordinates
strcpy(buffer,"coordinates");
fwrite(buffer,sizeof(char),80,fp);
number_of_nodes_ = coordinates.nCols();
fwrite(&number_of_nodes_,sizeof(int),1,fp);
int number_of_spatial_dimensions = coordinates.nRows();
if (number_of_spatial_dimensions != 3)
{
throw ATC_Error(0,"Ensight writer needs a 3D geometry");
}
for (int i=0; i<number_of_spatial_dimensions; i++)
{
for (int j=0; j<number_of_nodes_; j++)
{
float x = (float)coordinates(i,j);
fwrite(&x,sizeof(float),1,fp);
}
}
// write mesh connectivities or point "connectivities"
strcpy(buffer,"point");
fwrite(buffer,sizeof(char),80,fp);
int number_of_elements = number_of_nodes_;
fwrite(&number_of_elements,sizeof(int),1,fp);
int number_of_nodes_per_element = 1;
for (int j = 0; j < number_of_elements; ++j)
{
int inode = j +1; // 1 based numbering
fwrite(&inode,sizeof(int),1,fp);
}
++part_number;
}
strcpy(buffer,"END TIME STEP");
fwrite(buffer,sizeof(char),80,fp);
fclose(fp);
if (!initialized_) initialized_ = true;
}
//-----------------------------------------------------------------------------
/** pack "soln" into data */
//-----------------------------------------------------------------------------
void OutputManager::write_data(double time, FIELDS *soln, OUTPUT_LIST *data, const int *node_map)
{
// pack
OUTPUT_LIST combined_data;
if (soln)
{
FIELDS::iterator iter;
for (iter = soln->begin(); iter != soln->end(); iter++)
{
FieldName field_index = iter->first;
MATRIX* field_data = &(iter->second);
string field_name = field_to_string(field_index);
combined_data[field_name] = field_data;
}
}
if (data)
{
OUTPUT_LIST::iterator iter;
for (iter = data->begin(); iter != data->end(); iter++)
{
string field_name = iter->first;
MATRIX* field_data = iter->second;
combined_data[field_name] = field_data;
}
}
write_data(time, &(combined_data), node_map);
};
//-----------------------------------------------------------------------------
/** write (ensight gold format "C" binary) data */
//-----------------------------------------------------------------------------
void OutputManager::write_data(double time, OUTPUT_LIST *data, const int *node_map)
{
if (! initialized_) throw ATC_Error(0,"must write geometry before data");
// write data
OUTPUT_LIST::iterator iter;
for (iter = data->begin(); iter != data->end(); iter++)
{
string field_name = iter->first;
const MATRIX* field_data = iter->second;
write_data(field_name, field_data, node_map);
}
// write dictionary
write_dictionary(time,data);
// write text dump
if (outputType_ == GNUPLOT) {
write_text(data);
if (firstStep_ && node_map) {
string map_file_text = outputPrefix_ + ".MAP";
ofstream text;
text.open(map_file_text.c_str(),ios_base::out);
for (int i=0; i< number_of_nodes_ ; i++) {
text << node_map[i] << "\n";
}
text.close();
}
}
// global variables
if (! globalData_.empty()) write_globals();
if (firstStep_) firstStep_ = false;
}
//-----------------------------------------------------------------------------
/** write (ensight gold format "C" binary) data */
//-----------------------------------------------------------------------------
void OutputManager::write_data(string field_name, const MATRIX *field_data, const int *node_map)
{
int ndof = field_data->nCols();
int col_start = 0;
int col_end = ndof;
string filenames[kFileNameSize];
int nfiles = 1;
filenames[0] = outputPrefix_ + "." + field_name;
int type = data_type(ndof);
if (use_component_names(type)){
nfiles = ndof;
string* component_names = get_component_names(type);
for (int ifile = 0; ifile < nfiles; ++ifile)
{
string comp_name = field_name + component_names[ifile];
filenames[ifile] = outputPrefix_ + "." + comp_name;
}
}
for (int ifile = 0; ifile < nfiles; ++ifile)
{
// for vector/tensor to components
if ( nfiles > 1 )
{
col_start = ifile;
col_end = ifile+1;
}
// open or append data file
string data_file_name = filenames[ifile];
FILE * fp;
if ( outputTimes_.size() == 0 ) {
fp=fopen(data_file_name.c_str(),"wb"); // open
}
else {
fp=fopen(data_file_name.c_str(),"ab"); // append
}
if (fp == NULL) {
throw ATC_Error(0,"can not create Ensight data file: "+data_file_name);
}
// write data
char buffer[80];
strcpy(buffer,"BEGIN TIME STEP");
fwrite(buffer,sizeof(char),80,fp);
strcpy(buffer,"field name"); // NOTE could be the field name
fwrite(buffer,sizeof(char),80,fp);
// per part
strcpy(buffer,"part");
fwrite(buffer,sizeof(char),80,fp);
int part_number = 1;
fwrite(&part_number,sizeof(int),1,fp);
strcpy(buffer,"coordinates");
fwrite(buffer,sizeof(char),80,fp);
if (node_map)
{
for (int j = col_start; j < col_end; ++j)
{
for (int i = 0; i < number_of_nodes_; ++i)
{
int inode = node_map[i];
float x = (float) (*field_data)(inode,j);
fwrite(&x,sizeof(float),1,fp);
}
}
}
else
{
for (int j = col_start; j < col_end; ++j)
{
for (int i = 0; i < field_data->nRows(); ++i)
{
float x = (float) (*field_data)(i,j);
fwrite(&x,sizeof(float),1,fp);
}
}
}
// end per part
strcpy(buffer,"END TIME STEP");
fwrite(buffer,sizeof(char),80,fp);
fclose(fp);
}
}
void OutputManager::write_text(OUTPUT_LIST *data)
{
string data_file_text = outputPrefix_ + ".DATA";
ofstream text;
if (firstStep_) text.open(data_file_text.c_str(),ios_base::out);
else text.open(data_file_text.c_str(),ios_base::app);
// write data label header
if (firstStep_)
{
text.width(6); text << "# index:1" << " "; // give an ordinate for gnuplot
text.width(10); text << " step:2" << " ";
int k =3;
if (data)
{
OUTPUT_LIST::iterator iter;
for (iter = data->begin(); iter != data->end(); iter++)
{
int ncols = iter->second->nCols();
string field_name = iter->first;
if (ncols == 1) {
string str; stringstream out; out << ":" << k; str = out.str();
field_name.append(str);
text.width(kFieldWidth); text << field_name << " ";
k++;
}
else {
for (int i = 1; i <= ncols; i++) {
string str; stringstream out; out <<"_"<<i<<":"<<k; str = out.str();
string name = field_name;
name.append(str);
text.width(kFieldWidth); text << name << " ";
k++;
}
}
}
} else { throw ATC_Error(0," data missing from output");}
text << "\n";
}
text << "# timestep " << outputTimes_.size() << " : "
<< outputTimes_[outputTimes_.size()-1] << "\n";
int nrows = 0;
OUTPUT_LIST::iterator iter;
iter = data->begin();
const MATRIX* field_data = iter->second;
nrows = field_data->nRows();
for (int i = 0; i < nrows; ++i)
{
text.width(6); text << i << " "; // give an ordinate for gnuplot
text.width(10); text << outputTimes_.size() << " ";
OUTPUT_LIST::iterator iter;
for (iter = data->begin(); iter != data->end(); iter++)
{
const MATRIX* field_data = iter->second;
for (int j = 0; j < field_data->nCols(); ++j)
{
text.width(kFieldWidth);
text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << (*field_data)(i,j) << " ";
}
}
text <<"\n";
}
text <<"\n";
}
/** write (ensight gold : ASCII "C" format) dictionary */
void OutputManager::write_dictionary(double time, OUTPUT_LIST *data)
{
// store the time step value
outputTimes_.push_back(time);
// file names
string dict_file_name = outputPrefix_ + ".case";
string geom_file_name = outputPrefix_ + ".geo";
// open file
FILE * fp;
if ((fp=fopen(dict_file_name.c_str(),"w")) == NULL)
{
throw ATC_Error(0,"can not create Ensight case file");
}
// write file
fprintf(fp,"FORMAT\n");
fprintf(fp,"type: ensight gold\n");
fprintf(fp,"GEOMETRY\n");
if ( dataType_ == POINT) {
fprintf(fp,"model: 1 1 %s change_coords_only\n", geom_file_name.c_str());
} else {
fprintf(fp,"model: %s\n", geom_file_name.c_str());
}
fprintf(fp,"VARIABLE\n");
// data types
if (!data) throw ATC_Error(0,"no data for output");
OUTPUT_LIST::iterator iter;
int ncols = 0;
for (iter = data->begin(); iter != data->end(); iter++) {
string field_name = iter->first;
string field_file = outputPrefix_ + "." + field_name;
const MATRIX* field_data = iter->second;
int fieldCols = field_data->nCols();
ncols += fieldCols;
int type = data_type(fieldCols);
if (use_component_names(type)){
string* component_names = get_component_names(type);
for (int j = 0; j < fieldCols; ++j)
{
string comp_name = field_name + component_names[j];
string comp_file = outputPrefix_ + "." + comp_name;
fprintf(fp,"scalar per node: 1 1 %s %s\n",
comp_name.c_str(),comp_file.c_str());
}
}
else if (type == VECTOR_OUTPUT) {
fprintf(fp,"vector per node: 1 1 %s %s\n",
field_name.c_str(),field_file.c_str());
}
else if (type == SYM_TENSOR_OUTPUT) {
fprintf(fp,"tensor symm per node: 1 1 %s %s\n",
field_name.c_str(),field_file.c_str());
}
else if (type == TENSOR_OUTPUT) {
fprintf(fp,"tensor asymm per node: 1 1 %s %s\n",
field_name.c_str(),field_file.c_str());
}
else {
fprintf(fp,"scalar per node: 1 1 %s %s\n",
field_name.c_str(),field_file.c_str());
}
}
if (!firstStep_ && ncols != nDataCols_) {
throw ATC_Error(0,"number of columns of data has changed: start new output");
}
nDataCols_ = ncols;
int nsteps = outputTimes_.size();
fprintf(fp,"TIME\n");
fprintf(fp,"time set: 1\n");
fprintf(fp,"number of steps: %10d\n",nsteps);
if ( dataType_ == POINT) {
fprintf(fp,"filename start number: 0\n");
fprintf(fp,"filename increment: 1\n");
}
fprintf(fp,"time values:\n");
for (int j = 0; j < nsteps; ++j) {
double t = outputTimes_[j];
fprintf(fp,"%12.5e",t);
if ((j+1)%6 == 0) fprintf(fp,"\n");
}
fprintf(fp,"\n");
fprintf(fp,"FILE\n");
fprintf(fp,"file set: 1\n");
fprintf(fp,"number of steps: %10d\n",nsteps);
fclose(fp);
};
} // end ATC namespace

View File

@ -1,126 +0,0 @@
#ifndef OUTPUT_MANAGER_H
#define OUTPUT_MANAGER_H
#include "ATC_TypeDefs.h"
#include <map>
#include <string>
// NOTE : number of rows to data type:
// 1 -> scalar
// 3 -> vector x,y,z
// NOT 6 -> tensor xx,xy,xz,yy,yz,zz
// 6 -> tensor xx,yy,zz,xy,zx,yz
// 9 -> tensor xx,xy,xz,yx,yy,yz,zx,zy,zz
using namespace std;
namespace ATC {
enum OutputType { ENSIGHT=0, GNUPLOT };
enum OutputDataType { POINT=0, MESH };
enum OutputDataCardinality { SCALAR_OUTPUT=0, VECTOR_OUTPUT, TENSOR_OUTPUT,
SYM_TENSOR_OUTPUT, LIST_OUTPUT };
enum OutputOption { OUTPUT_VECTOR_COMPONENTS=0, OUTPUT_TENSOR_COMPONENTS};
class OutputManager{
public:
OutputManager(void);
OutputManager(string outputPrefix, OutputType otype = ENSIGHT);
~OutputManager(void);
/** initialize output */
void initialize(string outputPrefix, OutputType otype = ENSIGHT);
/** set output options */
void set_option(OutputOption option, bool value);
// Dump text-based field info to disk for later restart
void write_restart_file(string fileName, OUTPUT_LIST *data);
// Read text-based field file written from write_restart_file
void read_restart_file(string fileName, OUTPUT_LIST *data);
/** write initial/reference geometry
default is to write point data,
if connectivities are given then mesh data will be output
coordinates : num _total_ points/nodes X num spatial dim
connectivities : num elements X num nodes per element*/
void write_geometry(const MATRIX &coordinates,
const Array2D<int> *connectivity=NULL);
void write_geometry(OUTPUT_LIST &part_coordinates);
/** write data from a time step
specify node_map to handle periodic soln & data */
void write_data(double time, OUTPUT_LIST *data, const int *node_map=NULL);
void write_data(double time, FIELDS *soln, OUTPUT_LIST *data,
const int *node_map=NULL);
/*
void write_data (double time,
map<string, map<string, DenseMatrix<double> * > * > parts_data,
const int * node_map = NULL);
*/
/** add a scalar to a text output file */
void add_global(const string& name, const double& value) {
globalData_[name] = value; }
/** delete a scalar from the output */
void delete_global(const string& name) { globalData_.erase(name); }
/** reset the stored output scalars */
void reset_globals() { globalData_.clear(); writeGlobalsHeader_=true; }
/** return data type: scalar, vector, tensor, list */
int data_type(const DENS_MAT & data) const {
return data_type(data.nCols());
}
int data_type(int cols) const {
if (cols == 1) return SCALAR_OUTPUT;
else if (cols == 3) return VECTOR_OUTPUT;
else if (cols == 6) return SYM_TENSOR_OUTPUT;
else if (cols == 9) return TENSOR_OUTPUT;
else return LIST_OUTPUT;
}
bool use_component_names(int type) {
if ( (type==LIST_OUTPUT) ||
((type==SYM_TENSOR_OUTPUT || type==TENSOR_OUTPUT) && tensorToComponents_)
|| (type==VECTOR_OUTPUT && vectorToComponents_) )
return true;
else
return false;
}
private:
void write_data(string name, const MATRIX *data, const int *node_map=NULL);
void write_text(OUTPUT_LIST *data);
void write_dictionary(double time, OUTPUT_LIST *data);
void write_globals();
//* status booleans
bool initialized_, firstStep_, firstGlobalsWrite_, writeGlobalsHeader_;
/** number of columns of data */
int nDataCols_;
/** number of nodes */
int number_of_nodes_; // NOTE it would be nicer if node_map came with a size
/** data type */
int dataType_;
/** base name for output files */
string outputPrefix_;
/** list of output timesteps */
vector<double> outputTimes_;
/** output type */
int outputType_;
/** output tensor as its components */
bool tensorToComponents_;
/** output vector as its components */
bool vectorToComponents_;
/** global variables */
map<string,double> globalData_;
};
}
#endif

View File

@ -1,224 +0,0 @@
/**
* @class PhysicsModel
* @brief An adaptor for the FE_Engine of the specific weak form of
* the continuum PDE for the FE_Engine.
* It is assumed that the PDE fits this template:
* DENSITY(FIELDS) FIELD_RATE
* = DIV FLUX(FIELDS, GRAD_FIELDS) + SOURCE(FIELDS,GRAD_FIELDS)
* + PRESCRIBED_SOURCE(X,t) + EXTRINSIC_SOURCE(FIELDS,GRAD_FIELDS)
*/
#ifndef PHYSICS_MODEL_H
#define PHYSICS_MODEL_H
// included headers
#include <map>
#include "Array2D.h"
#include "MatrixLibrary.h"
#include "ATC_Error.h"
#include "Material.h"
#include "ATC_TypeDefs.h"
#include "StringManip.h"
using namespace std;
using namespace ATC_STRING;
namespace ATC
{
// Forward declarations
class ATC_Transfer;
class PhysicsModel
{
public:
// constructor
PhysicsModel(string fileName,
ATC_Transfer * atcTransfer)
: atcTransfer_(atcTransfer)
{
parse_material_file(fileName);
}
// destructor
virtual ~PhysicsModel()
{
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
if (mat) delete mat;
}
}
/** parse material file */
void parse_material_file(string fileName)
{
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
if (mat) delete mat;
}
fstream fileId(fileName.c_str(), std::ios::in);
if (!fileId.is_open()) throw ATC_Error(0,"cannot open material file");
vector<string> line;
int index = 0;
while(fileId.good()) {
get_command_line(fileId, line);
if (line.size() == 0 || line[0] == "#") continue;
if (line[0] == "material") {
string tag = line[1];
Material * mat = new Material(tag,fileId);
materials_.push_back(mat);
materialNameToIndexMap_[tag] = index++;
}
}
if (int(materials_.size()) == 0) {
throw ATC_Error(0,"No materials were defined"); }
cout << " ATC:: " << int(materials_.size()) << " materials defined\n";
fileId.close();
}
/** initialize */
virtual void initialize(void) = 0;
// set timescale parameters based on a given lengthscale
virtual void set_timescales(const double lengthscale) {};
/** access number of materials */
int get_nMaterials(void) const
{
return materials_.size();
}
/** access material index from name */
int material_index(const string & name) const
{
string tag = name;
to_lower(tag); // this is an artifact of StringManip parsing
map<string,int>::const_iterator iter;
iter = materialNameToIndexMap_.find(tag);
if (iter == materialNameToIndexMap_.end()) {
throw ATC_Error(0,"No material named "+name+" found");
}
int index = iter->second;
return index;
}
/** access to parameter values */
bool parameter_value(const string& name, double& value,
const int imat = 0) const
{
// search owned parameters
value = 0.0;
map<string,double>::const_iterator it = parameterValues_.find(name);
if (it != parameterValues_.end()) {
value = it->second;
return true;
}
// interogate material models
bool found = materials_[imat]->get_parameter(name,value);
return found;
}
/** return fields ids and length */
virtual void get_num_fields(map<FieldName,int> & fieldSizes,
Array2D<bool> & fieldMask) const = 0;
/** is the material model linear */
virtual bool is_linear(FieldName name) {
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
bool linear = mat->linear_flux(name)
&& mat->linear_source(name)
&& mat->constant_density(name);
if (! linear) return linear;
}
return true;
}
/** is rhs linear */
virtual bool has_linear_rhs(FieldName name) {
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
bool constant = mat->linear_flux(name) && mat->linear_source(name);
if (! constant) return constant;
}
return true;
}
/** is mass matrix constant */
virtual bool has_constant_mass(FieldName name) {
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
bool constant = mat->constant_density(name);
if (! constant) return constant;
}
return true;
}
/** energy or other preserved quantity */
virtual void E_integrand(const Array<FieldName> &mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &capacity,
const int matIndex = 0) const
{
throw ATC_Error(0,"E_integrand not implemented for this PhysicsModel");
}
/** heat/momentum/energy/mass capacity used in the LHS mass matrix */
virtual void M_integrand(const Array<FieldName> &mask,
const FIELDS &fields,
FIELDS &capacity,
const int matIndex = 0) const
{
throw ATC_Error(0,"M_integrand not implemented for this PhysicsModel");
}
// flux that is integrated with N as its weight
virtual void N_integrand(const Array2D<bool> &mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &flux,
const int matIndex = 0) const
{
throw ATC_Error(0,"N_integrand not implemented for this PhysicsModel");
}
/** flux that is integrated with Grad N as its weight */
virtual void B_integrand(const Array2D<bool> & mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
GRAD_FIELDS &flux,
const int matIndex = 0) const
{
throw ATC_Error(0,"B_integrand not implemented for this PhysicsModel");
}
/** has a integrand for the N weighted integral */
virtual bool has_N_integrand() const { return false; }
/** has a integrand for the B=grad_x N weighted integral */
virtual bool has_B_integrand() const { return false; }
protected:
/** associated ATC Transfer object */
ATC_Transfer * atcTransfer_;
// parameter values
map<string, double> parameterValues_;
// material models
vector<Material *> materials_;
map<string,int> materialNameToIndexMap_;
};
};
#endif

View File

@ -1,84 +0,0 @@
#include "ATC_Transfer.h"
#include "PhysicsModelThermal.h"
#include "Material.h"
#include <string>
#include <iostream>
#include <fstream>
namespace ATC {
PhysicsModelThermal::PhysicsModelThermal(string matFileName,
ATC_Transfer * atcTransfer)
: PhysicsModel(matFileName,atcTransfer)
{
initialize();
}
PhysicsModelThermal::~PhysicsModelThermal(void)
{
}
//--------------------------------------------------------------
// initialize
//--------------------------------------------------------------
void PhysicsModelThermal::initialize(void)
{
string list[2] = {"heat_capacity",
"heat_flux"};
set<string> needs(list,list+2);
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
if (! (mat->check_registry(needs)) ) {
throw ATC_Error(0,"material does not provide all interfaces for physics");
}
}
}
//---------------------------------------------------------------------
// compute heat capacity
//---------------------------------------------------------------------
void PhysicsModelThermal::M_integrand(const Array<FieldName> &mask,
const FIELDS &fields,
FIELDS &capacity,
const int matIndex) const
{
Material* material = materials_[matIndex];
for (int n = 0; n < mask.get_length(); n++) {
if (mask(n) == TEMPERATURE) {
material->heat_capacity(fields, capacity[TEMPERATURE]);
}
}
}
//---------------------------------------------------------------------
// compute total energy
//---------------------------------------------------------------------
void PhysicsModelThermal::E_integrand(const Array<FieldName> &mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &energy,
const int matIndex) const
{
Material* material = materials_[matIndex];
for (int n = 0; n < mask.get_length(); n++) {
if (mask(n) == TEMPERATURE) {
material->thermal_energy(fields, energy[TEMPERATURE]);
}
}
}
//--------------------------------------------------------------
// compute heat flux
//--------------------------------------------------------------
void PhysicsModelThermal::B_integrand(const Array2D<bool> & mask,
const FIELDS & fields,
const GRAD_FIELDS & gradFields,
GRAD_FIELDS & flux,
const int matIndex) const
{
Material *material = materials_[matIndex];
material->heat_flux(fields, gradFields, flux[TEMPERATURE]);
}
};

View File

@ -1,53 +0,0 @@
#ifndef PHYSICS_MODEL_THERMAL_H
#define PHYSICS_MODEL_THERMAL_H
#include "PhysicsModel.h"
namespace ATC{
class PhysicsModelThermal : public PhysicsModel {
public:
// constructor (take material parameter/s)
PhysicsModelThermal(std::string matFileName,
ATC_Transfer * atcTransfer);
// destructor
virtual ~PhysicsModelThermal();
/** checks materials for necessary interfaces */
virtual void initialize(void);
virtual void get_num_fields(map<FieldName,int> & fieldSizes, Array2D<bool> & fieldMask) const
{
fieldSizes[TEMPERATURE] = 1;
fieldMask(TEMPERATURE,FLUX) = true;
}
/** heat capacity */
virtual void M_integrand(const Array<FieldName> & mask,
const FIELDS &fields,
FIELDS &capacity,
const int matIndex = 0) const;
/** energy */
virtual void E_integrand(const Array<FieldName> & mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &energy,
const int matIndex = 0) const;
/** this model has a B weighted integrand */
virtual bool has_B_integrand() const {return true;};
/** flux that is integrated with Grad N as its weight */
virtual void B_integrand(const Array2D<bool> & mask,
const FIELDS & fields,
const GRAD_FIELDS & grad_fields,
GRAD_FIELDS & flux,
const int matIndex = 0) const;
};
};
#endif

View File

@ -1,123 +0,0 @@
#include "PhysicsModelTwoTemperature.h"
#include "Material.h"
#include <string>
#include <iostream>
#include <fstream>
namespace ATC {
//==============================================================
// Class PhysicsModelTwoTemperature
//==============================================================
//--------------------------------------------------------------
// Constructor
//--------------------------------------------------------------
PhysicsModelTwoTemperature::PhysicsModelTwoTemperature(string matFileName,
ATC_Transfer * atcTransfer)
: PhysicsModel(matFileName,atcTransfer)
{
initialize();
}
//--------------------------------------------------------------
// Destructor
//---------------------------------------------------------------------
PhysicsModelTwoTemperature::~PhysicsModelTwoTemperature(void)
{}
//---------------------------------------------------------------------
// intialization
//---------------------------------------------------------------------
void PhysicsModelTwoTemperature::initialize(void)
{
string list[5] = {"heat_capacity",
"electron_heat_capacity",
"heat_flux",
"electron_heat_flux",
"electron_phonon_exchange"};
set<string> needs(list,list+5);
vector< Material* >::iterator iter;
for (iter = materials_.begin(); iter != materials_.end(); iter++) {
Material * mat = *iter;
if (! (mat->check_registry(needs)) ) {
throw ATC_Error(0,"material " + mat->label() + " does not provide all interfaces for physics");
}
}
}
//---------------------------------------------------------------------
// compute energy
//---------------------------------------------------------------------
void PhysicsModelTwoTemperature::E_integrand(const Array<FieldName> &mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &energy,
const int matIndex) const
{
Material* material = materials_[matIndex];
for (int n = 0; n < mask.get_length(); n++) {
if (mask(n) == TEMPERATURE) {
material->thermal_energy(fields, energy[TEMPERATURE]);
}
else if (mask(n) == ELECTRON_TEMPERATURE) {
material->electron_thermal_energy(fields, energy[ELECTRON_TEMPERATURE]);
}
}
}
//---------------------------------------------------------------------
// compute heat capacities
//---------------------------------------------------------------------
void PhysicsModelTwoTemperature::M_integrand(const Array<FieldName> &mask,
const FIELDS &fields,
FIELDS &capacity,
const int matIndex) const
{
Material* material = materials_[matIndex];
for (int n = 0; n < mask.get_length(); n++) {
if (mask(n) == TEMPERATURE) {
material->heat_capacity(fields, capacity[TEMPERATURE]);
}
else if (mask(n) == ELECTRON_TEMPERATURE) {
material->electron_heat_capacity(fields, capacity[ELECTRON_TEMPERATURE]);
}
}
}
//---------------------------------------------------------------------
// compute heat fluxes
//---------------------------------------------------------------------
void PhysicsModelTwoTemperature::B_integrand(const Array2D<bool> & mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
GRAD_FIELDS &flux,
const int matIndex) const
{
Material * material = materials_[matIndex];
if (mask(TEMPERATURE,FLUX)) {
material->heat_flux(fields, grad_fields, flux[TEMPERATURE]);
}
if (mask(ELECTRON_TEMPERATURE,FLUX)) {
material->electron_heat_flux(fields, grad_fields, flux[ELECTRON_TEMPERATURE]);
}
}
//---------------------------------------------------------------------
// compute exchange fluxes
//---------------------------------------------------------------------
void PhysicsModelTwoTemperature::N_integrand(const Array2D<bool> &mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &flux,
const int matIndex) const
{
Material * material = materials_[matIndex];
FIELD exchange_flux;
material->electron_phonon_exchange(fields, exchange_flux);
if (mask(TEMPERATURE,SOURCE)) {
flux[TEMPERATURE] = exchange_flux;
}
if (mask(ELECTRON_TEMPERATURE,SOURCE)) {
flux[ELECTRON_TEMPERATURE] = -1.*exchange_flux;
}
}
}// end namespace

View File

@ -1,71 +0,0 @@
#ifndef PHYSICS_MODEL_TWO_TEMPERATURE_H
#define PHYSICS_MODEL_TWO_TEMPERATURE_H
// included headers
#include "PhysicsModel.h"
namespace ATC{
class PhysicsModelTwoTemperature : public PhysicsModel {
/** system:
\dot T_e = diffusion_e + exchange_e
\dot T_p = diffusion_p + exchange_p
*/
public:
// constructor (take material parameter/s)
PhysicsModelTwoTemperature(string matFileName,
ATC_Transfer * atcTransfer);
// destructor
virtual ~PhysicsModelTwoTemperature();
/** checks materials for necessary interfaces */
virtual void initialize(void);
virtual void get_num_fields(map<FieldName,int> & fieldSizes,
Array2D<bool> & fieldMask) const
{
fieldSizes[TEMPERATURE] = 1; fieldSizes[ELECTRON_TEMPERATURE] = 1;
fieldMask(ELECTRON_TEMPERATURE,FLUX) = true;
fieldMask(ELECTRON_TEMPERATURE,SOURCE) = true;
}
/** energy */
virtual void E_integrand(const Array<FieldName> & mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &energy,
const int matIndex = 0) const;
/** capacity that used to form the mass matrix */
virtual void M_integrand(const Array<FieldName> & mask,
const FIELDS &fields,
FIELDS &flux,
const int matIndex = 0) const;
/** this model has a B weighted integrand */
virtual bool has_B_integrand() const {return true;}
/** flux that is integrated with Grad N as its weight */
virtual void B_integrand(const Array2D<bool> & mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
GRAD_FIELDS &flux,
const int matIndex = 0) const;
/** this model has a N weighted integrand */
virtual bool has_N_integrand() const {return true;}
/** flux that is integrated with N as its weight */
virtual void N_integrand(const Array2D<bool> &mask,
const FIELDS &fields,
const GRAD_FIELDS &grad_fields,
FIELDS &flux,
const int matIndex = 0) const;
};
}; // end namespace
#endif

View File

@ -1,442 +0,0 @@
#include "PrescribedDataManager.h"
#include "FE_Engine.h"
#include "ATC_Error.h"
#include <set>
namespace ATC {
//-------------------------------------------------------------------------
// PrescribedDataManager
//-------------------------------------------------------------------------
PrescribedDataManager::PrescribedDataManager
(FE_Engine * feEngine,
const map<FieldName,int> & fieldSize) :
feEngine_(feEngine), fieldSizes_(fieldSize)
{
// construct & initialize internal data
nNodes_ = feEngine_->get_nNodes();
nElems_ = feEngine_->get_nElements();
map<FieldName,int>::const_iterator field;
for (field = fieldSizes_.begin(); field!=fieldSizes_.end(); field++) {
FieldName thisField = field->first;
int thisSize = field->second;
// nodal ics & essential bcs
ics_[thisField].reset(nNodes_,thisSize);
bcs_[thisField].reset(nNodes_,thisSize);
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int idof = 0; idof < thisSize ; ++idof) {
ics_[thisField](inode,idof) = NULL;
bcs_[thisField](inode,idof) = NULL;
}
}
// element based sources
elementSources_[thisField].reset(nElems_,thisSize);
for (int ielem = 0; ielem < nElems_ ; ++ielem) {
for (int idof = 0; idof < thisSize ; ++idof) {
elementSources_[thisField](ielem,idof) = NULL;
}
}
}
}
//-------------------------------------------------------------------------
// ~PrescribedDataManager
//-------------------------------------------------------------------------
PrescribedDataManager::~PrescribedDataManager()
{
}
//-------------------------------------------------------------------------
// add_field
//-------------------------------------------------------------------------
void PrescribedDataManager::add_field(FieldName fieldName, int size)
{
// check to see if field exists
if (fieldSizes_.find(fieldName) == fieldSizes_.end()) return;
// construct & initialize internal data
nNodes_ = feEngine_->get_nNodes();
nElems_ = feEngine_->get_nElements();
// nodal ics & essential bcs
ics_[fieldName].reset(nNodes_,size);
bcs_[fieldName].reset(nNodes_,size);
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int idof = 0; idof < size ; ++idof) {
ics_[fieldName](inode,idof) = NULL;
bcs_[fieldName](inode,idof) = NULL;
}
}
// element based sources
elementSources_[fieldName].reset(nElems_,size);
for (int ielem = 0; ielem < nElems_ ; ++ielem) {
for (int idof = 0; idof < size ; ++idof) {
elementSources_[fieldName](ielem,idof) = NULL;
}
}
}
//-------------------------------------------------------------------------
// remove_field
//-------------------------------------------------------------------------
void PrescribedDataManager::remove_field(FieldName fieldName)
{
// check to see if field exists
if (fieldSizes_.find(fieldName) == fieldSizes_.end())
return;
// delete field in maps
fieldSizes_.erase(fieldName);
ics_.erase(fieldName);
bcs_.erase(fieldName);
elementSources_.erase(fieldName);
}
//-------------------------------------------------------------------------
// fix_initial_field
//-------------------------------------------------------------------------
void PrescribedDataManager::fix_initial_field
(const string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f)
{
using std::set;
set<int> nodeSet = (feEngine_->get_feMesh())->get_nodeset(nodesetName);
set<int>::const_iterator iset;
for (iset = nodeSet.begin(); iset != nodeSet.end(); iset++) {
int inode = *iset;
ics_[thisField](inode,thisIndex) = (XT_Function*) f; // NOTE const cast?
}
}
//-------------------------------------------------------------------------
// fix_field
//-------------------------------------------------------------------------
void PrescribedDataManager::fix_field
(const string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f)
{
using std::set;
// fix fields
set<int> nodeSet = (feEngine_->get_feMesh())->get_nodeset(nodesetName);
set<int>::const_iterator iset;
for (iset = nodeSet.begin(); iset != nodeSet.end(); iset++) {
int inode = *iset;
bcs_[thisField](inode,thisIndex) = (XT_Function*) f;
}
}
//-------------------------------------------------------------------------
// unfix_field
//-------------------------------------------------------------------------
void PrescribedDataManager::unfix_field
(const string nodesetName,
const FieldName thisField,
const int thisIndex)
{
using std::set;
set<int> nodeSet = (feEngine_->get_feMesh())->get_nodeset(nodesetName);
set<int>::const_iterator iset;
for (iset = nodeSet.begin(); iset != nodeSet.end(); iset++) {
int inode = *iset;
bcs_[thisField](inode,thisIndex) = NULL;
}
}
//-------------------------------------------------------------------------
// fix_flux
//-------------------------------------------------------------------------
void PrescribedDataManager::fix_flux
(const string facesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f)
{
const set< pair <int,int> > * fset
= & ( (feEngine_->get_feMesh())->get_faceset(facesetName));
set< pair<int,int> >::const_iterator iset;
for (iset = fset->begin(); iset != fset->end(); iset++) {
pair<int,int> face = *iset;
// allocate, if necessary
Array < XT_Function * > & dof = faceSources_[thisField][face];
if (dof.get_length() == 0) {
int ndof = (fieldSizes_.find(thisField))->second;
dof.reset(ndof);
for(int i = 0; i < ndof; i++) dof(i) = NULL;
}
dof(thisIndex) = (XT_Function*) f;
}
}
//-------------------------------------------------------------------------
// unfix_flux
//-------------------------------------------------------------------------
void PrescribedDataManager::unfix_flux
(const string facesetName,
const FieldName thisField,
const int thisIndex)
{
const set< pair <int,int> > * fset
= & ( (feEngine_->get_feMesh())->get_faceset(facesetName));
set< pair<int,int> >::const_iterator iset;
for (iset = fset->begin(); iset != fset->end(); iset++) {
pair<int,int> face = *iset;
Array < XT_Function * > & dof = faceSources_[thisField][face];
dof(thisIndex) = NULL;
}
}
//-------------------------------------------------------------------------
// fix_source
//-------------------------------------------------------------------------
void PrescribedDataManager::fix_source
(const string elemsetName,
const FieldName thisField,
const int thisIndex,
const XT_Function *f)
{
using std::set;
set<int> elemSet = (feEngine_->get_feMesh())->get_elementset(elemsetName);
set<int>::const_iterator iset;
for (iset = elemSet.begin(); iset != elemSet.end(); iset++) {
int ielem = *iset;
// fix source
elementSources_[thisField](ielem,thisIndex) = (XT_Function*) f;
}
}
//-------------------------------------------------------------------------
// unfix_source
//-------------------------------------------------------------------------
void PrescribedDataManager::unfix_source
(const string elemsetName,
const FieldName thisField,
const int thisIndex)
{
using std::set;
set<int> elemSet = (feEngine_->get_feMesh())->get_elementset(elemsetName);
set<int>::const_iterator iset;
for (iset = elemSet.begin(); iset != elemSet.end(); iset++) {
int ielem = *iset;
elementSources_[thisField](ielem,thisIndex) = NULL;
}
}
//-------------------------------------------------------------------------
// set_initial_conditions
//-------------------------------------------------------------------------
void PrescribedDataManager::set_initial_conditions(const double t,
FIELDS &fields,
FIELDS &dot_fields,
FIELDS &ddot_fields,
FIELDS &dddot_fields)
{
map<FieldName,int>::const_iterator field;
for (field = fieldSizes_.begin(); field!=fieldSizes_.end(); field++) {
FieldName thisField = field->first;
int thisSize = field->second;
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
XT_Function *f = ics_[thisField](inode,thisIndex);
if (!f) f = bcs_[thisField](inode,thisIndex);
if (f)
{
DENS_VEC coords(3);
coords = (feEngine_->get_feMesh())->nodal_coordinates(inode);
double *x = coords.get_ptr();
fields [thisField](inode,thisIndex) = f->f(x,t);
dot_fields [thisField](inode,thisIndex) = f->dfdt(x,t);
ddot_fields [thisField](inode,thisIndex) = f->ddfdt(x,t);
dddot_fields[thisField](inode,thisIndex) = f->dddfdt(x,t);
}
else throw ATC_Error(0,"all initial conditions have not been defined");
}
}
}
}
//-------------------------------------------------------------------------
// set_fixed_fields
//-------------------------------------------------------------------------
void PrescribedDataManager::set_fixed_fields(const double t,
FIELDS &fields,
FIELDS &dot_fields,
FIELDS &ddot_fields,
FIELDS &dddot_fields)
{
map<FieldName,int>::const_iterator field;
for (field = fieldSizes_.begin(); field!=fieldSizes_.end(); field++) {
FieldName thisField = field->first;
int thisSize = field->second;
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
XT_Function * f = bcs_[thisField](inode,thisIndex);
if (f) {
DENS_VEC coords(3);
coords = (feEngine_->get_feMesh())->nodal_coordinates(inode);
double * x = coords.get_ptr();
FIELD * myField = & fields[thisField];
fields [thisField](inode,thisIndex) = f->f(x,t);
dot_fields [thisField](inode,thisIndex) = f->dfdt(x,t);
ddot_fields [thisField](inode,thisIndex) = f->ddfdt(x,t);
dddot_fields[thisField](inode,thisIndex) = f->dddfdt(x,t);
}
}
}
}
}
//-------------------------------------------------------------------------
// set_fixed_field
//-------------------------------------------------------------------------
void PrescribedDataManager::set_fixed_field(
const double t,
const FieldName & fieldName,
DENS_MAT & fieldMatrix)
{
map<FieldName,int>::iterator fieldSizeIter = fieldSizes_.find(fieldName);
if (fieldSizeIter == fieldSizes_.end()) {
throw ATC_Error(0, "Unrecognized FieldName in PrescribedDataManager::set_fixed_field()");
}
int thisSize = fieldSizeIter->second;
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
XT_Function * f = bcs_[fieldName](inode,thisIndex);
if (f) {
DENS_VEC coords(3);
coords = (feEngine_->get_feMesh())->nodal_coordinates(inode);
fieldMatrix(inode,thisIndex) = f->f(coords.get_ptr(),t);
}
}
}
}
//-------------------------------------------------------------------------
// set_fixed_dfield
//-------------------------------------------------------------------------
void PrescribedDataManager::set_fixed_dfield(
const double t,
const FieldName & fieldName,
DENS_MAT & dfieldMatrix)
{
map<FieldName,int>::iterator fieldSizeIter = fieldSizes_.find(fieldName);
if (fieldSizeIter == fieldSizes_.end()) {
throw ATC_Error(0, "Unrecognized FieldName in PrescribedDataManager::set_fixed_dfield()");
}
int thisSize = fieldSizeIter->second;
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
XT_Function * f = bcs_[fieldName](inode,thisIndex);
if (f) {
DENS_VEC coords(3);
coords = (feEngine_->get_feMesh())->nodal_coordinates(inode);
dfieldMatrix(inode,thisIndex) = f->dfdt(coords.get_ptr(),t);
}
}
}
}
//-------------------------------------------------------------------------
// set_sources
//-------------------------------------------------------------------------
void PrescribedDataManager::set_sources
(double t,
FIELDS & sources)
{
// zero
Array<bool> fieldMask(NUM_FIELDS);
fieldMask = false;
map<FieldName,int>::const_iterator field;
for (field = fieldSizes_.begin(); field!=fieldSizes_.end(); field++) {
FieldName thisField = field->first;
fieldMask(thisField) = true;
int thisSize = field->second;
sources[thisField].reset(nNodes_,thisSize);
}
// compute boundary fluxes
feEngine_->add_fluxes(fieldMask,t,faceSources_,sources);
// compute internal sources
feEngine_->add_sources(fieldMask,t,elementSources_,sources);
// mask out nodes with essential bcs
for (field = fieldSizes_.begin(); field!=fieldSizes_.end(); field++) {
FieldName thisField = field->first;
int thisSize = field->second;
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
XT_Function * f = bcs_[thisField](inode,thisIndex);
if (f) {
sources[thisField](inode,thisIndex) = 0.0;
}
}
}
}
}
//-------------------------------------------------------------------------
// print
//-------------------------------------------------------------------------
void PrescribedDataManager::print(void)
{
// print and check consistency
enum dataType {FREE=0,FIELD,SOURCE};
Array2D < int > bcTypes;
Array <int> conn;
map<FieldName,int>::const_iterator field;
XT_Function * f;
for (field = fieldSizes_.begin(); field!=fieldSizes_.end(); field++) {
FieldName thisField = field->first;
int thisFieldSize = field->second;
string fieldName = field_to_string(thisField);
int thisSize = field->second;
bcTypes.reset(nNodes_,thisSize);
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
f = bcs_[thisField](inode,thisIndex);
if (f) { bcTypes(inode,thisIndex) = FIELD; }
else { bcTypes(inode,thisIndex) = FREE; }
}
}
// FIXED has higher precidence than SOURCE
for (int ielem = 0; ielem < nElems_ ; ++ielem) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
f = elementSources_[thisField](ielem,thisIndex);
if (f) {
feEngine_->element_connectivity(ielem,conn);
for (int i = 0; i < conn.get_length() ; ++i) {
int inode = conn(i);
if (bcTypes(inode,thisIndex) != FIELD)
{ bcTypes(inode,thisIndex) = SOURCE; }
}
}
}
}
map < pair<int,int>, Array < XT_Function * > > & fset
= faceSources_[thisField];
map < pair<int,int>, Array < XT_Function * > > ::const_iterator iset;
for (iset = fset.begin(); iset != fset.end(); iset++) {
pair<int,int> face = iset->first;
Array < XT_Function * > fs = iset->second;
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
f = fs(thisIndex);
if (f) {
feEngine_->face_connectivity(face,conn);
for (int i = 0; i < conn.get_length() ; ++i) {
int inode = conn(i);
if (bcTypes(inode,thisIndex) != FIELD)
{ bcTypes(inode,thisIndex) = SOURCE; }
}
}
}
}
for (int inode = 0; inode < nNodes_ ; ++inode) {
for (int thisIndex = 0; thisIndex < thisSize ; ++thisIndex) {
cout << "node: " << inode << " " << fieldName;
if (thisFieldSize > 1) { cout << " " << thisIndex; }
f = ics_[thisField](inode,thisIndex);
if (f) { cout << " IC"; }
if (bcTypes(inode,thisIndex) == FIELD ) {cout << " FIXED"; }
else if (bcTypes(inode,thisIndex) == SOURCE) {cout << " SOURCE"; }
cout << "\n";
}
}
}
}
} // end namespace

View File

@ -1,157 +0,0 @@
#ifndef PRESCRIBED_DATA_MANAGER_H
#define PRESCRIBED_DATA_MANAGER_H
// manager for initial conditions, essential/natural "boundary" conditions
// and sources
// to do:
// handle no sources, time-independent sources
// prescribed surface sources
#include <vector>
#include <map>
#include <string>
#include "XT_Function.h"
#include "PhysicsModel.h"
#include "FE_Element.h"
#include "Array.h"
#include "Array2D.h"
#include "FE_Engine.h"
//clase FE_Engine
namespace ATC {
using std::vector;
using std::pair;
using std::map;
class PrescribedDataManager {
public:
/** exclusive conditions: free | fixed field | flux or domain source */
//enum Bc_Type {FREE=0,FIELD,SOURCE};
PrescribedDataManager(FE_Engine * feEngine,
const map<FieldName,int> & fieldSize);
~PrescribedDataManager();
/** add/remove a field */
void add_field(FieldName fieldName, int size);
void remove_field(FieldName fieldName);
/** direct access to ics */
map < FieldName, Array2D < XT_Function * > > *
get_ics(void) { return & ics_; }
const Array2D < XT_Function * > *
get_ics(FieldName fieldName) { return & ics_[fieldName]; }
/** direct access to bcs */
map < FieldName, Array2D < XT_Function * > > *
get_bcs(void) { return & bcs_; }
const Array2D < XT_Function * > *
get_bcs(FieldName fieldName) { return & bcs_[fieldName]; }
/** query initial state */
bool is_initially_fixed(const int node,
const FieldName thisField,
const int thisIndex=0) const
{
return ((ics_.find(thisField)->second))(node,thisIndex) ? true : false ;
}
/** query state */
bool is_fixed(const int node,
const FieldName thisField,
const int thisIndex=0) const
{
return ((bcs_.find(thisField)->second))(node,thisIndex) ? true : false ;
}
/** set initial field values */
void fix_initial_field (const string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
/** un/set field values at fixed nodes */
void fix_field (const string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void unfix_field (const string nodesetName,
const FieldName thisField,
const int thisIndex);
/** un/set fluxes */
void fix_flux (const string facesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void unfix_flux(const string facesetName,
const FieldName thisField,
const int thisIndex);
/** un/set sources */
void fix_source(const string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void unfix_source(const string nodesetName,
const FieldName thisField,
const int thisIndex);
/** get initial conditions */
void set_initial_conditions(const double time,
FIELDS & fields,
FIELDS & dot_fields,
FIELDS & ddot_fields,
FIELDS & dddot_fields);
/** get "boundary" conditions on fields */
void set_fixed_fields(const double time,
FIELDS & fields,
FIELDS & dot_fields,
FIELDS & ddot_fields,
FIELDS & dddot_fields);
/** get "boundary" conditions on a single field */
void set_fixed_field(const double time,
const FieldName & fieldName,
DENS_MAT & fieldMatrix);
/** get "boundary" conditions on a single time derivative field */
void set_fixed_dfield(const double time,
const FieldName & fieldName,
DENS_MAT & dfieldMatrix);
/** get "sources" (flux and sources: divided by leading coef of ODE) */
void set_sources(const double time,
FIELDS & sources);
/** debugging status output */
void print(void);
private:
/** number of nodes */
int nNodes_;
/** number of elements */
int nElems_;
/** names and sizes of fields */
map<FieldName,int> fieldSizes_;
/** access to all the FE computations */
FE_Engine * feEngine_;
// node numbering & dof numbering : contiguous
// fieldname & bc_type : types/enums
/** ics : XT_Function * f = ics_[field](inode,idof) */
map < FieldName, Array2D < XT_Function * > > ics_;
/** bcs: essential bcs XT_Function * f = bcs_[field][face](idof) */
map < FieldName, Array2D < XT_Function * > > bcs_;
/** sources : XT_Function * f = faceSources_[field][face](idof) */
map < FieldName, map < pair <int, int>, Array < XT_Function * > > >
faceSources_;
/** sources : XT_Function * f = elementSources_[field](ielem,idof) */
map < FieldName, Array2D < XT_Function * > > elementSources_;
};
}
#endif

View File

@ -1,50 +0,0 @@
/** Quadrature : creat Gaussian quadrature lists */
#ifndef QUADRATURE_H
#define QUADRATURE_H
using namespace std;
static const int line_ngauss = 10;
static double line_xg[line_ngauss], line_wg[line_ngauss];
/** domain of integration is -1 to 1 */
static void set_line_quadrature(int ng, double* xg, double* wg)
{
/** integration schemes : 3, 4, 5, 10 point Gauss */
if (ng == 3) {
xg[0] = 0.0; wg[0] = 8.0/9.0;
xg[1] = -sqrt(3.0/5.0); wg[1] = 5.0/9.0;
xg[2] = sqrt(3.0/5.0); wg[2] = 5.0/9.0;
}
else if (ng == 4) {
xg[0] = -sqrt((3.0/7.0)-(sqrt(120.0)/35.0)); wg[0] = (1.0/2.0)+(5.0/(3.0*sqrt(120.0)));
xg[1] = sqrt((3.0/7.0)-(sqrt(120.0)/35.0)); wg[1] = (1.0/2.0)+(5.0/(3.0*sqrt(120.0)));
xg[2] = -sqrt((3.0/7.0)+(sqrt(120.0)/35.0)); wg[2] = (1.0/2.0)-(5.0/(3.0*sqrt(120.0)));
xg[3] = sqrt((3.0/7.0)+(sqrt(120.0)/35.0)); wg[3] = (1.0/2.0)-(5.0/(3.0*sqrt(120.0)));
}
else if (ng == 5) {
xg[0] = 0.0; wg[0] = 0.5688888888888889;
xg[1] = -sqrt((35.0-sqrt(280.0))/63.0); wg[1] = 0.4786286704993658;
xg[2] = sqrt((35.0-sqrt(280.0))/63.0); wg[2] = 0.4786286704993658;
xg[3] = -sqrt((35.0+sqrt(280.0))/63.0); wg[3] = 0.2369268850561891;
xg[4] = sqrt((35.0+sqrt(280.0))/63.0); wg[4] = 0.2369268850561891;
}
else if (ng == 10) {
xg[0] = -0.14887434; wg[0] = 0.29552422;
xg[1] = 0.14887434; wg[1] = 0.29552422;
xg[2] = -0.43339539; wg[2] = 0.26926672;
xg[3] = 0.43339539; wg[3] = 0.26926672;
xg[4] = -0.67940957; wg[4] = 0.21908636;
xg[5] = 0.67940957; wg[5] = 0.21908636;
xg[6] = -0.86506337; wg[6] = 0.14945135;
xg[7] = 0.86506337; wg[7] = 0.14945135;
xg[8] = -0.97390653; wg[8] = 0.06667134;
xg[9] = 0.97390653; wg[9] = 0.06667134;
}
else { cout << "Invalid choice of number of Gauss points for Quadrature" << endl; }
//else { throw ATC_Error(0,"Invalid choice of number of Gauss points for Quadrature"); }
return;
};
#endif

View File

@ -1,147 +0,0 @@
#include "Solver.h"
#include <limits>
#include <cmath>
#include <iostream>
namespace ATC {
// Utility functions used by solvers, but not globally accessible.
static const double PI_OVER_3 = acos(-1.0)*(1.0/3.0);
static bool is_zero(double x)
{
static double GT_ZERO = 1.0e2*std::numeric_limits<double>::epsilon();
static double LT_ZERO = -GT_ZERO;
return x>LT_ZERO && x<GT_ZERO;
}
static double sign(double x)
{
static double s[] = {-1.0,1.0};
return s[x>0];
}
// Linear solver
int solve_linear(double c[2], double x0[1])
{
if (c[1] == 0) return 0; // constant function
*x0 = -c[0] / c[1];
return 1;
}
// Quadratic solver
int solve_quadratic(double c[3], double x0[2])
{
if (is_zero(c[2])) return solve_linear(c, x0);
const double ainv = 1.0/c[2]; // ax^2 + bx + c = 0
const double p = 0.5 * c[1] * ainv; // -b/2a
const double q = c[0] * ainv; // c/a
double D = p*p-q;
if (is_zero(D)) { // quadratic has one repeated root
x0[0] = -p;
return 1;
}
if (D > 0) { // quadratic has two real roots
D = sqrt(D);
x0[0] = D - p;
x0[1] = -D - p;
return 2;
}
return 0; // quadratic has no real roots
}
// Cubic solver
int solve_cubic(double c[4], double x0[3])
{
int num_roots;
if (is_zero(c[3])) return solve_quadratic(c, x0);
// normalize to x^3 + Ax^2 + Bx + C = 0
const double c3inv = 1.0/c[3];
const double A = c[2] * c3inv;
const double B = c[1] * c3inv;
const double C = c[0] * c3inv;
// substitute x = t - A/3 so t^3 + pt + q = 0
const double A2 = A*A;
const double p = (1.0/3.0)*((-1.0/3.0)*A2 + B);
const double q = 0.5*((2.0/27.0)*A*A2 - (1.0/3.0)*A*B + C);
// Cardano's fomula
const double p3 = p*p*p;
const double D = q*q + p3;
if (is_zero(D)) {
if (is_zero(q)) { // one triple soln
x0[0] = 0.0;
num_roots = 1;
}
else { // one single and one double soln
const double u = pow(fabs(q), 1.0/3.0)*sign(q);
x0[0] = -2.0*u;
x0[1] = u;
num_roots = 2;
}
}
else {
if (D < 0.0) { // three real roots
const double phi = 1.0/3.0 * acos(-q/sqrt(-p3));
const double t = 2.0 * sqrt(-p);
x0[0] = t * cos(phi);
x0[1] = -t * cos(phi + PI_OVER_3);
x0[2] = -t * cos(phi - PI_OVER_3);
num_roots = 3;
}
else { // one real root
const double sqrt_D = sqrt(D);
const double u = pow(sqrt_D + fabs(q), 1.0/3.0);
if (q > 0) x0[0] = -u + p / u;
else x0[0] = u - p / u;
num_roots = 1;
}
}
double sub = (1.0/3.0)*A;
for (int i=0; i<num_roots; i++) x0[i] -= sub;
return num_roots;
}
// Testing code
#if 0
//* runs test cases for cubic roots for all branches
void test()
{
double x[3];
// repeated root
double c3r[] = { 4.0, -12.0, 12.0, -4.0};
print_soln(solve_cubic(c3r,x), 4, c3r, x);
std::cout << "SOLN: x = {1.0}\n";
// one real root
double c31[] = {1.0, 2.0, 3.0, 4.0};
print_soln(solve_cubic(c31,x), 4, c31, x);
std::cout << "SOLN: x = {-0.60583}\n";
// two real roots
double c32[] = {18.0, -3.0, -4.0, 1.0,};
print_soln(solve_cubic(c32,x), 4, c32, x);
std::cout << "SOLN: x = {-2.0, 3.0}\n";
// three real roots
double c33[] = {-6.0, 11.0, -6.0, 1.0};
print_soln(solve_cubic(c33,x), 4, c33, x);
std::cout << "SOLN: x = {3.0, 2.0, 1.0}\n";
}
//* Outputs the solution to the screen.
void print_soln(int N, int NC, double *c, double *x0)
{
std::cout << N << " real root" << (N>1?"s":"") << " of: ";
switch (NC) {
case 4: std::cout << c[3] << "x^3+";
case 3: std::cout << c[2] << "x^2+";
case 2: std::cout << c[1] << "x+";
case 1: std::cout << c[0];
default: std::cout << " are ";
}
std::cout << "x = {";
for (int i=0; i<N; i++) {
if (i) std::cout << ", ";
std::cout << x0[i];
}
std::cout << "}\n";
}
#endif
}

View File

@ -1,13 +0,0 @@
#ifndef SOLVER_H
#define SOLVER_H
namespace ATC {
//* Solves a linear system, returns the number of roots found.
int solve_linear(double c[2], double x0[1]);
//* Solves a quadratic system, returns the number of roots found.
int solve_quadratic(double c[3], double x0[2]);
//* Solves a cubic system, returns the number of roots found.
int solve_cubic(double c[4], double x0[3]);
}
#endif

View File

@ -1,930 +0,0 @@
#ifndef SPARSEMATRIX_INL_H
#define SPARSEMATRIX_INL_H
template <typename T>
TRI_COORD<T>::TRI_COORD(unsigned row, unsigned col) : i(row), j(col) {}
template <typename T>
TRI_COORD<T>::TRI_COORD(unsigned row, unsigned col, T val, bool add_to)
: i(row), j(col), v(val), add(add_to) {}
// General flat index by value operator (by nth nonzero)
template <typename T> inline T SparseMatrix<T>::operator[](INDEX i) const
{
VICK(i); return _val[i];
}
// General flat index by reference operator (by nth nonzero)
template <typename T> inline T& SparseMatrix<T>::operator[](INDEX i)
{
VICK(i); return _val[i];
}
template<typename T>
T SparseMatrix<T>::_zero = T(0);
//-----------------------------------------------------------------------------
// triplet comparison operator returns true if x < y
//-----------------------------------------------------------------------------
template <typename T>
bool triplet_comparision(const TRI_COORD<T> &x, const TRI_COORD<T> &y)
{
const bool row_less = (x.i) < (y.i);
const bool row_equal = (x.i) == (y.i);
const bool col_less = (x.j) < (y.j);
return (row_less || (row_equal && col_less));
}
//-----------------------------------------------------------------------------
// triplet comparison operator returns true if x == y
//-----------------------------------------------------------------------------
template <typename T>
bool triplets_equal(const TRI_COORD<T> &x, const TRI_COORD<T> &y)
{
return x.i==y.i && x.j==y.j;
}
//-----------------------------------------------------------------------------
// multiply sparse matrix by a vector
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<T> operator*(const SparseMatrix<T> &A, const Vector<T>& x)
{
SparseMatrix<T>::compress(A);
GCK(A, x, A.nCols()!=x.size(), "SparseMatrix * Vector")
DenseVector<T> y(A.nRows(), true);
INDEX i, j;
for (i=0; i<A._nRowsCRS; i++)
for (j=A._ia[i]; j<A._ia[i+1]; j++)
y(i) += A._val[j]*x(A._ja[j]);
return y;
}
//-----------------------------------------------------------------------------
// multiply a vector by a sparse matrix
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<T> operator*(const Vector<T>& x, const SparseMatrix<T> &A)
{
return A.transMat(x);
}
//-----------------------------------------------------------------------------
// multiply sparse matrix by dense matrix
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> operator*(const SparseMatrix<T> &A, const Matrix<T>& D)
{
GCK(A, D, A.nCols()!=D.nRows(),"SparseMatrix * DenseMatrix")
DenseMatrix<T> C(A.nRows(), D.nCols(), true); // initialized to zero
const INDEX J = D.nCols();
INDEX i, ik, j, k;
for (i=0; i<A._nRowsCRS; i++)
for (ik=A._ia[i]; ik<A._ia[i+1]; ik++)
for (j=0; j<J; j++)
C(i, j) += A._val[ik]*D(A._ja[ik],j); // C(i,j) = S(i,k) * D(k, j)
return C;
}
//-----------------------------------------------------------------------------
// multiply sparse matrix by a diagonal matrix - scales each column
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T> operator*(const SparseMatrix<T> &A, const DiagonalMatrix<T>& D)
{
GCK(A, D, A.nCols()!=D.nRows(),"SparseMatrix * DiagonalMatrix")
SparseMatrix<T> C(A); // C has same sparcity as A
// C(i,j) = A(i,k) * D(k, j) * j==k
INDEX i, ij, j;
for (i=0; i<A._nRowsCRS; i++)
for (ij=A._ia[i]; ij<A._ia[i+1]; ij++)
C[ij] = A._val[ij]*D(A._ja[ij],A._ja[ij]);
return C;
}
//-----------------------------------------------------------------------------
// multiplies two sparse matrices - assumes their output is sparse
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T> operator*(const SparseMatrix<T> &A, const SparseMatrix<T> &B)
{
SparseMatrix<T> At(A.transpose());
SparseMatrix<T>::compress(B);
GCK(A, B, A.nCols()!=B.nRows(), "SparseMatrix * SparseMatrix");
SparseMatrix<T> C(A.nRows(), B.nCols());
if (At.empty() || B.empty()) return C;
INDEX k, ki, kj;
INDEX K = std::min(At._nRowsCRS, B._nRowsCRS);
for (k=0; k<K; k++) // loop over rows of A or B (smallest)
for (ki=At._ia[k]; ki<At._ia[k+1]; ki++) // loop over row nonzeros of A
for (kj=B._ia[k]; kj<B._ia[k+1]; kj++) // loop over row nonzeros of B
C.add(At._ja[ki], B._ja[kj], At[ki]*B[kj]); // C(i,j) = At(k,i)*B(k, j)
C.compress();
return C;
}
//-----------------------------------------------------------------------------
// default constructor - creates an empty sparsematrix with specified size
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>::SparseMatrix(INDEX rows, INDEX cols)
: _val(NULL), _ia(NULL), _ja(NULL), _size(0), _nRowsCRS(0),
_nRows(rows),_nCols(cols) {}
//-----------------------------------------------------------------------------
// copy constructor
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>::SparseMatrix(const SparseMatrix<T>& C)
: _val(NULL), _ia(NULL), _ja(NULL)
{
_copy(C);
}
//-----------------------------------------------------------------------------
// copy constructor - converts from DenseMatrix
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>::SparseMatrix(const DenseMatrix<T>& C)
: _val(NULL), _ia(NULL), _ja(NULL)
{
reset(C);
}
//-----------------------------------------------------------------------------
// destructor, cleans up internal storage
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>::~SparseMatrix()
{
_delete();
}
//-----------------------------------------------------------------------------
// assigns internal storage for CRS
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::_create(INDEX size, INDEX nrows)
{
_size = size;
_nRowsCRS = nrows;
// assign memory to hold matrix
try
{
_val = (_size*nrows) ? new T [_size] : NULL;
_ia = (_size*nrows) ? new INDEX [_nRowsCRS+1] : NULL;
_ja = (_size*nrows) ? new INDEX [_size] : NULL;
}
catch (std::exception &e)
{
cout << "Could not allocate SparseMatrix of "<< _size << " nonzeros.\n";
exit(EXIT_FAILURE);
}
if (!_ia) return;
// automatically handle the ends of rowpointer
*_ia = 0; // first non-zero is the zero index
_ia[_nRowsCRS] = _size; // last row pointer is the size
}
//-----------------------------------------------------------------------------
// cleans up internal storage, but retains nRows & nCols
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::_delete()
{
vector<TRI_COORD<T> >().swap(_tri); // completely deletes _tri
delete [] _val;
delete [] _ia;
delete [] _ja;
_size = _nRowsCRS = 0;
_val = NULL;
_ia = _ja = NULL;
}
//-----------------------------------------------------------------------------
// full memory copy of C into this
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::_copy(const SparseMatrix<T> &C)
{
compress(C);
_delete();
_create(C.size(), C._nRowsCRS);
if (_size) {
std::copy(C._val, C._val+_size, _val);
std::copy(C._ja, C._ja+_size, _ja);
}
if (_nRowsCRS) {
std::copy(C._ia, C._ia+_nRowsCRS+1, _ia);
}
_nCols = C._nCols;
_nRows = C._nRows;
}
//----------------------------------------------------------------------------
// general sparse matrix assignment
//----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::_set_equal(const Matrix<T> &r)
{
this->resize(r.nRows(), r.nCols());
const Matrix<T> *ptr_r = &r;
const SparseMatrix<T> *s_ptr = dynamic_cast<const SparseMatrix<T>*>(ptr_r);
if (s_ptr) this->reset(*s_ptr);
else if (dynamic_cast<const DiagonalMatrix<T>*>(ptr_r))
for (INDEX i=0; i<r.size(); i++) set(i,i,r[i]);
else if (dynamic_cast<const DenseMatrix<T>*>(ptr_r)) this->reset(r);
else
{
cout <<"Error in general sparse matrix assignment\n";
exit(1);
}
}
//-----------------------------------------------------------------------------
// returns the first row number with a nonzero entry or -1 if no rows
//-----------------------------------------------------------------------------
template<typename T>
int SparseMatrix<T>::_first_nonzero_row_crs() const
{
if (!_nRowsCRS) return -1;
INDEX r;
for (r=0; r<_nRowsCRS; r++)
if (_ia[r+1]>0) return r;
return -1;
}
//-----------------------------------------------------------------------------
// converts T to CRS
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::compress(const SparseMatrix<T> &C)
{
const_cast<SparseMatrix<T>*>(&C)->compress();
}
//-----------------------------------------------------------------------------
// merges all the _tri triples with CRS storage
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::compress()
{
if (_tri.empty()) return;
// sort and find the number of unique triplets
const INDEX nUnique = CountUniqueTriplets();
// max number of rows in new CRS structure
const INDEX nRows = std::max((INDEX)_tri.back().i+1, _nRowsCRS);
// make a new CRS structure
INDEX *ia = new INDEX [nRows+1];
INDEX *ja = new INDEX [nUnique];
T *val = new T [nUnique];
ia[0] = 0;
INDEX i;
for (i=1; i<nRows; i++) ia[i]=~0; // ~0 is max(INDEX)
ia[nRows] = nUnique;
INDEX crs_pt, crs_row, tri_ct;
// get the first CRS and triplet coordinates (if they exist)
TRI_COORD<T> nextCRS, nextTRI(_tri[0]), next;
int first_row = _first_nonzero_row_crs();
if (first_row != -1) nextCRS = TRI_COORD<T>(first_row, _ja[0], _val[0]);
// merge sorted triplets into a new CRS structure
crs_pt = crs_row = tri_ct = 0; // initialize counters
for (i=0; i<nUnique; i++)
{
// is the next non-zero in the new triplet vector
if (tri_ct<_tri.size()
&& (triplet_comparision(nextTRI, nextCRS) || crs_pt>=_size)) {
next = nextTRI;
// advance the triplet counter, and skip voided TRIPLET entries
do tri_ct++;
while ( tri_ct<_tri.size() && !~_tri[tri_ct].j );
// if not at the end of the vector, set the next triplet
if (tri_ct<_tri.size()) nextTRI = _tri[tri_ct];
}
// is the next nonzero in the old CRS data
else if (crs_pt < _size) {
next = nextCRS;
// advance the CRS counter, skip if it was the last one
if (++crs_pt >= _size) continue;
crs_row += _ia[crs_row+1]==crs_pt; // did the row advance
nextCRS = TRI_COORD<T>(crs_row, _ja[crs_pt], _val[crs_pt]);
}
else cout << "SparseMatrix - Error in compressing CRS\n";
// add next to the new CRS structure
// is this a new row (is j>0 and is ja[j] == 0)?
if (ia[next.i]==~0) ia[next.i] = i;
ja[i] = next.j;
val[i] = next.v;
}
// sweep backwards through row pointers and check for skipped rows
for (i=nRows-1; i>0; i--) ia[i] = (ia[i]==~0) ? ia[i+1] : ia[i];
_delete();
_val = val;
_ia = ia;
_ja = ja;
_size = nUnique;
_nRowsCRS = nRows;
}
//-----------------------------------------------------------------------------
// Sorts the triplets, condenses duplicates, and returns the # of unique values
//-----------------------------------------------------------------------------
template<typename T>
INDEX SparseMatrix<T>::CountUniqueTriplets()
{
std::sort(_tri.begin(), _tri.end(), triplet_comparision<T>);
INDEX i, nUnique=1 + _size;
// count unique entries
for (i=_tri.size()-1; i>0; i--) { // for all new triplets
if (triplets_equal(_tri[i-1], _tri[i])) { // previous has same index?
if (_tri[i].add) _tri[i-1].v += _tri[i].v; // add to previous
else _tri[i-1].v = _tri[i].v; // replace previous
_tri[i].j = ~0; // void this entry's col
}
else nUnique++;
}
return nUnique;
}
//-----------------------------------------------------------------------------
// Index by copy operator - return zero if not found
//-----------------------------------------------------------------------------
template<typename T>
T SparseMatrix<T>::operator()(INDEX i, INDEX j) const
{
MICK(i,j); // Matrix Index ChecKing
compress(*this);
if (i>=_nRowsCRS || _ia[i+1]==_ia[i]) return 0.0;
unsigned f = std::lower_bound(_ja+_ia[i], _ja+_ia[i+1]-1, j) - _ja;
if (f>=_ia[i] && f<_ia[i+1] && _ja[f] == j) return _val[f];
return 0.0;
}
//-----------------------------------------------------------------------------
// Index by reference operator - add to _tri if not found
//-----------------------------------------------------------------------------
template<typename T>
T& SparseMatrix<T>::operator()(INDEX i, INDEX j)
{
compress(*this);
MICK(i,j); // Matrix Index ChecKing
if (i < _nRowsCRS && _ia[i+1]>_ia[i]) {
unsigned f = std::lower_bound(_ja+_ia[i], _ja+_ia[i+1]-1, j) - _ja;
if (f>=_ia[i] && f<_ia[i+1] && _ja[f] == j) return _val[f];
}
// NEVER use index operator as LHS to modify values not already in the
// sparcity pattern - the crude check below will only catch this on the
// second infraction.
if (_zero != T(0)) cout << "Use add or set for SparseMatrix\n";
return _zero;
}
//-----------------------------------------------------------------------------
// Sets (i,j) to value
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::set(INDEX i, INDEX j, T v)
{
MICK(i,j); // Matrix Index ChecKing
if (i < _nRowsCRS)
{
const int loc = Utility::SearchSorted(_ja, j, _ia[i], _ia[i+1]);
if (loc >=0 )
{
_val[loc] = v;
return;
}
}
_tri.push_back(TRI_COORD<T>(i,j,v,false));
}
//-----------------------------------------------------------------------------
// Adds (i,j) to value
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::add(INDEX i, INDEX j, T v)
{
MICK(i,j); // Matrix Index ChecKing
if (i < _nRowsCRS)
{
const int loc = Utility::SearchSorted(_ja, j, _ia[i], _ia[i+1]);
if (loc >=0 )
{
_val[loc] += v;
return;
}
}
_tri.push_back(TRI_COORD<T>(i,j,v,true));
}
//-----------------------------------------------------------------------------
// returns a triplet value of the ith nonzero
//-----------------------------------------------------------------------------
template<typename T>
TRIPLET<T> SparseMatrix<T>::get_triplet(INDEX i) const
{
compress(*this);
if (i >= _ia[_nRowsCRS]) {
gerror("ERROR: tried indexing triplet of sparse matrix beyond range");
}
INDEX row(std::lower_bound(_ia, _ia+_nRowsCRS, i)-_ia);
row -= _ia[row] != i;
return TRIPLET<T>(row, _ja[i], _val[i]);
}
//-----------------------------------------------------------------------------
// full reset - completely wipes out all SparseMatrix data, zero is ignored
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::reset(INDEX rows, INDEX cols, bool zero)
{
_delete();
_nRows = rows;
_nCols = cols;
}
//-----------------------------------------------------------------------------
// resize - changes the _nRows and _nCols without changing anything else
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::resize(INDEX rows, INDEX cols, bool copy)
{
GCHK(_nRowsCRS>rows, "SparseMatrix::resize CRS rows exceed specified rows");
_nRows = rows;
_nCols = cols; // a check on this would be expensive
}
//-----------------------------------------------------------------------------
// get sparsity from DenseMatrix, if TOL < 0, then only zero values are added
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::reset(const DenseMatrix<T>& D, double TOL)
{
_delete(); // clears all values
// if TOL is specified then TOL = TOL^2 * max(abs(D))^2
if (TOL > 0.0)
{
TOL *= D.maxabs();
TOL *= TOL;
}
_nRows = D.nRows();
_nCols = D.nCols();
for (INDEX i=0; i<D.nRows(); i++)
for (INDEX j=0; j<D.nCols(); j++)
if (D(i,j)*D(i,j) >= TOL) // if TOL wasn't specified then TOL < 0
set(i, j, D(i,j));
compress();
}
//-----------------------------------------------------------------------------
// copy - dangerous: ignores rows & columns
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::copy(const T * ptr, INDEX rows, INDEX cols)
{
cout << "SparseMatrix<T>::copy() has no effect.\n";
}
//-----------------------------------------------------------------------------
// dense_copy - copy to dense matrix
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::dense_copy(DenseMatrix <T> & D ) const
{
SparseMatrix<T>::compress(*this);
D.reset(nRows(),nCols());
for (INDEX i=0; i<_nRowsCRS; i++)
for (INDEX j=_ia[i]; j<_ia[i+1]; j++)
D(i, _ja[j]) = _val[j];
}
template<typename T>
DenseMatrix <T> SparseMatrix<T>::dense_copy(void) const
{
DenseMatrix<T> D;
dense_copy(D);
return D;
}
//-----------------------------------------------------------------------------
// returns true if the matrix has no non-zero elements
//-----------------------------------------------------------------------------
template<typename T>
bool SparseMatrix<T>::empty() const
{
return _size==0 && _tri.empty();
}
//-----------------------------------------------------------------------------
// returns the number of rows specified by the user
//-----------------------------------------------------------------------------
template<typename T>
inline INDEX SparseMatrix<T>::nRows() const
{
return _nRows;
}
//-----------------------------------------------------------------------------
// returns the number of columns specified by the user
//-----------------------------------------------------------------------------
template<typename T>
inline INDEX SparseMatrix<T>::nCols() const
{
return _nCols;
}
//-----------------------------------------------------------------------------
// returns the number of non-zeros in the matrix
//-----------------------------------------------------------------------------
template<typename T>
INDEX SparseMatrix<T>::size() const
{
compress(*this);
return _size;
}
//-----------------------------------------------------------------------------
// returns the number of nonzero elements in a row
//-----------------------------------------------------------------------------
template<typename T>
INDEX SparseMatrix<T>::RowSize(INDEX r) const
{
compress(*this);
GCHK(r>=_nRows, "Rowsize: invalid row");
if (r >= _nRowsCRS) return 0;
return _ia[r+1]-_ia[r];
}
//-----------------------------------------------------------------------------
// returns a pointer to the data, causes a compress
//-----------------------------------------------------------------------------
template<typename T>
T* SparseMatrix<T>::get_ptr() const
{
compress(*this);
return _val;
}
//-----------------------------------------------------------------------------
// returns true if (i,j) falls in the user specified range
//-----------------------------------------------------------------------------
template<typename T>
bool SparseMatrix<T>::in_range(INDEX i, INDEX j) const
{
return i < nRows() && j < nCols();
}
//-----------------------------------------------------------------------------
// assigns this sparsematrix from another one - full memory copy
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>& SparseMatrix<T>::operator=(const SparseMatrix<T> &C)
{
_delete();
_copy(C);
return *this;
}
//-----------------------------------------------------------------------------
// assigns this sparsematrix from another one - full memory copy
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>& SparseMatrix<T>::operator=(const T v)
{
// set_all_elements only changes _data, so we need a compress
compress(*this);
return set_all_elements_to(v);
}
//-----------------------------------------------------------------------------
// scales this sparse matrix by a constant
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>& SparseMatrix<T>::operator*=(const T &a)
{
compress(*this);
for (INDEX i=0; i<size(); i++) _val[i] *= a;
return *this;
}
//-----------------------------------------------------------------------------
// Multiplies this Sparsematrix tranposed times a vector
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<T> SparseMatrix<T>::transMat(const Vector<T> &x) const
{
DenseVector<T> y(nCols(), true);
GCK(*this, x, nRows()!=x.size(),"operator *: Sparse matrix incompatible with Vector.")
INDEX i, ij;
for(i=0; i<_nRowsCRS; i++)
for(ij=_ia[i]; ij<_ia[i+1]; ij++)
y(_ja[ij]) += _val[ij]*x(i);
return y;
}
//-----------------------------------------------------------------------------
// Return matrix transpose
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T> SparseMatrix<T>::transpose() const
{
compress(*this);
SparseMatrix<T> At(nCols(), nRows());
for (INDEX i=0; i<_nRowsCRS; i++)
for (INDEX ij=_ia[i]; ij<_ia[i+1]; ij++)
At.set(_ja[ij], i, _val[ij]);
compress(At);
return At;
}
//-----------------------------------------------------------------------------
// Matrix Transpose/DenseMatrix multiply
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> SparseMatrix<T>::transMat(const DenseMatrix<T> &D) const
{
compress(*this);
GCK(*this, D, nRows()!=D.nRows(),"transMat: Sparse matrix incompatible with DenseMatrix.")
DenseMatrix<T> C(nCols(), D.nCols(), true); // initialized to zero
INDEX j, k, ki;
for (k=0; k<_nRowsCRS; k++)
for (ki=_ia[k]; ki<_ia[k+1]; ki++)
for (j=0; j<D.nCols(); j++)
C(_ja[ki], j) += _val[ki]*D(k,j); // C(i,j) = S(k,i) * D(k, j)
return C;
}
//-----------------------------------------------------------------------------
// Matrix Transpose/SparseMatrix multiply - IS THIS REALLY NEEDED??
//-----------------------------------------------------------------------------
template<typename T>
DenseMatrix<T> SparseMatrix<T>::transMat(const SparseMatrix<T> &D) const
{
compress(*this);
GCK(*this, D, nRows()!=D.nRows(),"transMat: Sparse matrix incompatible with DenseMatrix.")
DenseMatrix<T> C(nCols(), D.nCols(), true); // initialized to zero
INDEX k, ki, kj;
for (k=0; k<_nRowsCRS; k++)
for (kj=D._ia[k]; kj<D._ia[k+1]; kj++)
for (ki=_ia[k]; ki<_ia[k+1]; ki++)
C(_ja[ki], D._ja[kj]) += _val[ki]*D._val[kj]; // C(i,j) = S(k,i)*D(k,j)
return C;
}
//-----------------------------------------------------------------------------
// multiplies each row by the corresponding element in Vector scale
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>& SparseMatrix<T>::row_scale(const Vector<T> &v)
{
compress(*this);
INDEX i,ij;
GCK(*this, v, v.size()!=nRows(), "Incompatible Vector length in row_scale.");
for(i=0; i<_nRowsCRS; i++)
for(ij=_ia[i]; ij<_ia[i+1]; ij++) _val[ij] *= v[i];
return *this;
}
//-----------------------------------------------------------------------------
// multiples each column by the corresponding element in Vector scale
//-----------------------------------------------------------------------------
template<typename T>
SparseMatrix<T>& SparseMatrix<T>::col_scale(const Vector<T> &v)
{
compress(*this);
INDEX i,ij;
GCK(*this, v, v.size()!=nCols(), "Incompatible Vector length in col_scale.");
for(i=0; i<_nRowsCRS; i++)
for(ij=_ia[i]; ij<_ia[i+1]; ij++) _val[ij] *= v[_ja[ij]];
return *this;
}
//-----------------------------------------------------------------------------
// Returns a vector of the sums of each column
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<T> SparseMatrix<T>::col_sum() const
{
compress(*this);
INDEX i,ij;
GCHK(!nRows(), "SparseMatrix::Matrix not initialized in col_sum.")
DenseVector<T> csum(nCols());
for(i=0; i<_nRowsCRS; i++)
for(ij=_ia[i]; ij<_ia[i+1]; ij++) csum(_ja[ij]) += _val[ij];
return(csum);
}
//-----------------------------------------------------------------------------
// Returns a vector with the number of nonzeros in each column
//-----------------------------------------------------------------------------
template<typename T>
DenseVector<INDEX> SparseMatrix<T>::column_count() const
{
compress(*this);
INDEX i,j;
DenseVector<INDEX> counts(nCols());
for (i=0; i<_nRowsCRS; i++)
for(j=_ia[i]; j<_ia[i+1]; j++) counts(_ja[j])++;
return(counts);
}
//-----------------------------------------------------------------------------
// Writes a the nonzeros of a row to a vector
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::get_row(INDEX i, DenseVector<T>& row, DenseVector<INDEX>& indx) const
{
GCHK(i>=nRows(), "get_row() - invalid row number");
row.resize(RowSize(i));
indx.resize(row.size());
INDEX idx=0, ij;
for(ij=_ia[i]; ij<_ia[i+1]; ij++)
{
row(idx) = _val[ij];
indx(idx++) = _ja[ij];
}
}
//-----------------------------------------------------------------------------
// Computes the product of N'DN
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::
WeightedLeastSquares(const SparseMatrix<T> &N, const DiagonalMatrix<T> &D)
{
compress(N);
GCK(N,D,N.nRows()!=D.nRows(),"SparseMatrix::WeightedLeastSquares()");
INDEX k, ki, kj;
resize(N.nCols(), N.nCols()); // set size of this matrix
for (k=0; k<_size; k++) _val[k] = 0.0;
// compute R(i,j) = N(k,i) D(k,q) N(i,j) = N(k,i)*D(k,k)*N(k,j) (sum on k)
for (k=0; k<N._nRowsCRS; k++)
for (ki=N._ia[k]; ki<N._ia[k+1]; ki++)
for (kj=N._ia[k]; kj<N._ia[k+1]; kj++)
add(N._ja[ki],N._ja[kj], D[k]*N[kj]*N[ki]);
compress();
}
//-----------------------------------------------------------------------------
// Return a diagonal matrix containing the diagonal entries of this matrix
//-----------------------------------------------------------------------------
template<typename T>
DiagonalMatrix<T> SparseMatrix<T>::get_diag() const
{
compress(*this);
DiagonalMatrix<T> D(nRows(), true); // initialized to zero
INDEX i, ij;
for (i=0; i<_nRowsCRS; i++)
{
for(ij=_ia[i]; ij<_ia[i+1]; ij++)
{
if (_ja[ij]>=i) // have we reached or passed the diagonal?
{
if (_ja[ij]==i) D[i]=_val[ij]; // this this the diagonal?
break; // D[i] is already zero if there is no diagonal
}
}
}
return D;
}
//-----------------------------------------------------------------------------
// output function - builds a string with each nonzero triplet value
//-----------------------------------------------------------------------------
template<typename T>
string SparseMatrix<T>::tostring() const
{
compress(*this);
string out;
INDEX i, ij;
for(i=0; i<_nRowsCRS; i++)
{
for(ij=_ia[i]; ij<_ia[i+1]; ij++)
{
if (ij) out += "\n"; // append newline if not first nonzero
out += "(" + ATC_STRING::tostring(i) + ", "; // append "(i,"
out += ATC_STRING::tostring(_ja[ij]) + ") = "; // append "j) = "
out += ATC_STRING::tostring(_val[ij]); // append "value"
}
}
return out; // return the completed string
}
//-----------------------------------------------------------------------------
// returns the maximum value in the row
//-----------------------------------------------------------------------------
template<typename T>
T SparseMatrix<T>::get_row_max(INDEX row) const
{
compress(*this);
if (!RowSize(row)) return (T)0; // if there are no nonzeros in the row
INDEX ij;
T max = _val[_ia[row]];
for(ij=_ia[row]+1; ij<_ia[row+1]; ij++) max = std::max(max,_val[ij]);
return max;
}
//-----------------------------------------------------------------------------
// returns the minimum value in the row
//-----------------------------------------------------------------------------
template<typename T>
T SparseMatrix<T>::get_row_min(INDEX row) const
{
compress(*this);
if (!RowSize(row)) return (T)0; // if there are no nonzeros in the row
INDEX ij;
T min = _val[_ia[row]];
for(ij=_ia[row]+1; ij<_ia[row+1]; ij++) min = std::min(min,_val[ij]);
return min;
}
//-----------------------------------------------------------------------------
// prints a histogram of the values of a row to the screen
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::print_row_histogram(const string &name, INDEX nbins) const
{
compress(*this);
cout << "Begin histogram " << name << "\n";
cout << "# rows: " << _nRows << " columns: " << _nCols
<< " size: " << _size << "\n";
for(INDEX i=0; i<_nRows; i++)
{
print_row_histogram(i, nbins);
cout << "\n";
}
cout << "End histogram " << name << "\n";
}
//-----------------------------------------------------------------------------
// prints a histogram of the values of a row to the screen
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::print_row_histogram(INDEX row, INDEX nbins) const
{
compress(*this);
if (!nbins) nbins++;
vector<INDEX> counts(nbins, 0);
const T min = get_row_min(row);
const T max = get_row_max(row);
const T range = max-min;
const double bin_size = range/double(nbins);
if (range<=0.0) counts[nbins-1]=RowSize(row);
else
{
for(INDEX ij=_ia[row]; ij<_ia[row+1]; ij++)
{
INDEX bin = INDEX((_val[ij]-min)/bin_size);
counts[bin-(bin==nbins)]++;
}
}
cout<<showbase<<scientific;
cout<<"# Histogram: row "<<row<<" min "<<min<<" max "<<max<<" cnt " <<RowSize(row)<<"\n";
T bin_start = min;
for(INDEX i=0; i<nbins; i++)
{
cout << "(" << bin_start << ",";
bin_start += bin_size;
cout << bin_start << ") " << counts[i] << "\n";
}
}
//-----------------------------------------------------------------------------
// Outputs a string to a sparse Matlab type
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::matlab(ostream &o, const string &s) const
{
compress(*this);
INDEX i, ij;
o << s <<" = sparse(" << nRows() << "," << nCols() << ");\n";
o << showbase << scientific;
for(i=0; i<_nRowsCRS; i++)
for(ij=_ia[i]; ij<_ia[i+1]; ij++)
o<<s<<"("<<i+1<<","<<_ja[ij]+1<<")="<<_val[ij]<<";\n";
}
//-----------------------------------------------------------------------------
// Writes the matrix to a binary file (after a compress).
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::binary_write(std::fstream& f) const
{
compress(*this);
f.write((char*)&_size, sizeof(INDEX)); // writes number of nonzeros
f.write((char*)&_nRowsCRS, sizeof(INDEX)); // writes number of rows in crs
f.write((char*)&_nRows, sizeof(INDEX)); // write matrix rows
f.write((char*)&_nCols, sizeof(INDEX)); // write number of columns
if (!_size) return;
f.write((char*)_val, sizeof(T) *_size);
f.write((char*)_ja, sizeof(INDEX)*_size);
f.write((char*)_ia, sizeof(INDEX)*(_nRowsCRS+1));
}
//-----------------------------------------------------------------------------
// Reads a SparseMatrix from a binary file. (wipes out any original data)
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::binary_read(std::fstream& f)
{
_delete();
f.read((char*)&_size, sizeof(INDEX));
f.read((char*)&_nRowsCRS, sizeof(INDEX));
f.read((char*)&_nRows, sizeof(INDEX));
f.read((char*)&_nCols, sizeof(INDEX));
if (!_size) return;
_create(_size,_nRowsCRS);
f.read((char*)_val, sizeof(T)*_size);
f.read((char*)_ja, sizeof(INDEX)*_size);
f.read((char*)_ia, sizeof(INDEX)*(_nRowsCRS+1));
}
//-----------------------------------------------------------------------------
// Writes the sparse matrix to a file in a binary format
//-----------------------------------------------------------------------------
template<typename T>
void SparseMatrix<T>::write_restart(FILE *f) const
{
compress(*this);
fwrite(&_size, sizeof(INDEX), 1 ,f); // write number of nonzeros
fwrite(&_nRowsCRS, sizeof(INDEX), 1 ,f); // write number of rows
fwrite(&_nRows, sizeof(INDEX), 1 ,f); // write number of columns
fwrite(&_nCols, sizeof(INDEX), 1 ,f); // write number of columns
if (!_size) return;
fwrite(_val, sizeof(T), _size ,f);
fwrite(_ja, sizeof(T), _size ,f);
fwrite(_ia, sizeof(INDEX), _nRowsCRS+1 ,f);
}
#endif

View File

@ -1,180 +0,0 @@
#ifndef SPARSEMATRIX_H
#define SPARSEMATRIX_H
#include <exception>
#include "MatrixLibrary.h"
#include <algorithm>
/**
* @struct TRI_COORD
* @brief Triplet SparseMatrix entry
*/
template <typename T>
struct TRI_COORD
{
TRI_COORD<T>(unsigned row=0, unsigned col=0);
TRI_COORD<T>(unsigned row, unsigned col, T val, bool add_to=0);
unsigned i, j;
T v;
bool add;
};
/**
* @class SparseMatrix
* @brief Stores data in triplet format or CRS format
*/
template<typename T>
class SparseMatrix : public Matrix<T>
{
//* SparseMatrix-Vector multiplication (S * v)
friend DenseVector<T> operator*<T>(const SparseMatrix<T> &A, const Vector<T>& x);
//* SparseMatrix-DenseMatrix multiplication (S * F)
friend DenseMatrix<T> operator*<T>(const SparseMatrix<T> &A, const Matrix<T>& D);
//* SparseMatrix-DiagonalMatrix multiplication (S * D)
friend SparseMatrix<T> operator*<T>(const SparseMatrix<T> &A, const DiagonalMatrix<T>& D);
//* SparseMatrix-SparseMatrix multiplication (S * S)
friend SparseMatrix<T> operator*<T>(const SparseMatrix<T> &A, const SparseMatrix<T> &B);
//* computes the product of a SparseMatrix tranpose with a SparseVector (M'*v).
friend SparseVector<T> operator*<T>(const SparseMatrix<T> &M, const SparseVector<T> &v);
//* computes the product of a SparseMatrix tranpose with a SparseVector (M'*v).
friend SparseVector<T> operator*<T>(const SparseVector<T> &v, const SparseMatrix<T> &M);
public:
SparseMatrix(INDEX rows=0, INDEX cols=0);
SparseMatrix(const SparseMatrix<T>& c);
SparseMatrix(const DenseMatrix<T>& c);
~SparseMatrix();
//* General index by value (requires a binary search on the row)
T operator()(INDEX i, INDEX j) const;
//* General index by reference (requires a binary search on the row)
T& operator()(INDEX i, INDEX j);
//* General flat index by value operator (by nth nonzero)
T operator[](INDEX i) const;
//* General flat index by reference operator (by nth nonzero)
T& operator[](INDEX i);
//* adds a value to index i,j
void set(INDEX i, INDEX j, T v);
//* sets a value to index i,j
void add(INDEX i, INDEX j, T v);
//* return a triplet value of the ith nonzero
TRIPLET<T> get_triplet(INDEX i) const;
//* full reset - completely wipes out all SparseMatrix data
void reset(INDEX rows=0, INDEX cols=0, bool zero=true);
//* only changes the bounds of the matrix, no deletion
void resize(INDEX rows=0, INDEX cols=0, bool zero=true);
//* reset - from DenseMatrix - this will be SLOW
void reset(const DenseMatrix<T>& D, double TOL=-1.0);
//* copy data
void copy(const T * ptr, INDEX rows=0, INDEX cols=0);
void dense_copy(DenseMatrix<T>& D) const;
DenseMatrix<T> dense_copy(void) const;
//* returns true if the matrix has no nonzero elements
bool empty() const;
//* returns the user-specified number of rows
INDEX nRows() const;
//* returns the user-specified number of cols
INDEX nCols() const;
//* returns the number of non-zero elements
INDEX size() const;
//* returns the number of non-zeros in a row
INDEX RowSize(INDEX r) const;
//* returns a pointer to the nonzero data
inline T* get_ptr() const;
//* checks if the index i,j falls in the user-specified range
bool in_range(INDEX i, INDEX j) const;
/*
* \section assignment operators
*/
//* copies SparseMatrix R to this
SparseMatrix<T>& operator=(const SparseMatrix &R);
//* sets all nonzero values to a constant
SparseMatrix<T>& operator=(const T v);
//* scales all nonzero values by a constant
SparseMatrix<T>& operator*=(const T &a);
/*
* \section Multiplication operations
*/
//* S' * F
DenseMatrix<T> transMat(const DenseMatrix<T> &D) const;
//* S' * S
DenseMatrix<T> transMat(const SparseMatrix<T> &S) const;
//* S' * v
DenseVector<T> transMat(const Vector<T> &x) const;
SparseMatrix<T> transpose() const;
SparseMatrix<T>& row_scale(const Vector<T> &v);
SparseMatrix<T>& col_scale(const Vector<T> &v);
DenseVector<T> col_sum() const;
DenseVector<INDEX> column_count() const;
DiagonalMatrix<T> get_diag() const;
void get_row(INDEX i, DenseVector<T>& row, DenseVector<INDEX>& indx) const;
void WeightedLeastSquares(const SparseMatrix<T> &N, const DiagonalMatrix<T> &D);
T get_row_max(INDEX row) const;
T get_row_min(INDEX row) const;
/*
* \section I/O functions
*/
//* outputs this SparseMatrix to a formatted string
string tostring() const;
using Matrix<T>::matlab;
//* writes a command to recreate this matrix in matlab to a stream
void matlab(ostream &o, const string &name="S") const;
//* prints a row histogram for each row
void print_row_histogram(const string &name, INDEX nbins = 10) const;
//* prints a histogram of the values in a row
void print_row_histogram(INDEX row, INDEX nbins) const;
//! Writes the matrix to a binary file (after a compress).
void binary_write(std::fstream& f) const;
//! Reads a SparseMatrix from a binary file. (wipes out any original data)
void binary_read(std::fstream& f);
//* Dump templated type to disk; operation not safe for all types
void write_restart(FILE *f) const;
/*
* \section Utility functions
*/
//* converts all triplets and merges with CRS
void compress();
//* converts T to CRS
static void compress(const SparseMatrix<T> &C);
//* sorts and returns the # of unique triplets
INDEX CountUniqueTriplets();
private:
//* creates a CRS structure
void _create(INDEX size, INDEX nrows);
//* clears all memory and nulls references
void _delete();
//* copys all data from another SparseMatrix
void _copy(const SparseMatrix<T> &C);
//* general sparse matrix assignment
void _set_equal(const Matrix<T> &r);
//* returns the first row with a nonzero in it (from the CRS structure only)
int _first_nonzero_row_crs() const;
/*
* \section CRS storage variables
*/
T * _val; // matrix non-zeros
INDEX *_ia, *_ja; // ptrs to rows, column indexes
INDEX _size, _nRowsCRS; // # of non-zeros, rows
//* new (unsorted triplet values - won't intersect CRS values)
mutable vector<TRI_COORD<T> > _tri;
/*
* \section User specified variables
*/
INDEX _nRows, _nCols;
static T _zero;
};
#include "SparseMatrix-inl.h"
#endif

View File

@ -1,188 +0,0 @@
// SparseVector-inl.h: provides templated functions for SparseVector in
// separate header
template<class T>
SparseVector<T> sparse_rand(unsigned n, unsigned fill, int seed=1234)
{
srand(seed);
const double rmax_inv = 1.0/double(RAND_MAX);
SparseVector<T> r(n);
while (r.size()<fill)
r(rand()%r.nRows())=double(::rand()*rmax_inv);
return r;
}
// Multiplies a Matrix by a SparseVector (M*v) and returns a DenseVector.
template<class T>
DenseVector<T> operator*(const Matrix<T> &M, const SparseVector<T> &v)
{
DenseVector<T> y(M.nRows());
STORE::const_iterator it=v.data_.begin();
for (; it!=v.data_.end(); it++) {
const unsigned j = it->first;
const T& vj = it->second;
for (unsigned i=0; i<M.nRows(); i++) y(i)+=M(i,j)*vj;
}
return y;
}
// Multiplies a SparseVector by a Matrix (M'*v) and returns a DenseVector.
template<class T>
DenseVector<T> operator*(const SparseVector<T> &v, const Matrix<T> &M)
{
DenseVector<T> y(M.nCols());
STORE::const_iterator it=v.data_.begin();
for (; it!=v.data_.end(); it++) {
const unsigned i = it->first;
const T& vi = it->second;
for (unsigned j=0; j<M.nCols(); j++) y(j)+=vi*M(i,j);
}
return y;
}
// Computes the dot product between two SparseVectors of equal length.
template<class T>
T dot(const SparseVector<T> &a, const SparseVector<T> &b)
{
double v = 0.0;
for (STORE::const_iterator ai=a.data_.begin(); ai!=a.data_.end(); ai++) {
STORE::const_iterator bi=b.data_.find(ai->first);
if (bi == b.data_.end()) continue;
v += ai->second * bi->second;
}
return v;
}
// Computes the product of a SparseMatrix tranpose with a SparseVector (M'*v).
template<class T>
SparseVector<T> operator*(const SparseMatrix<T> &M, const SparseVector<T> &v)
{
SparseVector<T> y(M.nRows());
for (unsigned i=0; i<M.nRows(); i++) {
double yi=0.0;
for (unsigned ij=M._ia[i]; ij<M._ia[i+1]; ij++) {
const unsigned j = M._ja[ij];
STORE::const_iterator it = v._data.find(j);
if (it == v._data.end()) continue;
yi += M._v[ij] * it->second;
}
if (yi!=0.0) y(i)+=yi;
}
return y;
}
// computes the product of a SparseMatrix tranpose with a SparseVector (M'*v).
template<class T>
SparseVector<T> operator*(const SparseVector<T> &v, const SparseMatrix<T> &M)
{
SparseVector<T> y(M.nCols());
for (unsigned i=0; i<M.nRows(); i++) {
STORE::const_iterator it = v._data.find(i);
if (it == v._data.end()) continue;
for (unsigned ij=M._ia[i]; ij<M._ia[i+1]; ij++)
y(M._ja[ij]) += it->second * M._v[ij];
}
return y;
}
// General constructor - sets the vector length.
template<class T>
SparseVector<T>::SparseVector(unsigned n) : length_(n){}
// Outputs the vector to string
template<class T>
std::string SparseVector<T>::tostring() const
{
if (size() > nRows()/2) return Vector<T>::tostring();
STORE::const_iterator it=data_.begin();
std::string str;
using ATC_STRING::tostring;
for (; it!=data_.end(); it++)
str += tostring(it->first)+": "+tostring(it->second)+'\n';
return str;
}
// Indexes the ith component of the vector or returns zero if not found.
template<class T>
T SparseVector<T>::operator()(unsigned i, unsigned j) const
{
STORE::const_iterator it = data_.find(i);
if (it == data_.end()) return 0.0;
return it->second;
}
// Indexes the ith component of the vector or returns zero if not found.
template<class T>
T& SparseVector<T>::operator()(unsigned i, unsigned j)
{
return data_[i];
}
// Indexes the ith component of the vector or returns zero if not found.
template<class T> T SparseVector<T>::operator[](unsigned i) const
{
return (*this)(i);
}
// Indexes the ith component of the vector or returns zero if not found.
template<class T> T& SparseVector<T>::operator[](unsigned i)
{
return (*this)[i];
}
// Returns the number of nonzeros in the sparse vector.
template<class T> inline unsigned SparseVector<T>::size() const
{ return data_.size(); }
// Returns the number of nonzeros in the sparse vector.
template<class T> inline unsigned SparseVector<T>::nRows() const
{ return length_; }
// Changes the size of the SparseVector
template<class T>
void SparseVector<T>::resize(unsigned nRows, unsigned nCols, bool copy)
{
length_ = nRows;
STORE::iterator it;
for (it=data_.begin(); it!=data_.end(); it++) {
if (it->second >= length_) data_.erase(it);
else if (!copy) it->second=T(0);
}
}
// same as resize, but zero rather than copy
template<class T>
void SparseVector<T>::reset(unsigned nRows, unsigned nCols, bool zero)
{
resize(nRows, nCols, !zero);
}
// sets all elements to zero but preserves sparcity
template<class T>
void SparseVector<T>::zero()
{
STORE::iterator it;
for (it=data_.begin(); it!=data_.end(); it++) it->second=T(0);
}
// TODO
template<class T>
void SparseVector<T>::copy(const T* ptr, unsigned nRows, unsigned nCols)
{
}
// TODO
template<class T>
void SparseVector<T>::write_restart(FILE *F) const
{
}
// writes a stream to a matlab script to recreate this variable
template<class T>
void SparseVector<T>::matlab(ostream &o, const string &s) const
{
o << s << "=sparse(" << nRows() << ",1);\n";
o << showbase << scientific;
STORE::const_iterator it;
for (it=data_.begin(); it!=data_.end(); it++)
o << s << "(" << it->first+1 << ") = " << it->second << ";\n";
}

View File

@ -1,85 +0,0 @@
#ifndef SPARSEVECTOR_H
#define SPARSEVECTOR_H
#include "MatrixLibrary.h"
// No C++ templated typedefs, so use a define, gets cleaned up at end,
// so don't use outside of this class
#define STORE typename std::map<unsigned, T>
/** SparseVector class - an implimentation of a vector that contains a
** majority of zero element, and provides the relevant operations
** specified by the base class Vector.
**/
template<class T>
class SparseVector : public Vector<T> {
//* Multiplies a Matrix by a SparseVector (M*v) and returns a DenseVector.
friend DenseVector<T> operator*<T>(const Matrix<T> &M, const SparseVector<T> &v);
//* Multiplies a SparseVector by a Matrix (M'*v) and returns a DenseVector.
friend DenseVector<T> operator*<T>(const SparseVector<T> &v, const Matrix<T> &M);
//* Computes the dot product between two SparseVectors of equal length.
friend T dot<T>(const SparseVector<T> &a, const SparseVector<T> &b);
//* computes the product of a SparseMatrix tranpose with a SparseVector (M'*v).
friend SparseVector<T> operator*<T>(const SparseMatrix<T> &M, const SparseVector<T> &v);
//* computes the product of a SparseMatrix tranpose with a SparseVector (M'*v).
friend SparseVector<T> operator*<T>(const SparseVector<T> &v, const SparseMatrix<T> &M);
public:
//* Constructor - sets length of vector (NOT # of nonzeros).
SparseVector(unsigned length=0);
//* Copies another SparseVector
SparseVector(const SparseVector<T> &c);
//* Copies a general Vector (avoid if possible, its going to be slow).
SparseVector(const Vector<T> &c);
//* Overrides output to string function to list only nonzeros and indices.
std::string tostring() const;
//* Indexing operators (w/ const overloading).
//@{
T operator()(unsigned i, unsigned j=0) const;
// NOTE reading a non-const SparseVector will call this and add zero entries.
T& operator()(unsigned i, unsigned j=0);
T operator[](unsigned i) const;
T& operator[](unsigned i);
//@}
//* assignment operators
//@{
SparseVector<T>& operator=(SparseVector<T> &c);
SparseVector<T>& operator=(Vector<T> &c);
//@}
//* Return the number of rows in the Vector.
unsigned nRows() const;
//* Returns the number of columns - always 1.
unsigned nCols() const { return 1; }
//* Change # of Vector rows Vector and optionally keeps nonzeros (ignores nCols).
void resize(unsigned nRows, unsigned nCols=1, bool copy=0);
//* Return the number of nonzeros in the Vector.
unsigned size() const;
//* Changes size of Vector rows and optionally removes nonzeros.
void reset (unsigned nRows, unsigned nCols=1, bool zero=0);
//* zeros out all elements while preserving sparcity pattern
void zero();
//* TODO impliment copy (or maybe not necessary)
void copy(const T* ptr, unsigned nRows, unsigned nCols=1);
//* Writes a restart file (TODO impliment this if needed/wanted).
void write_restart(FILE *F) const;
// output to matlab (is this needed)
// using Matrix<T>::matlab;
//* Writes a matlab string to a stream that creates this object with a name.
void matlab(ostream &o, const string &s="v") const;
protected:
//* Banned operators
//@{
SparseVector(const Matrix<T> &c);
SparseVector<T>& operator=(Matrix<T> &c);
T* get_ptr() const {return NULL; }
//@}
STORE data_; //*> sparse data structure
unsigned length_; //*> number of rows
};
#include "SparseVector-inl.h"
#undef STORE
#endif

View File

@ -1,122 +0,0 @@
#ifndef STRINGMANIP_H
#define STRINGMANIP_H
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>
#include <algorithm>
using std::cout;
using std::transform;
using std::fstream;
using std::vector;
using std::string;
//* A collection of string convesion/manipulation routines
namespace ATC_STRING
{
//* converts anything that has iostream::<< defined to a string
template<typename T>
inline string tostring(const T &v, int precision=0)
{
std::ostringstream out;
if (precision) out << std::setprecision(precision);
out << v;
return out.str();
}
//* convert a string to anything that has iostream::>> defined
template<typename T>
inline T str2T(const string &s, T v)
{
std::istringstream in(s);
if (!(in >> v)) cout<<"Error: str2T invalid string conversion\n";\
return v;
}
//* convert a string to a double
inline double str2dbl(const string &s) { return str2T(s, double(0.0)); }
//* convert a string to an int
inline int str2int(const string &s) { return str2T(s, int(0)); }
//* replaces all characters in a set of characters with a character
//* @param str input string
//* @param *s pointer to array of characters that will be replaced
//* @param r character to replace characters in s[] with
static void replace_all_of(string &str, const char *s, const char r)
{
int found;
found = str.find_first_of(s);
while (found != string::npos)
{
str[found] = r;
found = str.find_first_of(s, found+1);
}
}
//* converts the string to lowercase
inline string& to_lower(string &s)
{
transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(tolower));
return s;
}
//* converts the string to uppercase
inline string& to_upper(string &s)
{
transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(toupper));
return s;
}
//* removes any whitespace from the beginning or end of string
static string& trim(string &s)
{
if (s.empty()) return s;
size_t found = s.find_last_not_of(" \t\n");
if (found < s.size()-1) s.erase(found+1);
found = s.find_first_not_of(" \t\n");
if (found != string::npos) s = s.substr(found);
return s;
}
//* splits delimited string into a vector of strings
static void split_up_string(const string &s, vector<string> &ss, char del=' ')
{
ss.clear();
size_t begin=0, end=0;
while (end != string::npos)
{
begin = s.find_first_not_of(del, end); // find beginning of fragment
end = s.find_first_of(del,begin);
if (begin != string::npos) // safe if end is npos-1
ss.push_back(s.substr(begin,end-begin));
}
}
//* scans a string for a list of commands delimited by ', \t' with # comments
//* @param line The input line to be parsed
//* @cs A vector of strings parsed from the input line
static void get_command_strings(string line, vector<string> &cs)
{
if (line.find('#') != string::npos) line.erase(line.find("#"));
replace_all_of(line, "\t,", ' ');
to_lower(trim(line));
split_up_string(line, cs);
}
//* reads a single line from a file and splits it into a vector of strings
//* returns the number of strings in the vector
inline int get_command_line(fstream &fid, vector<string> &cs)
{
string line;
getline(fid, line);
get_command_strings(line, cs);
return cs.size();
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,629 +0,0 @@
/** Thermostat : a class for atom-continuum control of energy/temperature */
#ifndef THERMOSTAT_H
#define THERMOSTAT_H
// ATC_Transfer headers
#include "AtomicRegulator.h"
// other headers
#include <map>
#include <set>
namespace ATC {
/**
* @class Thermtostat
* @brief Manager class for atom-continuum control of thermal energy
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class Thermostat
//--------------------------------------------------------
//--------------------------------------------------------
class Thermostat : public AtomicRegulator {
public:
/** thermostat types */
enum ThermostatType {
NONE=0,
RESCALE,
HOOVER,
FLUX
};
// constructor
Thermostat(ATC_Transfer * atcTransfer);
// destructor
~Thermostat(){};
/** parser/modifier */
virtual bool modify(int narg, char **arg);
/** pre time integration */
virtual void initialize();
// data access, intended for method objects
/** reset the nodal power to a prescribed value */
void reset_lambda_power(DENS_MAT & target);
/** return the nodal power induced by lambda */
DENS_VEC & get_nodal_atomic_lambda_power(){return nodalAtomicLambdaPower_;};
/** return value filtered lambda */
DENS_VEC & get_filtered_lambda_power(){return lambdaPowerFiltered_;};
/** access to thermostat type */
ThermostatType get_thermostat_type() const {return thermostatType_;};
protected:
/** thermostat type flag */
ThermostatType thermostatType_;
// thermostat data
/** lambda power applied to atoms */
DENS_VEC nodalAtomicLambdaPower_;
/** filtered lambda power */
DENS_VEC lambdaPowerFiltered_;
private:
// DO NOT define this
Thermostat();
};
/**
* @class ThermostatShapeFunction
* @brief Base class for implementation of thermostat algorithms using the shape function matrices
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatShapeFunction
// base class for all thermostats of general form
// of N^T w N lambda = rhs
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatShapeFunction : public RegulatorShapeFunction {
public:
ThermostatShapeFunction(Thermostat * thermostat);
~ThermostatShapeFunction(){};
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal();
protected:
// methods
/** set weighting factor for in matrix Nhat^T * weights * Nhat */
virtual void set_weights(DIAG_MAT & weights);
// member data
/** pointer to thermostat object for data */
Thermostat * thermostat_;
/** pointer to lammps atomic velocities */
double ** v_;
/** MD mass matrix */
MATRIX & mdMassMatrix_;
/** mass of ATC internal atoms on this processor */
DENS_VEC atomicMass_;
private:
// DO NOT define this
ThermostatShapeFunction();
};
/**
* @class ThermostatRescale
* @brief Enforces constraint on atomic kinetic energy based on FE temperature
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatRescale
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatRescale : public ThermostatShapeFunction {
public:
ThermostatRescale(Thermostat * thermostat);
~ThermostatRescale(){};
/** applies thermostat to atoms in the post-corrector phase */
virtual void apply_post_corrector(double dt);
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
/** apply solution to atomic quantities */
void apply_to_atoms(double ** atomicVelocity,
double dt);
/** FE temperature field */
DENS_MAT & nodalTemperature_;
private:
// DO NOT define this
ThermostatRescale();
};
/**
* @class ThermostatGlc
* @brief Base class for implementation of thermostat algorithms based on Gaussian least constraints (GLC)
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatGlc
// base clas for all thermostats of general form of a
// Gaussian least constraint (GLC)
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatGlc : public ThermostatShapeFunction {
public:
ThermostatGlc(Thermostat * thermostat);
~ThermostatGlc(){};
protected:
// methods
/** compute force induced by lambda */
virtual void compute_lambda_force(double * const * atomicQuantity,
DENS_MAT & lambdaForce);
/** apply forces to atoms */
virtual void apply_to_atoms(double ** atomicVelocity,
const DENS_MAT & lambdaForce,
double dt);
// member data
/** pointer to a time filtering object */
TimeFilter * timeFilter_;
/** power induced by lambda */
DENS_VEC & nodalAtomicLambdaPower_;
/** filtered lambda power */
DENS_VEC & lambdaPowerFiltered_;
/** atomic force induced by lambda */
DENS_MAT & lambdaForce_;
/** bool to determine if node is fixed or not */
Array2D<bool> & isFixedNode_;
private:
// DO NOT define this
ThermostatGlc();
};
/**
* @class ThermostatPower
* @brief Enforces GLC on atomic forces based on FE power
* when using fractional step time integration
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatPower
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatPower : public ThermostatGlc {
public:
ThermostatPower(Thermostat * thermostat);
~ThermostatPower();
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal();
/** applies thermostat to atoms in the predictor phase */
virtual void apply_pre_predictor(double dt);
/** applies thermostat to atoms in the pre-corrector phase */
virtual void apply_pre_corrector(double dt);
/** applies thermostat to atoms in the post-corrector phase */
virtual void apply_post_corrector(double dt);
protected:
// methods
/** destroys allocated memory */
void destroy();
/** update the nodal quantities after predictor step */
virtual void update_nodal_quantities_predictor(double dt);
/** compute the change in nodal atomic temperature */
virtual void compute_delta_nodal_atomic_temperature(double dt);
/** update the nodal quantities after pre-corrector step */
virtual void update_nodal_quantities_pre_corrector(double dt);
/** undoes the update the nodal quantities after pre-corrector step */
virtual void undo_update_nodal_quantities_pre_corrector(double dt);
/** update the nodal quantities after post-corrector step */
virtual void update_nodal_quantities_post_corrector(double dt);
/** sets up appropriate rhs for thermostat equations */
virtual void set_thermostat_rhs(DENS_MAT & rhs_nodes,
double dt);
/** apply forces to atoms */
virtual void apply_to_atoms(double ** atomicVelocity,
const DENS_MAT & lambdaForce,
double dt);
/** solves the non-linear equation for lambda iteratively */
void iterate_lambda(const MATRIX & rhs,
double * const * atomicVelocity,
double dt);
/** set weighting factor for in matrix Nhat^T * weights * Nhat */
virtual void set_weights(DIAG_MAT & weights);
// data
/** reference to AtC FE temperature */
DENS_MAT & nodalTemperature_;
/** reference to AtC restricted atomic temperature */
DENS_MAT & nodalAtomicTemperature_;
/** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
DENS_MAT & heatSource_;
/** reference to weights for Nhat */
DIAG_MAT & nodalWeights_;
/** change in FE temperature over a timestep */
DENS_MAT deltaTemperature_;
/** change in restricted atomic FE temperature over a timestep */
DENS_MAT deltaNodalAtomicTemperature_;
/** FE temperature rate of change */
DENS_MAT nodalTemperatureRoc_;
/** local version of velocity used as predicted final veloctiy */
double ** myAtomicVelocity_;
/** pointer to lammps atomic forces */
double ** f_;
/** number of total atoms on this processor */
int nLocalTotal_;
/** maximum number of iterations used in iterative solve for lambda */
int lambdaMaxIterations_;
/** tolerance used in iterative solve for lambda */
double lambdaTolerance_;
/** coefficient to account for effect of time filtering on rhs terms */
double filterCoefficient_;
/** reference to ATC unity shape function on ghost atoms */
SPAR_MAT & Nstar_;
/** maps ghost atom and LAMMPS atom ids */
Array<int> & ghostToAtom_;
private:
// DO NOT define this
ThermostatPower();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatHoover
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatHoover : public ThermostatPower {
public:
ThermostatHoover(Thermostat * thermostat);
~ThermostatHoover();
/** reset number of local atoms, as well as atomic data */
virtual void reset_nlocal();
/** applies thermostat to atoms in the predictor phase */
virtual void apply_pre_predictor(double dt);
/** applies thermostat to atoms in the pre-corrector phase */
virtual void apply_pre_corrector(double dt);
/** applies thermostat to atoms in the post-corrector phase */
virtual void apply_post_corrector(double dt);
protected:
// methods
/** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
virtual void compute_boundary_flux(FIELDS & fields) {boundaryFlux_[TEMPERATURE] = 0.;};
/** adds Hoover power terms to nodal variables after the predictor phase */
void add_to_lambda_power_predictor(double dt);
/** adds Hoover power terms to nodal variables after the pre-corrector phase */
void add_to_lambda_power_pre_corrector(double dt);
/** adds Hoover power terms to nodal variables after the post-corrector phase */
void add_to_lambda_power_post_corrector(double dt);
/** sets up appropriate rhs for thermostat equations */
virtual void set_hoover_rhs(DENS_MAT & rhs_nodes,
double dt);
/** add Hoover contributions to lambda power */
void add_to_lambda_power(DENS_MAT & myLambdaForce);
// data
/** force coming from Hoover contribution */
DENS_MAT lambdaForceHoover_;
/** reference to ATC map from global nodes to overlap nodes */
Array<int> & nodeToOverlapMap_;
private:
// DO NOT define this
ThermostatHoover();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatPowerFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatPowerFiltered : public ThermostatPower {
public:
ThermostatPowerFiltered(Thermostat * thermostat);
~ThermostatPowerFiltered(){};
protected:
/** update the nodal quantities after predictor step */
virtual void update_nodal_quantities_predictor(double dt);
/** compute the change in nodal atomic temperature */
virtual void compute_delta_nodal_atomic_temperature(double dt);
/** update the nodal quantities after pre-corrector step */
virtual void update_nodal_quantities_pre_corrector(double dt);
/** update the nodal quantities after post-corrector step */
virtual void update_nodal_quantities_post_corrector(double dt);
/** sets up appropriate rhs for thermostat equations */
virtual void set_thermostat_rhs(DENS_MAT & rhs_nodes,
double dt);
private:
// DO NOT define this
ThermostatPowerFiltered();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatPowerVerlet
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatPowerVerlet : public ThermostatGlc {
public:
ThermostatPowerVerlet(Thermostat * thermostat);
~ThermostatPowerVerlet(){};
/** applies thermostat to atoms in the predictor phase */
virtual void apply_pre_predictor(double dt);
/** applies thermostat to atoms in the pre-corrector phase */
virtual void apply_pre_corrector(double dt);
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
/** nodal temperature rate of change */
DENS_MAT & nodalTemperatureRoc_;
/** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
DENS_MAT & heatSource_;
/** pointer to lammps atomic forces */
double ** f_;
/** sets up and solves thermostat equations */
virtual void compute_thermostat(double dt);
/** sets up appropriate rhs for thermostat equations */
virtual void set_thermostat_rhs(DENS_MAT & rhs_nodes);
/** computes the nodal FE power applied by the thermostat */
virtual void compute_nodal_lambda_power(double dt);
/** add contributions (if any) to the finite element right-hand side */
virtual void add_to_rhs(FIELDS & rhs);
private:
// DO NOT define this
ThermostatPowerVerlet();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatHooverVerlet
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatHooverVerlet : public ThermostatPowerVerlet {
public:
ThermostatHooverVerlet(Thermostat * thermostat);
~ThermostatHooverVerlet(){};
protected:
/** reference to ATC map from global nodes to overlap nodes */
Array<int> & nodeToOverlapMap_;
/** sets up and solves thermostat equations */
virtual void compute_thermostat(double dt);
/** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
virtual void compute_boundary_flux(FIELDS & fields) {boundaryFlux_[TEMPERATURE] = 0.;};
/** sets up Hoover component of the thermostat */
void set_hoover_rhs(DENS_MAT & rhs_nodes);
/** add Hoover contributions to lambda power */
void add_to_lambda_power(DENS_MAT & myLambdaForce,
double dt);
private:
// DO NOT implement this
ThermostatHooverVerlet();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatPowerVerletFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatPowerVerletFiltered : public ThermostatPowerVerlet {
public:
ThermostatPowerVerletFiltered(Thermostat * thermostat);
~ThermostatPowerVerletFiltered(){};
/** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
virtual void compute_boundary_flux(FIELDS & fields);
/** get data for output */
virtual void output(double dt, OUTPUT_LIST & outputData);
protected:
/** sets up appropriate rhs for thermostat equations */
virtual void set_thermostat_rhs(DENS_MAT & rhs_nodes);
/** add contributions (if any) to the finite element right-hand side */
virtual void add_to_rhs(FIELDS & rhs);
/** nodal temperature 2nd rate of change (i.e. second time derivative) */
DENS_MAT & nodalTemperature2Roc_;
/** reference to ATC rate of change sources coming from prescribed data, AtC coupling, and extrinsic coupling */
DENS_MAT heatSourceRoc_;
/** references to ATC field rates of changing for inverting the filtered heat sources */
FIELDS & fieldsRoc_;
/** flux rate of changes for inverting filtered fluxes */
FIELDS fluxRoc_;
/** time scale for the time filter */
double filterScale_;
private:
// DO NOT define this
ThermostatPowerVerletFiltered();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class ThermostatHooverVerletFiltered
//--------------------------------------------------------
//--------------------------------------------------------
class ThermostatHooverVerletFiltered : public ThermostatPowerVerletFiltered {
public:
ThermostatHooverVerletFiltered(Thermostat * thermostat);
~ThermostatHooverVerletFiltered(){};
protected:
/** reference to ATC map from global nodes to overlap nodes */
Array<int> & nodeToOverlapMap_;
/** sets up and solves thermostat equations */
virtual void compute_thermostat(double dt);
/** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
virtual void compute_boundary_flux(FIELDS & fields) {boundaryFlux_[TEMPERATURE] = 0.;};
/** sets up Hoover component of the thermostat */
void set_hoover_rhs(DENS_MAT & rhs_nodes);
/** add Hoover contributions to lambda power */
void add_to_lambda_power(DENS_MAT & myLambdaForce,
double dt);
private:
// DO NOT implement this
ThermostatHooverVerletFiltered();
};
};
#endif

View File

@ -1,345 +0,0 @@
// ATC_Transfer headers
#include "ATC_Transfer.h"
#include "TimeFilter.h"
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterManager
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterManager::TimeFilterManager(ATC_Transfer * atcTransfer) :
atcTransfer_(atcTransfer),
filterType_(NO_FILTER),
filterScale_(0.),
useFilter_(false),
equilibrateFilter_(false),
endEquilibrate_(false),
needReset_(true)
{
// do nothing
}
//--------------------------------------------------------
// modify
// parses input commands
//--------------------------------------------------------
bool TimeFilterManager::modify(int narg, char ** arg)
{
bool foundMatch = false;
// filter scale size
/*! \page man_filter_scale fix_modify AtC transfer filter scale
\section syntax
fix_modify AtC transfer filter scale <scale> \n
- scale (real) = characteristic time scale of the filter \n
\section examples
<TT> fix_modify AtC transfer filter scale 10.0 </TT> \n
\section description
Filters the MD dynamics to construct a more appropriate continuous field. Equilibrating first filters the time derivatives without changing the dynamics to provide a better initial condition to the filtered dynamics
\section restrictions
only for be used with specific transfers:
thermal, two_temperature
\section related
\ref man_time_filter
\section default
0.
*/
if (strcmp(arg[0],"scale")==0) {
filterScale_ = atof(arg[1]);
if (filterScale_<=0.)
throw ATC_Error(0,"Bad filtering time scale");
foundMatch = true;
}
// time filtering activation switch
/*! \page man_time_filter fix_modify AtC transfer filter
\section syntax
fix_modify AtC transfer filter <on | off | equilibrate> \n
- on | off (keyword) = turns filter on or off\n
- equilibrate = runs dynamics without filtering but initializes filtered quantities
\section examples
<TT> fix_modify atc transfer filter on </TT> \n
\section description
Filters the MD dynamics to construct a more appropriate continuous field. Equilibrating first filters the time derivatives without changing the dynamics to provide a better initial condition to the filtered dynamics
\section restrictions
only for be used with specific transfers:
thermal, two_temperature
\section related
\ref man_filter_scale \n
\ref man_equilibrium_start
\section default
off
*/
else if (strcmp(arg[0],"on")==0) {
if (filterScale_<=0.)
throw ATC_Error(0,"Filtering time scale not initialized");
useFilter_ = true;
if (!equilibrateFilter_) {
needReset_ = true;
endEquilibrate_ = false;
}
else {
endEquilibrate_ = true;
}
equilibrateFilter_ = false;
foundMatch = true;
}
else if (strcmp(arg[0],"off")==0) {
useFilter_ = false;
equilibrateFilter_ = false;
endEquilibrate_ = false;
needReset_ = true;
foundMatch = true;
}
else if (strcmp(arg[0],"equilibrate")==0) {
if (filterScale_<=0.)
throw ATC_Error(0,"Filtering time scale not initialized");
equilibrateFilter_ = true;
endEquilibrate_ = false;
useFilter_ = false;
needReset_ = true;
foundMatch = true;
}
/** Example command for to set time filter scale:
fix_modify atc transfer filter type step*/
else if (strcmp(arg[0],"type")==0) {
if (strcmp(arg[1],"exponential")==0) {
filterType_ = EXPONENTIAL_FILTER;
}
else if (strcmp(arg[1],"no_filter")==0) {
filterType_ = NO_FILTER;
}
else throw ATC_Error(0,"Not a supported time filter type");
foundMatch = true;
}
return foundMatch;
}
//--------------------------------------------------------
// initialize
// filter set up before a run
//--------------------------------------------------------
void TimeFilterManager::initialize()
{
needReset_ = false;
endEquilibrate_ = false;
}
//--------------------------------------------------------
// construct
// instantiates the filter
//--------------------------------------------------------
// NOTE currently the caller is responsible for deletion
TimeFilter * TimeFilterManager::construct(const FilterIntegrationType intType)
{
if (useFilter_ || equilibrateFilter_) {
if (filterType_ == EXPONENTIAL_FILTER) {
if (intType == IMPLICIT_EXPLICIT) {
return new TimeFilterImplicitExplicit(*this);
}
else if (intType == EXPLICIT_IMPLICIT) {
return new TimeFilterExplicitImplicit(*this);
}
else if (intType == EXPLICIT) {
return new TimeFilterExplicit(*this);
}
else if (intType == IMPLICIT) {
return new TimeFilterImplicit(*this);
}
else if (intType == IMPLICIT_UPDATE) {
return new TimeFilterImplicitUpdate(*this);
}
else {
return new TimeFilterCrankNicolson(*this);
}
}
}
// default to return base class
return new TimeFilter(*this);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilter
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilter::TimeFilter(TimeFilterManager & timeFilterManager) :
atcTransfer_(timeFilterManager.get_atc_transfer()),
filterScale_(timeFilterManager.get_filter_scale())
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterExponential
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterExponential::TimeFilterExponential(TimeFilterManager & timeFilterManager) :
TimeFilter(timeFilterManager)
{
TimeFilter::filterType_ = TimeFilterManager::EXPONENTIAL_FILTER;
}
//--------------------------------------------------------
// initialize
// resets memory as needed
//--------------------------------------------------------
void TimeFilterExponential::initialize(const MATRIX & target)
{
TimeFilter::initialize(target);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterCrankNicoslon
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterCrankNicolson::TimeFilterCrankNicolson(TimeFilterManager & timeFilterManager) :
TimeFilterExponential(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
// initialize
// resets memory as needed
//--------------------------------------------------------
void TimeFilterCrankNicolson::initialize(const MATRIX & target)
{
TimeFilterExponential::initialize(target);
unFilteredQuantityOld_.reset(target.nRows(),target.nCols());
unFilteredQuantityOld_ = target;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterExplicit
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterExplicit::TimeFilterExplicit(TimeFilterManager & timeFilterManager) :
TimeFilterExponential(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterImplicit
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterImplicit::TimeFilterImplicit(TimeFilterManager & timeFilterManager) :
TimeFilterExponential(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterImplicitExplicit
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterImplicitExplicit::TimeFilterImplicitExplicit(TimeFilterManager & timeFilterManager) :
TimeFilterExponential(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterExplicitImplicit
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterExplicitImplicit::TimeFilterExplicitImplicit(TimeFilterManager & timeFilterManager) :
TimeFilterExponential(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterImplicitUpdate
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterImplicitUpdate::TimeFilterImplicitUpdate(TimeFilterManager & timeFilterManager) :
TimeFilterExponential(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterStep
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeFilterStep::TimeFilterStep(TimeFilterManager & timeFilterManager) :
TimeFilter(timeFilterManager)
{
// do nothing
}
//--------------------------------------------------------
// initialize
// resets memory as needed
//--------------------------------------------------------
void TimeFilterStep::initialize(const MATRIX & target)
{
TimeFilter::initialize(target);
}
};

View File

@ -1,696 +0,0 @@
// The type of filter used should be determined by the
// integrator since filtering much match the time integration scheme
#ifndef TIME_FILTER_H
#define TIME_FILTER_H
// ATC_Transfer headers
#include "MatrixLibrary.h"
#include "ATC_Error.h"
using namespace std;
namespace ATC {
// forward declarations
class ATC_Transfer;
class TimeFilter;
/**
* @class TimeFilterManager
* @brief Handles parsing and parameter storage for time filters
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterManager
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterManager {
public:
/** enumeration for the functional form underlying the filter */
enum TimeFilterType {
NO_FILTER=0, // default
EXPONENTIAL_FILTER,
STEP_FILTER
};
/** enumeration for the functional form underlying the filter */
enum FilterIntegrationType {
CRANK_NICHOLSON=0, // default
IMPLICIT_EXPLICIT,
EXPLICIT_IMPLICIT,
EXPLICIT,
IMPLICIT,
IMPLICIT_UPDATE
};
// constructor
TimeFilterManager(ATC_Transfer * atcTransfer);
// destructor
~TimeFilterManager(){};
/** parser/modifier */
bool modify(int narg, char **arg);
/** pre time integration */
void initialize();
/** get filter base function */
TimeFilterType get_filter_type() const {return filterType_;};
/** return filtering time scale */
double get_filter_scale() const {return filterScale_;};
/** check if dynamics should be filtering */
bool filter_dynamics() const {return useFilter_;};
/** check if variables should be filtered */
bool filter_variables() const {return (useFilter_ || equilibrateFilter_);};
/** flag for if reset is needed */
bool need_reset() const {return needReset_;};
/** flag if ending equilibration */
bool end_equilibrate() const {return endEquilibrate_;};
/** get pointer to ATC transfer methods */
ATC_Transfer * get_atc_transfer() {return atcTransfer_;};
/** construct the appropriate time filter */
TimeFilter * construct(const FilterIntegrationType type = CRANK_NICHOLSON);
protected:
TimeFilterManager(){};
/** pointer to access ATC methods */
ATC_Transfer * atcTransfer_;
/** description of underlying function form of filter */
TimeFilterType filterType_;
/** filtering time scale */
double filterScale_;
/** flag to see if filtering is active */
bool useFilter_;
/** flag to see if we are equilibrating the filtered variables */
bool equilibrateFilter_;
/** flag to reset data */
bool needReset_;
/** flag to denote switch from equilibration to integration */
bool endEquilibrate_;
};
/**
* @class TimeFilter
* @brief Base class for various temporal filters of atomistic quantities
* default behavior is no filter
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilter
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilter {
public:
// constructor
TimeFilter(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilter(){};
/** pre time integration */
virtual void initialize(const MATRIX & target){};
/** Step 1:
apply first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt)
{ TimeFilter::unFilteredQuantityOld_ = unFilteredQuantity;}
/** Step 2:
apply second step in a time filter update in pre integration phase */
virtual void apply_pre_step2(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** Step 3:
apply first step in a time filter update in post integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** Step 4:
apply second step in a time filter update in post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt)
{ filteredQuantity = unFilteredQuantity;}
/** coefficient multipling unfiltered terms in apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return 0.;};
/** coefficient multipling unfiltered terms in apply_post_step1 method */
virtual double get_unfiltered_coefficient_post_s1(double dt){return 0.;};
/** coefficient multipling unfiltered terms in apply_pre_step2 method */
virtual double get_unfiltered_coefficient_pre_s2(double dt){return 0.;};
/** coefficient multipling unfiltered terms in apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s2(double dt){return 0.;};
/** rate of filtered quantity to be called in post integration phase */
virtual void rate(MATRIX & rate,
const MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt = 0.0)
{ rate = 1/dt*(unFilteredQuantity - TimeFilter::unFilteredQuantityOld_);};
protected:
TimeFilter(){};
/** pointer to access ATC methods */
ATC_Transfer * atcTransfer_;
/** filtering time scale */
double filterScale_;
/** filter type */
TimeFilterManager::TimeFilterType filterType_;
/** member data to track old unfiltered values */
DENS_MAT unFilteredQuantityOld_;
};
/**
* @class TimeFilterExponential
* @brief Base class for filters using an exponential kernel,
* derived classes implement specific integration schemes
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterExponential
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterExponential : public TimeFilter {
public:
// constructor
TimeFilterExponential(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterExponential(){};
/** pre time integration */
virtual void initialize(const MATRIX & target);
/** apply first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** apply second step in a time filter update in pre integration phase */
virtual void apply_pre_step2(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** apply first step in a time filter update in post integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** apply second step in a time filter update in post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** time rate of filtered quantity */
virtual void rate(MATRIX & rate,
const MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
double dt = 0)
{ double tau = TimeFilter::filterScale_;
rate = 1/tau*(unfilteredQuantity - filteredQuantity); };
protected:
TimeFilterExponential(){};
//--------------------------------------------------------
//--------------------------------------------------------
// filter integration functions not associated
// with any particular class
//--------------------------------------------------------
//--------------------------------------------------------
void update_filter(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
MATRIX & unfilteredQuantityOld,
double tau,
double dt)
{
filteredQuantity = 1./(1./dt+1./(2*tau))*( 1./(2*tau)*
(unfilteredQuantity+unfilteredQuantityOld) +
(1./dt-1./(2*tau))*filteredQuantity);
unfilteredQuantityOld = unfilteredQuantity;
};
void add_to_filter(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
MATRIX & unfilteredQuantityOld,
double tau,
double dt)
{
filteredQuantity += 1./(1./dt+1./(2.*tau))*( 1./(2.*tau))*unfilteredQuantity;
unfilteredQuantityOld += unfilteredQuantity;
};
double get_unfiltered_coef(double tau, double dt)
{ return 1./(1./dt+1./(2.*tau))*( 1./(2.*tau)); };
void update_filter_implicit(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
double tau,
double dt)
// TODO: replace the rest of these like below:
{ filteredQuantity = (1./(1.+dt/tau))*((dt/tau)*unfilteredQuantity + filteredQuantity); };
// {
// filteredQuantity /= 1.0 + dt/tau;
// filteredQuantity += (dt)/(tau+dt)*unfilteredQuantity;
// }
void add_to_filter_implicit(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
double tau,
double dt)
{ filteredQuantity += (1./(1.+dt/tau))*(dt/tau)*unfilteredQuantity; };
double get_unfiltered_coef_implicit(double tau, double dt)
{ return (1./(1.+dt/tau))*(dt/tau); };
void update_filter_explicit(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
double tau,
double dt)
{ filteredQuantity = (dt/tau)*unfilteredQuantity + (1.-dt/tau)*filteredQuantity; };
void add_to_filter_explicit(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
double tau,
double dt)
{ filteredQuantity += (dt/tau)*unfilteredQuantity; };
double get_unfiltered_coef_explicit(double dt, double tau)
{ return (dt/tau); };
};
/**
* @class TimeFilterCrankNicolson
* @brief Time Filter using Crank-Nicolson advancement of filtered quantity ODE's
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterCrankNicolson
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterCrankNicolson : public TimeFilterExponential {
public:
// constructor
TimeFilterCrankNicolson(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterCrankNicolson(){};
/** pre time integration */
virtual void initialize(const MATRIX & target);
/** applies first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter(filteredQuantity,unFilteredQuantity,unFilteredQuantityOld_,TimeFilter::filterScale_,dt); };
/** applies first step in a time filter update after the pre integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ add_to_filter(filteredQuantity,unFilteredQuantity,unFilteredQuantityOld_,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter(filteredQuantity,unFilteredQuantity,unFilteredQuantityOld_,TimeFilter::filterScale_,dt); };
/** return coefficient multipling unfiltered terms in the apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return get_unfiltered_coef(TimeFilter::filterScale_,dt);};
/** return coefficient multipling unfiltered terms in the apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s2(double dt){return get_unfiltered_coef(TimeFilter::filterScale_,dt);};
protected:
TimeFilterCrankNicolson();
};
/**
* @class TimeFilterExplicit
* @brief Time Filter using explicit advancement of filtered quantity ODE's
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterExplicit
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterExplicit : public TimeFilterExponential {
public:
// constructor
TimeFilterExplicit(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterExplicit(){};
/** applies first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{update_filter_explicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies first step in a time filter update after the pre integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ add_to_filter_explicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_explicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** return coefficient multipling unfiltered terms in the apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return get_unfiltered_coef_explicit(TimeFilter::filterScale_,dt);};
/** return coefficient multipling unfiltered terms in the apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s2(double dt){return get_unfiltered_coef_explicit(TimeFilter::filterScale_,dt);};
protected:
TimeFilterExplicit();
};
/**
* @class TimeFilterImplicit
* @brief Time Filter using implicit advancement of filtered quantity ODE's
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterImplicit
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterImplicit : public TimeFilterExponential {
public:
// constructor
TimeFilterImplicit(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterImplicit(){};
/** applies first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** return coefficient multipling unfiltered terms in the apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return get_unfiltered_coef_implicit(TimeFilter::filterScale_,dt);};
/** return coefficient multipling unfiltered terms in the apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s2(double dt){return get_unfiltered_coef_implicit(TimeFilter::filterScale_,dt);};
protected:
TimeFilterImplicit();
};
/**
* @class TimeFilterImplicitExplicit
* @brief Time Filter using two-step implicit/explicit advancement of filtered quantity ODE's
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterImplicitExplicit
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterImplicitExplicit : public TimeFilterExponential {
public:
// constructor
TimeFilterImplicitExplicit(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterImplicitExplicit(){};
/** applies first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_explicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** return coefficient multipling unfiltered terms in the apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return get_unfiltered_coef_implicit(TimeFilter::filterScale_,dt);};
/** return coefficient multipling unfiltered terms in the apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s2(double dt){return get_unfiltered_coef_explicit(TimeFilter::filterScale_,dt);};
protected:
TimeFilterImplicitExplicit();
};
/**
* @class TimeFilterExplicitImplicit
* @brief Time Filter using two-step explicit/implicit advancement of filtered quantity ODE's
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterExplicitImplicit
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterExplicitImplicit : public TimeFilterExponential {
public:
// constructor
TimeFilterExplicitImplicit(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterExplicitImplicit(){};
/** applies first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_explicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the pre integration phase */
virtual void apply_pre_step2(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ add_to_filter_explicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ add_to_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** return coefficient multipling unfiltered terms in the apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return get_unfiltered_coef_explicit(TimeFilter::filterScale_,dt);};
/** return coefficient multipling unfiltered terms in the apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s1(double dt){return get_unfiltered_coef_implicit(TimeFilter::filterScale_,dt);};
protected:
TimeFilterExplicitImplicit();
};
/**
* @class TimeFilterImplicitUpdate
* @brief Time Filter using implicit advancement of filtered quantity ODE's but adds on contribution at the end of the second step
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterImplicitUpdate
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterImplicitUpdate : public TimeFilterExponential {
public:
// constructor
TimeFilterImplicitUpdate(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterImplicitUpdate(){};
/** applies first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ update_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** applies second step in a time filter update in the post integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
MATRIX const & unFilteredQuantity,
double dt)
{ add_to_filter_implicit(filteredQuantity,unFilteredQuantity,TimeFilter::filterScale_,dt); };
/** return coefficient multipling unfiltered terms in the apply_pre_step1 method */
virtual double get_unfiltered_coefficient_pre_s1(double dt){return get_unfiltered_coef_implicit(TimeFilter::filterScale_,dt);};
/** return coefficient multipling unfiltered terms in the apply_post_step2 method */
virtual double get_unfiltered_coefficient_post_s1(double dt){return get_unfiltered_coef_implicit(TimeFilter::filterScale_,dt);};
protected:
TimeFilterImplicitUpdate();
};
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeFilterStep
//--------------------------------------------------------
//--------------------------------------------------------
class TimeFilterStep : public TimeFilter {
public:
// constructor
TimeFilterStep(TimeFilterManager & timeFilterManager);
// destructor
virtual ~TimeFilterStep(){};
/** pre time integration */
virtual void initialize(const MATRIX & target);
/** apply first step in a time filter update in the pre integration phase */
virtual void apply_pre_step1(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** apply second step in a time filter update in pre integration phase */
virtual void apply_pre_step2(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** apply first step in a time filter update in post integration phase */
virtual void apply_post_step1(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt) {};
/** apply second step in a time filter update in post integration phase */
virtual void apply_post_step2(MATRIX & filteredQuantity,
const MATRIX & unFilteredQuantity,
double dt)
{ update_filter(filteredQuantity, unFilteredQuantity,
TimeFilter::unFilteredQuantityOld_, TimeFilter::filterScale_, dt);
}
/** time rate of filtered quantity */
virtual void rate(MATRIX & rate,
const MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
double dt = 0)
{ rate = 1/elapsedTime_*(unfilteredQuantity - filteredQuantity); }
protected:
TimeFilterStep(){};
double elapsedTime_;
void update_filter(MATRIX & filteredQuantity,
const MATRIX & unfilteredQuantity,
MATRIX & unfilteredQuantitySum,
double tau,
double dt)
{
elapsedTime_ += dt;
if (elapsedTime_ > tau) {
elapsedTime_ = dt;
unfilteredQuantitySum = unfilteredQuantity*dt;
filteredQuantity = unfilteredQuantity;
}
else {
unfilteredQuantitySum += unfilteredQuantity*dt;
filteredQuantity = unfilteredQuantitySum;
filteredQuantity /= elapsedTime_;
}
};
};
};
#endif

View File

@ -1,176 +0,0 @@
// ATC transfer headers
#include "TimeIntegrator.h"
#include "ATC_Transfer.h"
#include "ATC_Error.h"
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeIntegrator
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
TimeIntegrator::TimeIntegrator(ATC_Transfer * atcTransfer,
TimeIntegrationType timeIntegrationType) :
atcTransfer_(atcTransfer),
timeIntegrationMethod_(NULL),
timeFilter_(NULL),
timeFilterManager_(atcTransfer_->get_time_filter_manager()),
timeIntegrationType_(timeIntegrationType),
needReset_(true)
{
// do nothing
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
TimeIntegrator::~TimeIntegrator()
{
if (timeFilter_)
delete timeFilter_;
if (timeIntegrationMethod_)
delete timeIntegrationMethod_;
}
//--------------------------------------------------------
// pre_initial_integrate1
// first time integration computations
// before Verlet step 1
//--------------------------------------------------------
void TimeIntegrator::pre_initial_integrate1(double dt)
{
timeIntegrationMethod_->pre_initial_integrate1(dt);
}
//--------------------------------------------------------
// pre_initial_integrate2
// second time integration computations
// before Verlet step 1
//--------------------------------------------------------
void TimeIntegrator::pre_initial_integrate2(double dt)
{
timeIntegrationMethod_->pre_initial_integrate2(dt);
}
//--------------------------------------------------------
// mid_initial_integrate1
// first time integration computations
// at the mid-point of Verlet step 1
//--------------------------------------------------------
void TimeIntegrator::mid_initial_integrate1(double dt)
{
timeIntegrationMethod_->mid_initial_integrate1(dt);
}
//--------------------------------------------------------
// mid_initial_integrate2
// second time integration computations
// at the mid-point of Verlet step 1
//--------------------------------------------------------
void TimeIntegrator::mid_initial_integrate2(double dt)
{
timeIntegrationMethod_->mid_initial_integrate2(dt);
}
//--------------------------------------------------------
// post_initial_integrate1
// first time integration computations
// after Verlet step 1
//--------------------------------------------------------
void TimeIntegrator::post_initial_integrate1(double dt)
{
timeIntegrationMethod_->post_initial_integrate1(dt);
}
//--------------------------------------------------------
// post_initial_integrate2
// second time integration computations
// after Verlet step 1
//--------------------------------------------------------
void TimeIntegrator::post_initial_integrate2(double dt)
{
timeIntegrationMethod_->post_initial_integrate2(dt);
}
//--------------------------------------------------------
// pre_final_integrate1
// first time integration computations
// before Verlet step 2
//--------------------------------------------------------
void TimeIntegrator::pre_final_integrate1(double dt)
{
timeIntegrationMethod_->pre_final_integrate1(dt);
}
//--------------------------------------------------------
// pre_final_integrate2
// second time integration computations
// before Verlet step 2
//--------------------------------------------------------
void TimeIntegrator::pre_final_integrate2(double dt)
{
timeIntegrationMethod_->pre_final_integrate2(dt);
}
//--------------------------------------------------------
// post_final_integrate1
// first time integration computations
// after Verlet step 2
//--------------------------------------------------------
void TimeIntegrator::post_final_integrate1(double dt)
{
timeIntegrationMethod_->post_final_integrate1(dt);
}
//--------------------------------------------------------
// post_final_integrate2
// second time integration computations
// after Verlet step 2
//--------------------------------------------------------
void TimeIntegrator::post_final_integrate2(double dt)
{
timeIntegrationMethod_->post_final_integrate2(dt);
}
//--------------------------------------------------------
// post_process
// perform any post processing calculations
//--------------------------------------------------------
void TimeIntegrator::post_process(double dt)
{
timeIntegrationMethod_->post_process(dt);
}
//--------------------------------------------------------
// output
// add variables to output list
//--------------------------------------------------------
void TimeIntegrator::output(OUTPUT_LIST & outputData)
{
timeIntegrationMethod_->output(outputData);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeIntegrationMethod
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab data from ATC
//--------------------------------------------------------
TimeIntegrationMethod::TimeIntegrationMethod(TimeIntegrator * timeIntegrator) :
timeIntegrator_(timeIntegrator),
atcTransfer_(timeIntegrator_->get_atc_transfer())
{
// do nothing
}
};

View File

@ -1,280 +0,0 @@
#ifndef TIME_INTEGRATOR_H
#define TIME_INTEGRATOR_H
// ATC_Transfer headers
#include "MatrixLibrary.h"
#include "TimeFilter.h"
#include "ATC_TypeDefs.h"
using namespace std;
namespace ATC {
// forward declarations
class ATC_Transfer;
class TimeIntegrationMethod;
/**
* @class TimeIntegrator
* @brief Base class fo various time integrators for FE quantities
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeIntegrator
//--------------------------------------------------------
//--------------------------------------------------------
class TimeIntegrator {
public:
/** types of time integration */
enum TimeIntegrationType {
STEADY,
VERLET,
GEAR,
FRACTIONAL_STEP,
EXPLICIT,
IMPLICIT,
CRANK_NICOLSON
};
// constructor
TimeIntegrator(ATC_Transfer * atcTransfer,
TimeIntegrationType timeIntegrationType = STEADY);
// destructor
virtual ~TimeIntegrator();
/** parser/modifier */
virtual bool modify(int narg, char **arg){return false;};
/** pre time integration */
virtual void initialize(){needReset_ = false;};
/** flag if reset is needed */
bool need_reset() {return needReset_;};
// time step methods, corresponding to ATC_Transfer
/** first part of pre_initial_integrate */
virtual void pre_initial_integrate1(double dt);
/** second part of pre_initial_integrate */
virtual void pre_initial_integrate2(double dt);
/** first part of mid_initial_integrate */
virtual void mid_initial_integrate1(double dt);
/** second part of mid_initial_integrate */
virtual void mid_initial_integrate2(double dt);
/** first part of post_initial_integrate */
virtual void post_initial_integrate1(double dt);
/** second part of post_initial_integrate */
virtual void post_initial_integrate2(double dt);
/** first part of pre_final_integrate */
virtual void pre_final_integrate1(double dt);
/** second part of pre_final_integrate */
virtual void pre_final_integrate2(double dt);
/** first part of post_final_integrate */
virtual void post_final_integrate1(double dt);
/** second part of post_final_integrate */
virtual void post_final_integrate2(double dt);
/** post processing step */
virtual void post_process(double dt);
/** add output data */
virtual void output(OUTPUT_LIST & outputData);
// Member data access
/** access to time integration type */
TimeIntegrationType get_time_integration_type() const
{ return timeIntegrationType_; };
/** access to ATC Transfer object */
ATC_Transfer * get_atc_transfer() {return atcTransfer_;};
/** access to time filter object */
TimeFilter * get_time_filter() {return timeFilter_;};
/** access to time filter manager object */
TimeFilterManager * get_time_filter_manager() {return timeFilterManager_;};
/** force the integrator to be reset */
void force_reset() {needReset_ = true;};
/** force the integrator not to be reset */
void force_no_reset() {needReset_ = false;};
protected:
/** pointer to time integrator method */
TimeIntegrationMethod * timeIntegrationMethod_;
/** pointer to access ATC methods */
ATC_Transfer * atcTransfer_;
/** time filter for specific updates */
TimeFilter * timeFilter_;
/** time filter manager for getting time filtering info */
TimeFilterManager * timeFilterManager_;
/** type of integration scheme being used */
TimeIntegrationType timeIntegrationType_;
/** flat to reset data */
bool needReset_;
private:
// DO NOT define this
TimeIntegrator();
};
/**
* @class TimeIntegrationMethod
* @brief Base class fo various time integration methods
*/
//--------------------------------------------------------
//--------------------------------------------------------
// Class TimeIntegrationMethod
// Base class for time integration methods which
// update the FE quantities
//--------------------------------------------------------
//--------------------------------------------------------
class TimeIntegrationMethod {
public:
// constructor
TimeIntegrationMethod(TimeIntegrator * timeIntegrator);
// destructor
virtual ~TimeIntegrationMethod(){};
// time step methods, corresponding to ATC_Transfer and TimeIntegrator
/** first part of pre_initial_integrate */
virtual void pre_initial_integrate1(double dt){};
/** second part of pre_initial_integrate */
virtual void pre_initial_integrate2(double dt){};
/** first part of mid_initial_integrate */
virtual void mid_initial_integrate1(double dt){};
/** second part of mid_initial_integrate */
virtual void mid_initial_integrate2(double dt){};
/** first part of post_initial_integrate */
virtual void post_initial_integrate1(double dt){};
/** second part of post_initial_integrate */
virtual void post_initial_integrate2(double dt){};
/** first part of pre_final_integrate */
virtual void pre_final_integrate1(double dt){};
/** second part of pre_final_integrate */
virtual void pre_final_integrate2(double dt){};
/** first part of post_final_integrate */
virtual void post_final_integrate1(double dt){};
/** second part of post_final_integrate */
virtual void post_final_integrate2(double dt){};
/** post processing step */
virtual void post_process(double dt){};
/** add output data */
virtual void output(OUTPUT_LIST & outputData){};
protected:
/** owning time integrator */
TimeIntegrator * timeIntegrator_;
/** associated ATC transfer object */
ATC_Transfer * atcTransfer_;
private:
// DO NOT define this
TimeIntegrationMethod();
};
//--------------------------------------------------------
//--------------------------------------------------------
// time integration functions not associated
// with any particular class
//--------------------------------------------------------
//--------------------------------------------------------
static void gear1_4_predict(MATRIX & f,
MATRIX & dot_f,
MATRIX & ddot_f,
MATRIX & dddot_f,
double dt)
// 4th order Gear integrator for 1rst order ODE predictor step
{
f = f + dot_f*dt + ddot_f*(1./2.*dt*dt) + dddot_f*(1./6.*dt*dt*dt);
dot_f = dot_f + ddot_f*dt+dddot_f*(1./2.*dt*dt);
ddot_f = ddot_f + dddot_f*dt;
};
static void gear1_3_predict(MATRIX & f,
MATRIX & dot_f,
MATRIX & ddot_f,
double dt)
// 3rd order Gear integrator for 1rst order ODE predictor step
{
f = f + dot_f*dt + ddot_f*(1./2.*dt*dt);
dot_f = dot_f + ddot_f*dt;
};
static void gear1_4_correct(MATRIX & f,
MATRIX & dot_f,
MATRIX & ddot_f,
MATRIX & dddot_f,
const MATRIX & R_f,
double dt)
// 4th order Gear integrator for 1rst order ODE corrector step
{
f = f + (3./8.)*R_f;
dot_f = dot_f + (1./dt)*R_f;
ddot_f = ddot_f + (3./2./dt/dt)*R_f;
dddot_f = dddot_f + (1./dt/dt/dt)*R_f;
};
static void gear1_3_correct(MATRIX & f,
MATRIX & dot_f,
MATRIX & ddot_f,
const MATRIX & R_f,
double dt)
// 3rd order Gear integrator for 1rst order ODE corrector step
{
f = f + (5./12.)*R_f;
dot_f = dot_f + (1./dt)*R_f;
ddot_f = ddot_f + (1./dt/dt)*R_f;
};
static void explicit_1(MATRIX & f,
MATRIX & dot_f,
double dt)
// 1rst order explict ODE update
{
f = f + dt*dot_f;
};
static void explicit_2(MATRIX & f,
MATRIX & dot_f,
MATRIX & ddot_f,
double dt)
// 2nd order explict ODE update
{
f = f + dt*dot_f + .5*dt*dt*ddot_f;
};
};
#endif

View File

@ -1,109 +0,0 @@
#ifndef UTILITY_H
#define UTILITY_H
#include <iostream>
#include <ctime>
#undef near
using std::vector;
namespace Utility
{
///////////////////////////////////////////////////////////////////////////////////////////////
// Returns true if the value v is between min and max
///////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline bool InRange(const T &v, const T &min, const T &max)
{
return v >= min && v <= max;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Returns true if the value v is between min and max within the tolerance TOL
///////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline bool InRange(const T &v, const T &min, const T &max, const T &TOL)
{
return InRange(v, min-TOL, max+TOL);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Returns the value with the larger absolute value
///////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T MaxAbs(const T &a, const T &b)
{
return (a*a > b*b) ? a : b;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Returns the value with the smaller absolute value
///////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T MinAbs(const T &a, const T &b)
{
return (a*a < b*b) ? a : b;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// A simple Matlab like timing function
///////////////////////////////////////////////////////////////////////////////////////////////
inline double tictoc()
{
double t_new = clock() / (double) CLOCKS_PER_SEC;
static double t = t_new;
double dt = t_new - t;
t = t_new;
return dt;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Binary search between low and high for value (assumes array is sorted)
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline int SearchSorted(const T* A, T value, unsigned low, unsigned high)
{
unsigned mid;
while ((low+1)<=(high+1))
{
mid = (low + high) >> 1; // set mid to mean of high and low
if (A[mid] > value) high = mid-1; // mid was too high, reduce high
else if (A[mid] < value) low = mid+1; // mid was too low, increase low
else return mid;
}
return -1; // value not found in array, return -1
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Flat search between low and high for value (assumes array is NOT sorted)
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline int SearchUnsorted(const T* A, T value, unsigned low, unsigned high)
{
for (low; low<=high; low++) if (A[low] == value) return low;
return -1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Regular swap
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void Swap(T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Returns the sign of a double precision number
///////////////////////////////////////////////////////////////////////////////////////////////////
inline double Sign(double x) { return (x >= 0.0) ? 1.0 : -1.0; }
///////////////////////////////////////////////////////////////////////////////////////////////////
// Returns the sign of a single precision number
///////////////////////////////////////////////////////////////////////////////////////////////////
inline float Sign(float x) { return (x >= 0.0f) ? 1.0f : -1.0f; }
///////////////////////////////////////////////////////////////////////////////////////////////////
// Returns the pythagorean distance with the two lengths
///////////////////////////////////////////////////////////////////////////////////////////////////
inline double Norm(double x, double y) { return sqrt(x*x+y*y); }
///////////////////////////////////////////////////////////////////////////////////////////////////
// Returns square of a value
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T Square(T x) { return x*x; }
}
#endif

View File

@ -1,30 +0,0 @@
#include "DenseVector.h"
///////////////////////////////////////////////////////////////////////////////
//* performs a matrix-vector multiply with optional transposes BLAS version
void MultMv(const Matrix<double> &A, const Vector<double> &v, DenseVector<double> &c,
const bool At, double a, double b)
{
static char t[2] = {'N','T'};
char *ta=t+At;
int sA[2] = {A.nRows(), A.nCols()}; // sizes of A
int sV[2] = {v.size(), 1}; // sizes of v
GCK(A, v, sA[!At]!=sV[0], "MultAB<double>: matrix-vector multiply");
if (c.size() != sA[At])
{
c.resize(sA[At]); // set size of C to final size
c.zero();
}
// get pointers to the matrix sizes needed by BLAS
int *M = sA+At; // # of rows in op[A] (op[A] = A' if At='T' else A)
int *N = sV+1; // # of cols in op[B]
int *K = sA+!At; // # of cols in op[A] or # of rows in op[B]
double *pa=A.get_ptr(), *pv=v.get_ptr(), *pc=c.get_ptr();
#ifdef COL_STORAGE
dgemm_(ta, t, M, N, K, &a, pa, sA, pv, sV, &b, pc, M);
#else
dgemm_(t, ta, N, M, K, &a, pv, sV+1, pa, sA+1, &b, pc, N);
#endif
}

View File

@ -1,195 +0,0 @@
#ifndef VECTOR_H
#define VECTOR_H
#include "Matrix.h"
///////////////////////////////////////////////////////////////////////////////
// forward declarations ///////////////////////////////////////////////////////
//* Matrix-vector product
//template<typename T>
//void MultMv(const Matrix<T> &A, const Vector<T> &v, DenseVector<T> &c,
// const bool At=0, T a=1, T b=0);
/******************************************************************************
* abstract class Vector
******************************************************************************/
template<typename T>
class Vector : public Matrix<T>
{
public:
Vector() {}
Vector(const Vector<T> &c); // do not implement!
virtual ~Vector() {}
string tostring() const;
// pure virtual functions
virtual T operator()(INDEX i, INDEX j=0) const=0;
virtual T& operator()(INDEX i, INDEX j=0) =0;
virtual T operator[](INDEX i) const=0;
virtual T& operator[](INDEX i) =0;
virtual INDEX nRows() const=0;
virtual T* get_ptr() const=0;
virtual void resize(INDEX nRows, INDEX nCols=1, bool copy=0)=0;
virtual void reset(INDEX nRows, INDEX nCols=1, bool zero=0)=0;
virtual void copy(const T * ptr, INDEX nRows, INDEX nCols=1)=0;
void write_restart(FILE *f) const; // will be virtual
// output to matlab
using Matrix<T>::matlab;
void matlab(ostream &o, const string &s="v") const;
INDEX nCols() const;
bool in_range(INDEX i) const;
bool same_size(const Vector &m) const;
static bool same_size(const Vector &a, const Vector &b);
protected:
//* don't allow this
Vector& operator=(const Vector &r);
};
///////////////////////////////////////////////////////////////////////////////
//* performs a matrix-vector multiply with default naive implementation
template<typename T>
void MultMv(const Matrix<T> &A, const Vector<T> &v, DenseVector<T> &c,
const bool At, T a, T b)
{
const INDEX sA[2] = {A.nRows(), A.nCols()}; // m is sA[At] k is sA[!At]
const INDEX M=sA[At], K=sA[!At];
GCK(A, v, v.size()!=K, "MultAb<T>: matrix-vector multiply");
if (c.size() != M)
{
c.resize(M); // set size of C
c.zero(); // do not add result to C
}
else c *= b;
for (INDEX p=0; p<M; p++)
for (INDEX r=0; r<K; r++)
c[p] += A(p*!At+r*At, p*At+r*!At) * v[r];
}
///////////////////////////////////////////////////////////////////////////////
//* Operator for Matrix-vector product
template<typename T>
DenseVector<T> operator*(const Matrix<T> &A, const Vector<T> &b)
{
DenseVector<T> c;
MultMv(A, b, c, 0, 1.0, 0.0);
return c;
}
///////////////////////////////////////////////////////////////////////////////
//* Operator for Vector-matrix product
template<typename T>
DenseVector<T> operator*(const Vector<T> &a, const Matrix<T> &B)
{
DenseVector<T> c;
MultMv(B, a, c, 1, 1.0, 0.0);
return c;
}
///////////////////////////////////////////////////////////////////////////////
//* Multiply a vector by a scalar
template<typename T>
DenseVector<T> operator*(const Vector<T> &v, const T s)
{
DenseVector<T> r(v);
r*=s;
return r;
}
///////////////////////////////////////////////////////////////////////////////
//* Multiply a vector by a scalar - communitive
template<typename T>
DenseVector<T> operator*(const T s, const Vector<T> &v)
{
DenseVector<T> r(v);
r*=s;
return r;
}
///////////////////////////////////////////////////////////////////////////////
//* inverse scaling operator - must always create memory
template<typename T>
DenseMatrix<T> operator/(const Vector<T> &v, const T s)
{
DenseVector<T> r(v);
r*=(1.0/s); // for integer types this may be worthless
return ;
}
///////////////////////////////////////////////////////////////////////////////
//* Operator for Vector-Vector sum
template<typename T>
DenseVector<T> operator+(const Vector<T> &a, const Vector<T> &b)
{
DenseVector<T> c(a);
c+=b;
return c;
}
///////////////////////////////////////////////////////////////////////////////
//* Operator for Vector-Vector subtraction
template<typename T>
DenseVector<T> operator-(const Vector<T> &a, const Vector<T> &b)
{
DenseVector<T> c(a);
c-=b;
return c;
}
///////////////////////////////////////////////////////////////////////////////
// Template definitions ///////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//* output operator
template<typename T>
string Vector<T>::tostring() const
{
string s;
FORi s += string(i?"\t":"") + ATC_STRING::tostring(VIDX(i),5);
return s;
}
///////////////////////////////////////////////////////////////////////////////
//* Writes a matlab script defining the vector to the stream
template<typename T>
void Vector<T>::matlab(ostream &o, const string &s) const
{
o << s <<"=zeros(" << this->size() << ",1);\n";
FORi o << s << "("<<i+1<<") = " << VIDX(i) << ";\n";
}
///////////////////////////////////////////////////////////////////////////////
//* writes the vector data to a file
template <typename T>
void Vector<T>::write_restart(FILE *f) const
{
INDEX size = this->size();
fwrite(&size, sizeof(INDEX),1,f);
if (size) fwrite(this->get_ptr(), sizeof(T), this->size(), f);
}
///////////////////////////////////////////////////////////////////////////////
//* returns the number of columns; always 1
template<typename T>
inline INDEX Vector<T>::nCols() const
{
return 1;
}
///////////////////////////////////////////////////////////////////////////////
//* returns true if INDEX i is within the range of the vector
template<typename T>
bool Vector<T>::in_range(INDEX i) const
{
return i<this->size();
}
///////////////////////////////////////////////////////////////////////////////
//* returns true if m has the same number of elements this vector
template<typename T>
bool Vector<T>::same_size(const Vector &m) const
{
return this->size() == m.size();
}
///////////////////////////////////////////////////////////////////////////////
//* returns true if a and b have the same number of elements
template<typename T>
inline bool Vector<T>::same_size(const Vector &a, const Vector &b)
{
return a.same_size(b);
}
#endif

View File

@ -1,257 +0,0 @@
#include "XT_Function.h"
#include "ATC_Error.h"
namespace ATC {
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// XT_Function
//--------------------------------------------------------------------
//--------------------------------------------------------------------
XT_Function::XT_Function(int narg, double* args)
{
// NOTE need to adjust scaling to match input nodal coordinates
if (narg > 5 ) { // NOTE kludge for temporal only functions
x0[0] = args[0];
x0[1] = args[1];
x0[2] = args[2];
mask[0] = args[3];
mask[1] = args[4];
mask[2] = args[5];
}
else {
x0[0] = 0.0;
x0[1] = 0.0;
x0[2] = 0.0;
mask[0] = 0.0;
mask[1] = 0.0;
mask[2] = 0.0;
}
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// XT_Function_Mgr
//--------------------------------------------------------------------
//--------------------------------------------------------------------
XT_Function_Mgr * XT_Function_Mgr::myInstance_ = NULL;
// -----------------------------------------------------------------
// instance()
// -----------------------------------------------------------------
XT_Function_Mgr * XT_Function_Mgr::instance()
{
if (myInstance_ == NULL) {
myInstance_ = new XT_Function_Mgr();
}
return myInstance_;
}
// Destructor
XT_Function_Mgr::~XT_Function_Mgr()
{
// Delete all functions created using "new"
for (int i = 0; i < xtFunctionVec_.size(); i++) {
delete xtFunctionVec_[i];
}
}
// add user function into the if statement and assign returnFunction to it
XT_Function* XT_Function_Mgr::get_function(string & type, int nargs, double * args)
{
XT_Function * returnFunction;
if (type=="constant") {
returnFunction = new ConstantFunction(nargs,args);
}
else if (type=="temporal_ramp") {
returnFunction = new TemporalRamp(nargs,args);
}
else if (type=="linear")
returnFunction = new LinearFunction(nargs,args);
else if (type=="quadratic")
returnFunction = new QuadraticFunction(nargs,args);
else if (type=="sine")
returnFunction = new SineFunction(nargs,args);
else if (type=="gaussian")
returnFunction = new GaussianFunction(nargs,args);
else if (type=="gaussian_temporal_ramp")
returnFunction = new GaussianTemporalRamp(nargs,args);
else
throw ATC_Error(0,"Bad user function name");
xtFunctionVec_.push_back(returnFunction);
return returnFunction;
}
// add user function into the if statement and assign returnFunction to it
XT_Function* XT_Function_Mgr::get_function(char ** args, int nargs)
{
string type = args[0];
int narg = nargs -1;
double dargs[narg];
for (int i = 0; i < narg; ++i) dargs[i] = atof(args[i+1]);
return get_function(type, narg, dargs);
}
// add constant function
XT_Function* XT_Function_Mgr::get_constant_function(double c)
{
double args[1] = {c}; // NOTE kludge
XT_Function * returnFunction = new ConstantFunction(1,args);
xtFunctionVec_.push_back(returnFunction);
return (returnFunction);
}
XT_Function* XT_Function_Mgr::copy_XT_function(XT_Function* other)
{
string tag = other->get_tag();
XT_Function * returnFunction = NULL;
if (tag=="linear") {
LinearFunction * other_cast = (LinearFunction*) other;
returnFunction = new LinearFunction(*other_cast);
}
if (tag=="quadratic") {
QuadraticFunction * other_cast = (QuadraticFunction*) other;
returnFunction = new QuadraticFunction(*other_cast);
}
else if (tag=="sine") {
SineFunction * other_cast = (SineFunction*) other;
returnFunction = new SineFunction(*other_cast);
}
else if (tag=="gaussian") {
GaussianFunction * other_cast = (GaussianFunction*) other;
returnFunction = new GaussianFunction(*other_cast);
}
else if (tag=="gaussian_temporal_ramp") {
GaussianTemporalRamp * other_cast = (GaussianTemporalRamp*) other;
returnFunction = new GaussianTemporalRamp(*other_cast);
}
else if (tag=="temporal_ramp") {
TemporalRamp * other_cast = (TemporalRamp*) other;
returnFunction = new TemporalRamp(*other_cast);
}
return returnFunction;
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// ConstantFunction
//--------------------------------------------------------------------
//--------------------------------------------------------------------
ConstantFunction::ConstantFunction(int narg, double* args)
: XT_Function(narg,args),
C0(args[0])
{
tag = "constant";
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// LinearFunction
//--------------------------------------------------------------------
//--------------------------------------------------------------------
LinearFunction::LinearFunction(int narg, double* args)
: XT_Function(narg,args)
{
C0 = args[6];
tag = "linear";
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// QuadraticFunction
//--------------------------------------------------------------------
//--------------------------------------------------------------------
QuadraticFunction::QuadraticFunction(int narg, double* args)
: XT_Function(narg,args)
{
C0 = args[6];
C2[0] = args[7];
C2[1] = args[8];
C2[2] = args[9];
C2[3] = args[10];
C2[4] = args[11];
C2[5] = args[12];
tag = "quadratic";
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// SineFunction
//--------------------------------------------------------------------
//--------------------------------------------------------------------
SineFunction::SineFunction(int narg, double* args)
: XT_Function(narg,args)
{
C = args[6];
w = args[7];
tag = "sine";
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// GaussianFunction
//--------------------------------------------------------------------
//--------------------------------------------------------------------
GaussianFunction::GaussianFunction(int narg, double* args)
: XT_Function(narg,args)
{
tau = args[6];
C = args[7];
C0 = args[8];
tag = "gaussian";
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// GaussianTemporalRamp
//--------------------------------------------------------------------
//--------------------------------------------------------------------
GaussianTemporalRamp::GaussianTemporalRamp(int narg, double* args)
: GaussianFunction(narg,args)
{
tau_initial = args[9];
C_initial = args[10];
C0_initial = args[11];
double delta_t = args[12];
tau_slope = (tau - tau_initial)/delta_t;
C_slope = (C - C_initial)/delta_t;
C0_slope = (C0 - C0_initial)/delta_t;
tag = "gaussian_temporal_ramp";
}
double GaussianTemporalRamp::f(double* x, double t) {
tau = tau_initial + tau_slope*t;
C = C_initial + C_slope*t;
C0 = C0_initial + C0_slope*t;
return GaussianFunction::f(x,t);
}
double GaussianTemporalRamp::dfdt(double* x, double t) {
tau = tau_initial + tau_slope*t;
C = C_initial + C_slope*t;
C0 = C0_initial + C0_slope*t;
double dfdt = 0.;
dfdt += C_slope*exp(-(mask[0]*(x[0]-x0[0])*(x[0]-x0[0])
+mask[1]*(x[1]-x0[1])*(x[1]-x0[1])
+mask[2]*(x[2]-x0[2])*(x[2]-x0[2]))
/tau/tau);
dfdt += C*exp(2.*tau_slope*(mask[0]*(x[0]-x0[0])*(x[0]-x0[0])
+mask[1]*(x[1]-x0[1])*(x[1]-x0[1])
+mask[2]*(x[2]-x0[2])*(x[2]-x0[2]))
/tau/tau/tau);
dfdt += C0_slope;
return dfdt;
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// TemporalRamp
//--------------------------------------------------------------------
//--------------------------------------------------------------------
TemporalRamp::TemporalRamp(int narg, double* args)
: XT_Function(narg,args)
{
f_initial = args[0];
double f_final = args[1];
double delta_t = args[2];
slope = (f_final - f_initial)/delta_t;
tag = "temporal_ramp";
}
}

View File

@ -1,172 +0,0 @@
#ifndef XT_FUNCTION_H
#define XT_FUNCTION_H
#include <math.h>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
namespace ATC {
//------------------------------------------------------------------------
// base class
//------------------------------------------------------------------------
class XT_Function {
public:
XT_Function(int nargs, double* args);
~XT_Function(void) {};
const string & get_tag() { return tag;}
/** function value */
virtual inline double f(double* x, double t) {return 0.0;};
/** time derivative of function */
virtual inline double dfdt(double* x, double t) {return 0.0;};
/** 2nd time derivative of funtion */
virtual inline double ddfdt(double* x, double t) {return 0.0;};
/** 3rd time derivative of funtion */
virtual inline double dddfdt(double* x, double t) {return 0.0;};
protected:
/** mask : masks x,y,z dependence, x0 : origin */
double mask[3], x0[3];
/** tag : name of function */
string tag;
};
//------------------------------------------------------------------------
// manager
//------------------------------------------------------------------------
class XT_Function_Mgr {
public:
/** Static instance of this class */
static XT_Function_Mgr * instance();
XT_Function* get_function(string & type, int nargs, double * arg);
XT_Function* get_function(char ** arg, int nargs);
XT_Function* get_constant_function(double c);
XT_Function* copy_XT_function(XT_Function* other);
protected:
XT_Function_Mgr() {};
~XT_Function_Mgr();
/** Vector of ptrs to functions created thus far */
std::vector<XT_Function *> xtFunctionVec_;
private:
static XT_Function_Mgr * myInstance_;
};
//------------------------------------------------------------------------
// derived classes
//------------------------------------------------------------------------
/** a constant */
class ConstantFunction : public XT_Function {
public:
ConstantFunction(int nargs, double* args);
~ConstantFunction(void) {};
inline double f(double* x, double t)
{return C0;};
private :
double C0;
};
/** a linear in x-y-z */
class LinearFunction : public XT_Function {
public:
LinearFunction(int nargs, double* args);
~LinearFunction(void) {};
inline double f(double* x, double t)
{return mask[0]*(x[0]-x0[0])+mask[1]*(x[1]-x0[1])+mask[2]*(x[2]-x0[2]) + C0;};
private :
double C0;
};
/** a quadratic in x-y-z */
class QuadraticFunction : public XT_Function {
public:
QuadraticFunction(int nargs, double* args);
~QuadraticFunction(void) {};
inline double f(double* x, double t)
{return
C2[0]*(x[0]-x0[0])*(x[0]-x0[0])+
C2[1]*(x[1]-x0[1])*(x[1]-x0[1])+
C2[2]*(x[2]-x0[2])*(x[2]-x0[2])+
2.0*C2[3]*(x[0]-x0[0])*(x[1]-x0[1]) +
2.0*C2[4]*(x[0]-x0[0])*(x[2]-x0[2]) +
2.0*C2[5]*(x[1]-x0[1])*(x[2]-x0[2]) +
mask[0]*(x[0]-x0[0])+mask[1]*(x[1]-x0[1])+mask[2]*(x[2]-x0[2]) + C0;};
private :
double C0, C2[6]; // C2 1:xx 2:yy 3:zz 4:xy|yx 5:xz|zx 6:yz|zy
};
class SineFunction : public XT_Function {
public:
SineFunction(int nargs, double* args);
~SineFunction(void);
inline double f(double* x, double t)
{return C*sin( mask[0]*(x[0]-x0[0])
+mask[1]*(x[1]-x0[1])
+mask[2]*(x[2]-x0[2]) - w*t);};
private :
double C, w;
};
/** a spatial gaussian function */
class GaussianFunction : public XT_Function {
public:
GaussianFunction(int nargs, double* args);
~GaussianFunction(void){};
// 1/(2 pi \sigma)^(n/2) exp(-1/2 x.x/\sigma^2 ) for n = dimension
inline double f(double* x, double t)
{return C*exp(-(mask[0]*(x[0]-x0[0])*(x[0]-x0[0])
+mask[1]*(x[1]-x0[1])*(x[1]-x0[1])
+mask[2]*(x[2]-x0[2])*(x[2]-x0[2]))/tau/tau) + C0;};
protected:
double tau, C, C0;
};
/** a spatial gaussian function that has variables ramp up in time */
class GaussianTemporalRamp : public GaussianFunction {
public:
GaussianTemporalRamp(int nargs, double* args);
~GaussianTemporalRamp(void){};
double f(double* x, double t);
double dfdt(double* x, double t);
protected:
double tau_initial, tau_slope;
double C_initial, C_slope;
double C0_initial, C0_slope;
};
/** a ramp in time */
class TemporalRamp : public XT_Function {
public:
TemporalRamp(int nargs, double* args);
~TemporalRamp(void) {};
inline double f(double* x, double t)
{return f_initial + slope*t;};
inline double dfdt(double* x, double t)
{return slope;};
private :
double f_initial, slope;
};
}
#endif

4541
lib/atc/build.log Normal file

File diff suppressed because it is too large Load Diff

88
lib/atc/svn.stdout Normal file
View File

@ -0,0 +1,88 @@
Deleting atc/ATC_Error.h
Deleting atc/ATC_HardyKernel.cpp
Deleting atc/ATC_HardyKernel.h
Deleting atc/ATC_Transfer.cpp
Deleting atc/ATC_Transfer.h
Deleting atc/ATC_TransferHardy.cpp
Deleting atc/ATC_TransferHardy.h
Deleting atc/ATC_TransferThermal.cpp
Deleting atc/ATC_TransferThermal.h
Deleting atc/ATC_TransferUtility.cpp
Deleting atc/ATC_TypeDefs.h
Deleting atc/Array.h
Deleting atc/Array2D.h
Deleting atc/AtomicRegulator.cpp
Deleting atc/AtomicRegulator.h
Deleting atc/CG.h
Deleting atc/CloneVector.h
Deleting atc/DenseMatrix.h
Deleting atc/DenseVector.h
Deleting atc/DiagonalMatrix.h
Deleting atc/ElasticTimeIntegrator.cpp
Deleting atc/ElasticTimeIntegrator.h
Deleting atc/ElectronFlux.cpp
Deleting atc/ElectronFlux.h
Deleting atc/ElectronHeatCapacity.cpp
Deleting atc/ElectronHeatCapacity.h
Deleting atc/ElectronHeatFlux.cpp
Deleting atc/ElectronHeatFlux.h
Deleting atc/ElectronPhononExchange.cpp
Deleting atc/ElectronPhononExchange.h
Deleting atc/ExtrinsicModel.cpp
Deleting atc/ExtrinsicModel.h
Deleting atc/ExtrinsicModelTwoTemperature.cpp
Deleting atc/ExtrinsicModelTwoTemperature.h
Deleting atc/FE_Element.cpp
Deleting atc/FE_Element.h
Deleting atc/FE_Engine.cpp
Deleting atc/FE_Engine.h
Deleting atc/FE_Mesh.cpp
Deleting atc/FE_Mesh.h
Deleting atc/FieldEulerIntegrator.cpp
Deleting atc/FieldEulerIntegrator.h
Deleting atc/GMRES.h
Deleting atc/ImplicitSolveOperator.cpp
Deleting atc/ImplicitSolveOperator.h
Deleting atc/Kinetostat.cpp
Deleting atc/Kinetostat.h
Deleting atc/LammpsInterface.cpp
Deleting atc/LammpsInterface.h
Adding atc/Makefile.lammps
Adding atc/Makefile.mpic++
Deleting atc/Material.cpp
Deleting atc/Material.h
Deleting atc/Matrix.cpp
Deleting atc/Matrix.h
Deleting atc/MatrixDef.h
Deleting atc/MatrixLibrary.h
Deleting atc/OutputManager.cpp
Deleting atc/OutputManager.h
Deleting atc/PhysicsModel.h
Deleting atc/PhysicsModelThermal.cpp
Deleting atc/PhysicsModelThermal.h
Deleting atc/PhysicsModelTwoTemperature.cpp
Deleting atc/PhysicsModelTwoTemperature.h
Deleting atc/PrescribedDataManager.cpp
Deleting atc/PrescribedDataManager.h
Deleting atc/Quadrature.h
Deleting atc/Solver.cpp
Deleting atc/Solver.h
Deleting atc/SparseMatrix-inl.h
Deleting atc/SparseMatrix.h
Deleting atc/SparseVector-inl.h
Deleting atc/SparseVector.h
Deleting atc/StringManip.h
Deleting atc/Thermostat.cpp
Deleting atc/Thermostat.h
Deleting atc/TimeFilter.cpp
Deleting atc/TimeFilter.h
Deleting atc/TimeIntegrator.cpp
Deleting atc/TimeIntegrator.h
Deleting atc/Utility.h
Deleting atc/Vector.cpp
Deleting atc/Vector.h
Deleting atc/XT_Function.cpp
Deleting atc/XT_Function.h
Adding atc/build.log
Adding atc/svn.stdout
Transmitting file data ...