FEI Version of the Day
fei_Lookup_Impl.cpp
00001 /*--------------------------------------------------------------------*/
00002 /*    Copyright 2005 Sandia Corporation.                              */
00003 /*    Under the terms of Contract DE-AC04-94AL85000, there is a       */
00004 /*    non-exclusive license for use of this work by or on behalf      */
00005 /*    of the U.S. Government.  Export of this program may require     */
00006 /*    a license from the United States Government.                    */
00007 /*--------------------------------------------------------------------*/
00008 
00009 #include <fei_macros.hpp>
00010 
00011 #include <fei_Lookup_Impl.hpp>
00012 
00013 #include <fei_VectorSpace.hpp>
00014 
00015 #include <snl_fei_Utils.hpp>
00016 #include <fei_TemplateUtils.hpp>
00017 #include <fei_CommUtils.hpp>
00018 
00019 #include <snl_fei_Constraint.hpp>
00020 
00021 #include <snl_fei_SubdMsgHandler.hpp>
00022 
00023 #undef fei_file
00024 #define fei_file "fei_Lookup_Impl.cpp"
00025 #include <fei_ErrMacros.hpp>
00026 
00027 //----------------------------------------------------------------------------
00028 fei::Lookup_Impl::Lookup_Impl(fei::SharedPtr<fei::MatrixGraph> matGraph,
00029           int nodeIDType)
00030   : matGraph_(matGraph),
00031     ptBlkMap_(NULL),
00032     vspace_(),
00033     nodeIDType_(nodeIDType),
00034     nodenumPairs_(),
00035     eqnnumPairs_(),
00036     nodenumSubdomainDB_(),
00037     databasesBuilt_(false),
00038     fieldIDs_(),
00039     fieldSizes_(),
00040     elemBlockIDs_(0, 4),
00041     fieldIDs_2D_(),
00042     workspace_()
00043 {
00044   vspace_ = matGraph_->getRowSpace();
00045   ptBlkMap_ = vspace_->getPointBlockMap();
00046 
00047   int err = buildDatabases();
00048   if (err != 0) {
00049     voidERReturn;
00050   }
00051 }
00052 
00053 //----------------------------------------------------------------------------
00054 fei::Lookup_Impl::~Lookup_Impl()
00055 {
00056   fei::destroyValues(nodenumSubdomainDB_);
00057   nodenumSubdomainDB_.clear();
00058 }
00059 
00060 //----------------------------------------------------------------------------
00061 int fei::Lookup_Impl::getEqnNumber(int nodeNumber, int fieldID)
00062 {
00063   std::map<int,fei::Record<int>*>::iterator
00064     nnp_iter = nodenumPairs_.find(nodeNumber);
00065 
00066   if (nnp_iter == nodenumPairs_.end()) return(-1);
00067 
00068   fei::Record<int>* node = (*nnp_iter).second;
00069 
00070   std::vector<int>& eqnNums = vspace_->getEqnNumbers();
00071   int* eqnNumbers = eqnNums.size() > 0 ? &eqnNums[0] : NULL;
00072   if (eqnNumbers == NULL) {
00073     throw std::runtime_error("Fatal error in fei::Lookup_Impl::getEqnNumber");
00074   }
00075   eqnNumbers += node->getOffsetIntoEqnNumbers();
00076   int numInstances = 1;
00077   int offset = -1;
00078   node->getFieldMask()->getFieldEqnOffset(fieldID, offset, numInstances);
00079   return(eqnNumbers[offset]);
00080 }
00081 
00082 //----------------------------------------------------------------------------
00083 int fei::Lookup_Impl::getAssociatedNodeNumber(int eqnNumber)
00084 {
00085   std::map<int,fei::Record<int>*>::iterator
00086     enp_iter = eqnnumPairs_.find(eqnNumber);
00087 
00088   if (enp_iter == eqnnumPairs_.end()) return(-1);
00089 
00090   fei::Record<int>* node = (*enp_iter).second;
00091 
00092   return( node->getNumber() );
00093 }
00094 
00095 //----------------------------------------------------------------------------
00096 int fei::Lookup_Impl::getAssociatedNodeID(int eqnNumber)
00097 {
00098   std::map<int,fei::Record<int>*>::iterator
00099     enp_iter = eqnnumPairs_.find(eqnNumber);
00100 
00101   if (enp_iter == eqnnumPairs_.end()) return(-1);
00102 
00103   fei::Record<int>* node = (*enp_iter).second;
00104 
00105   return( node->getID() );
00106 }
00107 
00108 //----------------------------------------------------------------------------
00109 int fei::Lookup_Impl::getAssociatedFieldID(int eqnNumber)
00110 {
00111   std::map<int,fei::Record<int>*>::iterator
00112     enp_iter = eqnnumPairs_.find(eqnNumber);
00113 
00114   if (enp_iter == eqnnumPairs_.end()) return(-1);
00115 
00116   fei::Record<int>* node = (*enp_iter).second;
00117 
00118   fei::FieldMask* fm = node->getFieldMask();
00119   const std::vector<int>& fieldIDs = fm->getFieldIDs();
00120   const std::vector<int>& fieldSizes = fm->getFieldSizes();
00121 
00122   const std::vector<int>& eqnNumbers = vspace_->getEqnNumbers();
00123 
00124   int baseEqnOffset = node->getOffsetIntoEqnNumbers();
00125   int numNodalEqns = fm->getNumIndices();
00126 
00127   if (baseEqnOffset + numNodalEqns > (int)eqnNumbers.size()) {
00128     throw std::runtime_error("fei::Lookup_Impl::getAssociatedFieldID ERROR, nodal eqn offset out of range.");
00129   }
00130 
00131   int offset = 0;
00132   int eqn = eqnNumbers[baseEqnOffset];
00133   while(eqn < eqnNumber && offset < numNodalEqns) {
00134     eqn = eqnNumbers[baseEqnOffset + ++offset];
00135   }
00136 
00137   if (eqn != eqnNumber) {
00138     throw std::runtime_error("fei::Lookup_Impl::getAssociatedFieldID ERROR, eqnNumber not found");
00139   }
00140 
00141   int fieldSize_total = 0;
00142   for(size_t i=0; i<fieldSizes.size(); ++i) {
00143     fieldSize_total += fieldSizes[i];
00144     if (fieldSize_total > offset) {
00145       return fieldIDs[i];
00146     }
00147   }
00148 
00149   return -1;
00150 }
00151 
00152 //----------------------------------------------------------------------------
00153 bool fei::Lookup_Impl::isInLocalElement(int nodeNumber)
00154 {
00155   std::map<int,std::vector<int>* >::iterator
00156     nns_iter = nodenumSubdomainDB_.find(nodeNumber);
00157   if (nns_iter != nodenumSubdomainDB_.end()) {
00158     return( true );
00159   }
00160 
00161   std::map<int,fei::Record<int>*>::iterator
00162     nnp_iter = nodenumPairs_.find(nodeNumber);
00163 
00164   return(nnp_iter != nodenumPairs_.end() ? true : false);
00165 }
00166 
00167 //----------------------------------------------------------------------------
00168 int fei::Lookup_Impl::getOffsetIntoBlkEqn(int blkEqn, int ptEqn)
00169 {
00170   //assume blkEqn is a node-number, for now.
00171   std::map<int,fei::Record<int>*>::iterator
00172     nnp_iter = nodenumPairs_.find(blkEqn);
00173 
00174   if (nnp_iter == nodenumPairs_.end()) return(-1);
00175 
00176   fei::Record<int>* node = (*nnp_iter).second;
00177 
00178   int eqn = vspace_->getEqnNumbers()[node->getOffsetIntoEqnNumbers()];
00179   return(ptEqn - eqn);
00180 }
00181 
00182 //----------------------------------------------------------------------------
00183 int fei::Lookup_Impl::buildDatabases()
00184 {
00185   if (databasesBuilt_) return(0);
00186 
00187   snl_fei::RecordCollection* collection = NULL;
00188   int err = vspace_->getRecordCollection(nodeIDType_, collection);
00189   if (err != 0) {
00190     //probably means that vspace_ doesn't have 'nodeIDType_', so we'll skip the
00191     //rest of this function. It's not a problem if vspace_ doesn't have nodeIDType_.
00192     return(0);
00193   }
00194 
00195   std::vector<int>& vspcEqnNumbers = vspace_->getEqnNumbers();
00196 
00197   snl_fei::RecordCollection::map_type& rmap = collection->getRecords();
00198 
00199   snl_fei::RecordCollection::map_type::iterator
00200     r_iter = rmap.begin(),
00201     r_end = rmap.end();
00202 
00203   for(; r_iter != r_end; ++r_iter) {
00204     fei::Record<int>* node = (*r_iter).second;
00205 
00206     std::pair<int,fei::Record<int>* > int_node_pair(node->getNumber(), node);
00207 
00208     nodenumPairs_.insert(int_node_pair);
00209 
00210     int numEqns = node->getFieldMask()->getNumIndices();
00211     int* eqnNumbers = &vspcEqnNumbers[0]
00212                     + node->getOffsetIntoEqnNumbers();
00213 
00214     for(int eq=0; eq<numEqns; ++eq) {
00215       std::pair<int,fei::Record<int>* > eqn_node_pair(eqnNumbers[eq], node);
00216       eqnnumPairs_.insert(eqn_node_pair);
00217     }
00218   }
00219 
00220   MPI_Comm comm = matGraph_->getRowSpace()->getCommunicator();
00221 
00222   int numLocalLagrangeConstraints = matGraph_->getLagrangeConstraints().size();
00223 
00224   int numGlobalLagrangeConstraints = 0;
00225   fei::GlobalSum(comm, numLocalLagrangeConstraints, numGlobalLagrangeConstraints);
00226 
00227   bool noconstraints = numGlobalLagrangeConstraints<1 ? true : false;
00228 
00229   fei::SharedIDs<int> subdomainIDs;
00230   fei::SharedIDs<int>& sharedIDs = vspace_->getSharedIDs_private(nodeIDType_);
00231 
00232   if (noconstraints == false) {
00233     snl_fei::SubdMsgHandler subdmsghndlr(collection, &sharedIDs, &subdomainIDs);
00234 
00235     if (vspace_->ownerPatterns_.size() > 0 && vspace_->sharerPatterns_.size() > 0) {
00236       subdmsghndlr.setSendPattern(vspace_->ownerPatterns_.find(nodeIDType_)->second);
00237       subdmsghndlr.setRecvPattern(vspace_->sharerPatterns_.find(nodeIDType_)->second);
00238       CHK_ERR( fei::exchange(comm, &subdmsghndlr) );
00239     }
00240 
00241     //Now the subdomainIDs object contains a mapping from each shared ID to a
00242     //list of processors that have that ID in their local subdomain.
00243     //So what we'll do next is run through the list of IDs in subdomainIDs and
00244     //for each ID, store the corresponding node-number in a database together
00245     //with a pointer to a list (vector) of the subdomain-processors.
00246   }
00247   else {
00248     subdomainIDs = sharedIDs;
00249   }
00250 
00251   int local_proc = fei::localProc(comm);
00252 
00253   fei::SharedIDs<int>::map_type& sdIDTable = subdomainIDs.getSharedIDs();
00254   fei::SharedIDs<int>::map_type::iterator
00255     sd_iter = sdIDTable.begin(),
00256     sd_end  = sdIDTable.end();
00257 
00258   for(int i=0; sd_iter != sd_end; ++i, ++sd_iter) {
00259     int id = sd_iter->first;
00260     std::set<int>& procList = sd_iter->second;
00261 
00262     fei::Record<int>* node = collection->getRecordWithID(id);
00263     if (node == NULL) {
00264       ERReturn(-1);
00265     }
00266 
00267     std::vector<int>* newarray = new std::vector<int>;
00268     std::set<int>::const_iterator
00269       p_iter = procList.begin(), p_end = procList.end();
00270 
00271     for(; p_iter != p_end; ++p_iter) {
00272       int proc = *p_iter;
00273       newarray->push_back(proc);
00274     }
00275 
00276     if (node->isInLocalSubdomain_) {
00277       fei::sortedListInsert(local_proc, *newarray);
00278     }
00279 
00280     nodenumSubdomainDB_.insert(std::pair<int,std::vector<int>*>(node->getNumber(), newarray));
00281   }
00282 
00283   databasesBuilt_ = true;
00284   return(0);
00285 }
00286 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends