#include "PrescribedDataManager.h" #include "FE_Engine.h" #include "ATC_Error.h" #include namespace ATC { //------------------------------------------------------------------------- // PrescribedDataManager //------------------------------------------------------------------------- PrescribedDataManager::PrescribedDataManager (FE_Engine * feEngine, const map & fieldSize) : feEngine_(feEngine), fieldSizes_(fieldSize) { // construct & initialize internal data nNodes_ = feEngine_->get_nNodes(); nElems_ = feEngine_->get_nElements(); map::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 nodeSet = (feEngine_->get_feMesh())->get_nodeset(nodesetName); set::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 nodeSet = (feEngine_->get_feMesh())->get_nodeset(nodesetName); set::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 nodeSet = (feEngine_->get_feMesh())->get_nodeset(nodesetName); set::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 > * fset = & ( (feEngine_->get_feMesh())->get_faceset(facesetName)); set< pair >::const_iterator iset; for (iset = fset->begin(); iset != fset->end(); iset++) { pair 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 > * fset = & ( (feEngine_->get_feMesh())->get_faceset(facesetName)); set< pair >::const_iterator iset; for (iset = fset->begin(); iset != fset->end(); iset++) { pair 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 elemSet = (feEngine_->get_feMesh())->get_elementset(elemsetName); set::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 elemSet = (feEngine_->get_feMesh())->get_elementset(elemsetName); set::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::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::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::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::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 fieldMask(NUM_FIELDS); fieldMask = false; map::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 conn; map::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, Array < XT_Function * > > & fset = faceSources_[thisField]; map < pair, Array < XT_Function * > > ::const_iterator iset; for (iset = fset.begin(); iset != fset.end(); iset++) { pair 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