lammps/lib/atc/AtomicRegulator.cpp

420 lines
15 KiB
C++
Raw Normal View History

// 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()");
}
};