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:
@ -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
|
|
||||||
@ -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; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -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
@ -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
@ -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
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
@ -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
|
|
||||||
170
lib/atc/Array.h
170
lib/atc/Array.h
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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()");
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
|
|
||||||
79
lib/atc/CG.h
79
lib/atc/CG.h
@ -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;
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
|
|
||||||
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
@ -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"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -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> ¶meters);
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
@ -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
|
|
||||||
1315
lib/atc/FE_Mesh.cpp
1315
lib/atc/FE_Mesh.cpp
File diff suppressed because it is too large
Load Diff
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
150
lib/atc/GMRES.h
150
lib/atc/GMRES.h
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
@ -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
@ -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
|
|
||||||
@ -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_; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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
5
lib/atc/Makefile.lammps
Normal 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
29
lib/atc/Makefile.mpic++
Normal 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)
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
664
lib/atc/Matrix.h
664
lib/atc/Matrix.h
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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";
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
@ -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
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
195
lib/atc/Vector.h
195
lib/atc/Vector.h
@ -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
|
|
||||||
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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
4541
lib/atc/build.log
Normal file
File diff suppressed because it is too large
Load Diff
88
lib/atc/svn.stdout
Normal file
88
lib/atc/svn.stdout
Normal 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 ...
|
||||||
Reference in New Issue
Block a user