#ifndef PRESCRIBED_DATA_MANAGER_H
#define PRESCRIBED_DATA_MANAGER_H
#include <vector>
#include <map>
#include <set>
#include <string>
#include <utility>
#include "ATC_TypeDefs.h"
#include "Function.h"
#include "PhysicsModel.h"
#include "FE_Element.h"
#include "Array.h"
#include "Array2D.h"
#include "FE_Engine.h"
namespace ATC {
class PrescribedDataManager {
public:
PrescribedDataManager(FE_Engine * feEngine,
const std::map<FieldName,int> & fieldSize);
~PrescribedDataManager();
void add_field(FieldName fieldName, int size);
void remove_field(FieldName fieldName);
std::map < FieldName, Array2D < XT_Function * > > *
ics(void) { return & ics_; }
const Array2D < XT_Function * > *
ics(FieldName fieldName) { return & ics_[fieldName]; }
const std::map < FieldName, BCS > & bcs(void) const
{
return bcValues_;
}
const BCS & bcs(const FieldName fieldName) const
{
return (bcValues_.find(fieldName))->second;
}
void bcs
(const FieldName fieldName, const std::set<int> nodes, BCS & bcs,
bool local = false) const;
std::map < FieldName, Array2D < XT_Function * > > *
bc_functions(void) { return & bcs_; }
const Array2D < XT_Function * > *
bc_functions(FieldName fieldName) { return & bcs_[fieldName]; }
ROBIN_SURFACE_SOURCE * robin_functions(void) { return & faceSourcesRobin_; }
bool has_robin_source(FieldName fieldName) const {
return ((faceSourcesRobin_.find(fieldName)->second).size() > 0) ;
}
const std::map<PAIR, Array<UXT_Function*> > *
robin_functions(FieldName fieldName) { return & faceSourcesRobin_[fieldName]; }
OPEN_SURFACE * open_faces(void) { return & facesOpen_; }
bool has_open_face(FieldName fieldName) const {
return ((facesOpen_.find(fieldName)->second).size() > 0) ;
}
const std::set<PAIR> *
open_faces(FieldName fieldName) { return & facesOpen_[fieldName]; }
bool is_initially_fixed(const int node,
const FieldName thisField,
const int thisIndex=0) const
{
return ((ics_.find(thisField)->second))(node,thisIndex) ? true : false ;
}
bool is_fixed(const int node,
const FieldName thisField,
const int thisIndex=0) const
{
return ((bcs_.find(thisField)->second))(node,thisIndex) ? true : false ;
}
std::set<int> fixed_nodes(
const FieldName thisField,
const int thisIndex=0) const
{
std::set<int> fixed;
const Array2D < XT_Function *> & bcs = bcs_.find(thisField)->second;
for (int node = 0; node < bcs.nRows() ; node++) {
if (bcs(node,thisIndex)) fixed.insert(node);
}
return fixed;
}
void fixed_nodes(
const FieldName thisField,
std::set<int> & fixed,
const int thisIndex=0) const
{
const Array2D < XT_Function *> & bcs = bcs_.find(thisField)->second;
for (int node = 0; node < bcs.nRows() ; node++) {
if (bcs(node,thisIndex)) fixed.insert(node);
}
}
bool all_fixed(
const FieldName thisField,
const int thisIndex=-1) const
{
if (thisIndex < 0) {
bool allFixed = (fixed_nodes(thisField,0).size() == static_cast<unsigned>(nNodes_) );
int ndof = (fieldSizes_.find(thisField)->second);
for (int j = 1; j < ndof; ++j) {
allFixed = allFixed && (fixed_nodes(thisField,j).size() == static_cast<unsigned>(nNodes_));
}
return allFixed;
}
else {
return (fixed_nodes(thisField,thisIndex).size() == static_cast<unsigned>(nNodes_) );
}
}
bool none_fixed(
const FieldName thisField,
const int thisIndex=0) const
{
return (fixed_nodes(thisField,thisIndex).size() == 0 )
&& (faceSourcesRobin_.size() == 0)
&& (facesOpen_.size() == 0);
}
std::set<int> flux_face_nodes(
const FieldName thisField,
const int thisIndex=0) const
{
std::set<int> fluxes;
int *toInsert = new int[nNodes_];
for (int i = 0; i < nNodes_; ++i) toInsert[i] = 0;
const std::map < std::pair <int, int>, Array < XT_Function * > > & sources = faceSources_.find(thisField)->second;
std::map < std::pair <int, int>, Array < XT_Function * > >::const_iterator fset_iter;
for (fset_iter = sources.begin(); fset_iter != sources.end(); fset_iter++) {
int ielem = fset_iter->first.first;
if (!feEngine_->fe_mesh()->is_owned_elt(ielem)) continue;
const Array <XT_Function*> &fs = fset_iter->second;
if (fs(thisIndex)) {
Array<int> nodes;
feEngine_->face_connectivity(fset_iter->first,nodes);
for (int node = 0; node < nodes.size(); node++) {
toInsert[nodes(node)] = 1;
}
}
}
LammpsInterface::instance()->logical_or(MPI_IN_PLACE, toInsert, nNodes_);
for (int node = 0; node < nNodes_; ++node) {
if (toInsert[node]) fluxes.insert(node);
}
delete[] toInsert;
return fluxes;
}
void flux_face_nodes(
const FieldName thisField,
std::set<int> fluxes,
const int thisIndex=0) const
{
int *toInsert = new int[nNodes_];
for (int i = 0; i < nNodes_; ++i) toInsert[i] = 0;
const std::map < std::pair <int, int>, Array < XT_Function * > > & sources = faceSources_.find(thisField)->second;
std::map < std::pair <int, int>, Array < XT_Function * > >::const_iterator fset_iter;
for (fset_iter = sources.begin(); fset_iter != sources.end(); fset_iter++) {
int ielem = fset_iter->first.first;
if (!feEngine_->fe_mesh()->is_owned_elt(ielem)) continue;
const Array <XT_Function*> &fs = fset_iter->second;
if (fs(thisIndex)) {
Array<int> nodes;
feEngine_->face_connectivity(fset_iter->first,nodes);
for (int node = 0; node < nodes.size(); node++) {
toInsert[nodes(node)] = 1;
}
}
}
LammpsInterface::instance()->logical_or(MPI_IN_PLACE, toInsert, nNodes_);
for (int node = 0; node < nNodes_; ++node) {
if (toInsert[node]) fluxes.insert(node);
}
delete[] toInsert;
}
std::set<int> flux_element_nodes(
const FieldName thisField,
const int thisIndex=0) const
{
std::set<int> fluxes;
int *toInsert = new int[nNodes_];
for (int i = 0; i < nNodes_; ++i) toInsert[i] = 0;
const Array2D < XT_Function *> & sources = elementSources_.find(thisField)->second;
for (int element = 0; element < sources.nRows() ; element++) {
if (!feEngine_->fe_mesh()->is_owned_elt(element)) continue;
if (sources(element,thisIndex)) {
Array<int> nodes;
feEngine_->element_connectivity(element,nodes);
for (int node = 0; node < nodes.size(); node++) {
toInsert[nodes(node)] = 1;
}
}
}
LammpsInterface::instance()->logical_or(MPI_IN_PLACE, toInsert, nNodes_);
for (int node = 0; node < nNodes_; ++node) {
if (toInsert[node]) fluxes.insert(node);
}
delete[] toInsert;
return fluxes;
}
void flux_element_nodes(
const FieldName thisField,
std::set<int> fluxes,
const int thisIndex=0) const
{
int *toInsert = new int[nNodes_];
for (int i = 0; i < nNodes_; ++i) toInsert[i] = 0;
const Array2D < XT_Function *> & sources = elementSources_.find(thisField)->second;
for (int element = 0; element < sources.nRows() ; element++) {
if (!feEngine_->fe_mesh()->is_owned_elt(element)) continue;
if (sources(element,thisIndex)) {
Array<int> nodes;
feEngine_->element_connectivity(element,nodes);
for (int node = 0; node < nodes.size(); node++) {
toInsert[nodes(node)] = 1;
}
}
}
LammpsInterface::instance()->logical_or(MPI_IN_PLACE, toInsert, nNodes_);
for (int node = 0; node < nNodes_; ++node) {
if (toInsert[node]) fluxes.insert(node);
}
delete[] toInsert;
}
bool no_fluxes(
const FieldName thisField,
const int thisIndex=0) const
{
return ((flux_element_nodes(thisField,thisIndex).size() == 0) &&
(flux_face_nodes(thisField,thisIndex).size() == 0));
}
void fix_initial_field (const std::string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void fix_field (const std::set<int> nodeset,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void fix_field (const std::string nodesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void unfix_field (const std::string nodesetName,
const FieldName thisField,
const int thisIndex);
void fix_field (const int nodeId,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void unfix_field (const int nodeId,
const FieldName thisField,
const int thisIndex);
void fix_flux (const std::string facesetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void unfix_flux(const std::string facesetName,
const FieldName thisField,
const int thisIndex);
void fix_robin (const std::string facesetName,
const FieldName thisField,
const int thisIndex,
const UXT_Function * f);
void unfix_robin(const std::string facesetName,
const FieldName thisField,
const int thisIndex);
void fix_open (const std::string facesetName,
const FieldName thisField);
void unfix_open(const std::string facesetName,
const FieldName thisField);
void fix_source(const std::string elemsetName,
const FieldName thisField,
const int thisIndex,
const XT_Function * f);
void fix_source( const FieldName thisField,
const int thisIndex,
const std::set<std::pair<int,double> > & source);
void unfix_source(const std::string elemsetName,
const FieldName thisField,
const int thisIndex);
void set_initial_conditions(const double time,
FIELDS & fields,
FIELDS & dot_fields,
FIELDS & ddot_fields,
FIELDS & dddot_fields);
void set_fixed_fields(const double time,
FIELDS & fields,
FIELDS & dot_fields,
FIELDS & ddot_fields,
FIELDS & dddot_fields);
void set_fixed_field(const double time,
const FieldName & fieldName,
DENS_MAT & fieldMatrix);
void set_fixed_dfield(const double time,
const FieldName & fieldName,
DENS_MAT & dfieldMatrix);
void set_sources(const double time,
FIELDS & sources);
void print(void);
private:
int nNodes_;
int nElems_;
std::map<FieldName,int> fieldSizes_;
FE_Engine * feEngine_;
std::map < FieldName, Array2D < XT_Function * > > ics_;
std::map < FieldName, Array2D < XT_Function * > > bcs_;
std::map < FieldName, std::map < std::pair <int, int>, Array < XT_Function * > > >
faceSources_;
std::map < FieldName, std::map < std::pair <int, int>, Array < UXT_Function * > > >
faceSourcesRobin_;
std::map < FieldName, std::set < std::pair <int, int> > >
facesOpen_;
std::map < FieldName, Array2D < XT_Function * > > elementSources_;
FIELDS nodalSources_;
std::map < FieldName, BCS > bcValues_;
};
}
#endif