fei_VectorSpace.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_sstream.hpp"
00010 #include "fei_fstream.hpp"
00011 
00012 #include "fei_utils.hpp"
00013 
00014 #include "fei_TemplateUtils.hpp"
00015 #include "fei_chk_mpi.hpp"
00016 #include <fei_CommUtils.hpp>
00017 #include "snl_fei_Utils.hpp"
00018 #include "fei_Record.hpp"
00019 #include "snl_fei_RecordCollection.hpp"
00020 #include "fei_ParameterSet.hpp"
00021 #include "snl_fei_RecordMsgHandler.hpp"
00022 #include "fei_SharedIDs.hpp"
00023 #include "fei_Pattern.hpp"
00024 #include "fei_VectorSpace.hpp"
00025 #include "fei_FieldMask.hpp"
00026 #include "snl_fei_PointBlockMap.hpp"
00027 #include "fei_LogManager.hpp"
00028 
00029 #undef fei_file
00030 #define fei_file "fei_VectorSpace.cpp"
00031 #include "fei_ErrMacros.hpp"
00032 
00033 namespace fei {
00034   class RecordAttributeCounter : public Record_Operator {
00035   public:
00036     RecordAttributeCounter(int proc)
00037       : numLocalDOF_(0),
00038         numLocalIDs_(0),
00039         numLocallyOwnedIDs_(0),
00040         numRemoteSharedDOF_(0),
00041         proc_(proc)
00042     {}
00043 
00044     virtual ~RecordAttributeCounter(){}
00045 
00046     void operator()(fei::Record& record)
00047     {
00048       fei::FieldMask* mask = record.getFieldMask();
00049       int owner = record.getOwnerProc();
00050 
00051       if (owner != proc_) {
00052         numRemoteSharedDOF_ += mask->getNumIndices();
00053         return;
00054       }
00055       else {
00056         ++numLocallyOwnedIDs_;
00057       }
00058 
00059       ++numLocalIDs_;
00060 
00061       int numDOF = mask->getNumIndices();
00062 
00063       numLocalDOF_ += numDOF;  
00064     }
00065 
00066     int numLocalDOF_;
00067     int numLocalIDs_;
00068     int numLocallyOwnedIDs_;
00069     int numRemoteSharedDOF_;
00070 
00071   private:
00072     int proc_;
00073   };//class Record_Operator
00074 
00075   class BlkIndexAccessor : public Record_Operator {
00076   public:
00077     BlkIndexAccessor(int localProc,
00078                      int lenBlkIndices,
00079                      int* globalBlkIndices,
00080                      int* blkSizes)
00081       : numBlkIndices_(0),
00082         proc_(localProc),
00083         lenBlkIndices_(lenBlkIndices),
00084         globalBlkIndices_(globalBlkIndices),
00085         blkSizes_(blkSizes)
00086     {
00087     }
00088 
00089     BlkIndexAccessor(int lenBlkIndices,
00090                      int* globalBlkIndices,
00091                      int* blkSizes)
00092       : numBlkIndices_(0),
00093         proc_(-1),
00094         lenBlkIndices_(lenBlkIndices),
00095         globalBlkIndices_(globalBlkIndices),
00096         blkSizes_(blkSizes)
00097     {
00098     }
00099 
00100     void operator()(fei::Record& record)
00101     {
00102       int owner = record.getOwnerProc();
00103       if (owner != proc_ && proc_ > -1) {
00104         return;
00105       }
00106 
00107       fei::FieldMask* mask = record.getFieldMask();
00108       int blkSize = mask->getNumIndices();
00109 
00110       if (numBlkIndices_ < lenBlkIndices_) {
00111         globalBlkIndices_[numBlkIndices_] = record.getNumber();
00112         blkSizes_[numBlkIndices_] = blkSize;
00113       }
00114 
00115       ++numBlkIndices_;
00116     }
00117 
00118     int numBlkIndices_;
00119 
00120   private:
00121     int proc_;
00122     int lenBlkIndices_;
00123     int* globalBlkIndices_;
00124     int* blkSizes_;
00125   };//class BlkIndexAccessor
00126 }//namespace snl_fei
00127 
00128 //----------------------------------------------------------------------------
00129 fei::SharedPtr<fei::VectorSpace>
00130 fei::VectorSpace::Factory::createVectorSpace(MPI_Comm comm,
00131                                              const char* name)
00132 {
00133   fei::SharedPtr<fei::VectorSpace> sptr(new fei::VectorSpace(comm, name));
00134   return(sptr);
00135 }
00136 
00137 //----------------------------------------------------------------------------
00138 fei::VectorSpace::VectorSpace(MPI_Comm comm, const char* name)
00139   : fieldMasks_(),
00140     comm_(comm),
00141     idTypes_(),
00142     fieldDatabase_(),
00143     recordCollections_(),
00144     sharedIDTypes_(),
00145     sharedIDTables_(),
00146     ownerPatterns_(),
00147     sharerPatterns_(),
00148     sharedRecordsSynchronized_(true),
00149     ptBlkMap_(NULL),
00150     globalOffsets_(),
00151     globalIDOffsets_(),
00152     simpleProblem_(false),
00153     firstLocalOffset_(-1),
00154     lastLocalOffset_(-1),
00155     eqnNumbers_(),
00156     newInitData_(false),
00157     name_(),
00158     dbgprefix_("VecSpc: "),
00159     checkSharedIDs_(false)
00160 {
00161   check_version();
00162 
00163 //The initializations below are redundant with the ones above in the
00164 //initializer list. For some reason, when compiled for janus with optimization,
00165 //these pointers are not being set to NULL by the above initializers.
00166 //This was causing seg faults later when other VectorSpace methods delete these
00167 //pointers if they aren't NULL.  ABW 5/19/2004
00168 
00169   ptBlkMap_ = NULL;
00170 
00171   int numProcs = fei::numProcs(comm_);
00172   globalOffsets_.assign(numProcs+1, 0);
00173   globalIDOffsets_.assign(numProcs+1, 0);
00174 
00175   setName(name);
00176 }
00177 
00178 //----------------------------------------------------------------------------
00179 fei::VectorSpace::~VectorSpace()
00180 {
00181   int i, len = fieldMasks_.size();
00182   for(i=0; i<len; ++i) delete fieldMasks_[i];
00183 
00184   len = recordCollections_.size();
00185   for(i=0; i<len; ++i) delete recordCollections_[i];
00186 
00187   len = sharedIDTypes_.size();
00188   for(i=0; i<len; ++i) {
00189     delete sharedIDTables_[i];
00190   }
00191 
00192   len = ownerPatterns_.size();
00193   for(i=0; i<len; ++i) {
00194     delete ownerPatterns_[i];
00195   }
00196 
00197   len = sharerPatterns_.size();
00198   for(i=0; i<len; ++i) {
00199     delete sharerPatterns_[i];
00200   }
00201 
00202   delete ptBlkMap_;
00203 }
00204 
00205 //----------------------------------------------------------------------------
00206 MPI_Comm
00207 fei::VectorSpace::getCommunicator() const
00208 {
00209   return comm_;
00210 }
00211 
00212 //----------------------------------------------------------------------------
00213 void fei::VectorSpace::setParameters(const fei::ParameterSet& paramset)
00214 {
00215   const fei::Param* param = paramset.get("name");
00216   fei::Param::ParamType ptype = param != NULL ?
00217     param->getType() : fei::Param::BAD_TYPE;
00218   if (ptype == fei::Param::STRING) {
00219     setName(param->getStringValue().c_str());
00220   }
00221 
00222   param = paramset.get("FEI_OUTPUT_LEVEL");
00223   ptype = param != NULL ? param->getType() : fei::Param::BAD_TYPE;
00224   if (ptype == fei::Param::STRING) {
00225     fei::LogManager& log_manager = fei::LogManager::getLogManager();
00226     log_manager.setOutputLevel(param->getStringValue().c_str());
00227     setOutputLevel(fei::utils::string_to_output_level(param->getStringValue()));
00228   }
00229 
00230   param = paramset.get("FEI_LOG_EQN");
00231   ptype =  param != NULL ? param->getType() : fei::Param::BAD_TYPE;  
00232   if (ptype == fei::Param::INT) {
00233     addLogEqn(param->getIntValue());
00234   }
00235 
00236   param = paramset.get("FEI_LOG_ID");
00237   ptype =  param != NULL ? param->getType() : fei::Param::BAD_TYPE;  
00238   if (ptype == fei::Param::INT) {
00239     addLogID(param->getIntValue());
00240   }
00241 
00242   param = paramset.get("FEI_CHECK_SHARED_IDS");
00243   ptype = param != NULL ? param->getType() : fei::Param::BAD_TYPE;
00244   if (ptype != fei::Param::BAD_TYPE) {
00245     if (ptype == fei::Param::BOOL) {
00246       checkSharedIDs_ = param->getBoolValue();
00247     }
00248     else if (ptype == fei::Param::INT) {
00249       checkSharedIDs_ = param->getIntValue() > 0 ? true : false;
00250     }
00251     else {
00252       checkSharedIDs_ = true;
00253     }
00254   }
00255   else {
00256     checkSharedIDs_ = false;
00257   }
00258 }
00259 
00260 //----------------------------------------------------------------------------
00261 void fei::VectorSpace::defineFields(int numFields,
00262                                     const int* fieldIDs,
00263                                     const int* fieldSizes)
00264 {
00265   if (output_level_ >= fei::BRIEF_LOGS && output_stream_ != NULL) {
00266     FEI_OSTREAM& os = *output_stream_;
00267     os << dbgprefix_<<"defineFields ";
00268     for(int j=0; j<numFields; ++j) {
00269       os << "{"<<fieldIDs[j] << "," << fieldSizes[j] << "} ";
00270     }
00271     os << FEI_ENDL;
00272   }
00273 
00274   for (int i=0; i<numFields; ++i) {
00275     fieldDatabase_.insert(std::pair<int,unsigned>(fieldIDs[i], fieldSizes[i]));
00276   }
00277 }
00278 
00279 //----------------------------------------------------------------------------
00280 void fei::VectorSpace::defineIDTypes(int numIDTypes,
00281                                      const int* idTypes)
00282 {
00283   if (output_level_ >= fei::BRIEF_LOGS && output_stream_ != NULL) {
00284     FEI_OSTREAM& os = *output_stream_;
00285     os << dbgprefix_<<"defineIDTypes {";
00286     for(int j=0; j<numIDTypes; ++j) {
00287       os << idTypes[j] << " ";
00288     }
00289     os << "}"<<FEI_ENDL;
00290   }
00291 
00292   int localProc = fei::localProc(comm_);
00293   for (int i=0; i<numIDTypes; ++i) {
00294     int offset = snl_fei::sortedListInsert(idTypes[i], idTypes_);
00295 
00296     if (offset >= 0) {
00297       recordCollections_.insert(recordCollections_.begin()+offset, new snl_fei::RecordCollection(localProc));
00298     }
00299   }
00300 }
00301 
00302 //----------------------------------------------------------------------------
00303 int fei::VectorSpace::addDOFs(int fieldID,
00304                                           int numInstancesOfThisFieldPerID,
00305                                           int idType,
00306                                           int numIDs,
00307                                           const int* IDs)
00308 {
00309   if (output_level_ > fei::BRIEF_LOGS && output_stream_ != NULL) {
00310     FEI_OSTREAM& os = *output_stream_;
00311     os << dbgprefix_<<"addDOFs, fID=" << fieldID
00312        <<", idT="<<idType <<", ninst="
00313        << numInstancesOfThisFieldPerID << " {";
00314     for(int j=0; j<numIDs; ++j) {
00315       os << IDs[j] << " ";
00316       if (j>0 && j%20==0) os << FEI_ENDL << dbgprefix_;
00317     }
00318     os << "}"<<FEI_ENDL;
00319   }
00320 
00321   if (numIDs <= 0) return(0);
00322 
00323   int idx = snl_fei::binarySearch(idType, idTypes_);
00324   if (idx < 0) ERReturn(-1);
00325 
00326   unsigned fieldSize = getFieldSize(fieldID);
00327   recordCollections_[idx]->initRecords(fieldID, fieldSize,
00328                                        numInstancesOfThisFieldPerID,
00329                                        numIDs, IDs,
00330                                        fieldMasks_);
00331   newInitData_ = true;
00332   sharedRecordsSynchronized_ = false;
00333 
00334   return(0);
00335 }
00336 
00337 //----------------------------------------------------------------------------
00338 int fei::VectorSpace::addDOFs(int fieldID,
00339                                           int numInstancesOfThisFieldPerID,
00340                                           int idType,
00341                                           int numIDs,
00342                                           const int* IDs,
00343                                           fei::Record** records)
00344 {
00345   if (output_level_ > fei::BRIEF_LOGS && output_stream_ != NULL) {
00346     FEI_OSTREAM& os = *output_stream_;
00347     os << dbgprefix_<<"addDOFs*, fID=" << fieldID
00348        <<", idT="<<idType <<", ninst="
00349        << numInstancesOfThisFieldPerID << " {";
00350     for(int j=0; j<numIDs; ++j) {
00351       os << IDs[j] << " ";
00352       if (j>0 && j%20==0) os << FEI_ENDL << dbgprefix_;
00353     }
00354     os << "}"<<FEI_ENDL;
00355   }
00356 
00357   if (numIDs <= 0) return(0);
00358 
00359   int idx = snl_fei::binarySearch(idType, idTypes_);
00360   if (idx < 0) {
00361     FEI_OSTRINGSTREAM osstr;
00362     osstr << "fei::VectorSpace::addDOFs: error, idType " << idType
00363           << " not recognized. (idTypes need to be initialized via the"
00364           << " method VectorSpace::defineIDTypes)";
00365     throw std::runtime_error(osstr.str());
00366   }
00367 
00368   unsigned fieldSize = getFieldSize(fieldID);
00369   recordCollections_[idx]->initRecords(fieldID, fieldSize,
00370                                        numInstancesOfThisFieldPerID,
00371                                        numIDs, IDs,
00372                                        fieldMasks_,
00373                                        records);
00374   newInitData_ = true;
00375   sharedRecordsSynchronized_ = false;
00376 
00377   return(0);
00378 }
00379 
00380 //----------------------------------------------------------------------------
00381 int fei::VectorSpace::addDOFs(int idType,
00382                                           int numIDs,
00383                                           const int* IDs)
00384 {
00385   if (output_level_ > fei::BRIEF_LOGS && output_stream_ != NULL) {
00386     FEI_OSTREAM& os = *output_stream_;
00387     os << dbgprefix_<<"addDOFs idT=" <<idType<<" {";
00388     for(int j=0; j<numIDs; ++j) {
00389       os << IDs[j] << " ";
00390       if (j>0 && j%20==0) os << FEI_ENDL << dbgprefix_;
00391     }
00392     os << "}"<<FEI_ENDL;
00393   }
00394 
00395   if (numIDs <= 0) return(0);
00396 
00397   int idx = snl_fei::binarySearch(idType, idTypes_);
00398   if (idx < 0) ERReturn(-1);
00399 
00400   recordCollections_[idx]->initRecords(numIDs, IDs, fieldMasks_);
00401 
00402   newInitData_ = true;
00403   sharedRecordsSynchronized_ = false;
00404 
00405   return(0);
00406 }
00407 
00408 //----------------------------------------------------------------------------
00409 int fei::VectorSpace::addDOFs(int idType,
00410                                           int numIDs,
00411                                           const int* IDs,
00412                                           fei::Record** records)
00413 {
00414   if (output_level_ > fei::BRIEF_LOGS && output_stream_ != NULL) {
00415     FEI_OSTREAM& os = *output_stream_;
00416     os << dbgprefix_<<"addDOFs* idT=" <<idType<<" {";
00417     for(int j=0; j<numIDs; ++j) {
00418       os << IDs[j] << " ";
00419       if (j>0 && j%20==0) os << FEI_ENDL << dbgprefix_;
00420     }
00421     os << "}"<<FEI_ENDL;
00422   }
00423 
00424   if (numIDs <= 0) return(0);
00425 
00426   int idx = snl_fei::binarySearch(idType, idTypes_);
00427   if (idx < 0) ERReturn(-1);
00428 
00429   recordCollections_[idx]->initRecords(numIDs, IDs,
00430                                        fieldMasks_, records);
00431 
00432   newInitData_ = true;
00433   sharedRecordsSynchronized_ = false;
00434 
00435   return(0);
00436 }
00437 
00438 //----------------------------------------------------------------------------
00439 int fei::VectorSpace::initSharedIDs(int numShared,
00440                                     int idType,
00441                                     const int* sharedIDs,
00442                                     const int* numSharingProcsPerID,
00443                                     const int* sharingProcs)
00444 {
00445   if (output_level_ >= fei::BRIEF_LOGS && output_stream_ != NULL) {
00446     FEI_OSTREAM& os = *output_stream_;
00447     os << dbgprefix_<<"initSharedIDs n=" <<numShared<<", idT="<<idType<< FEI_ENDL;
00448     int offset = 0;
00449     for(int ns=0; ns<numShared; ++ns) {
00450       os << dbgprefix_<<"#sharedID="<<sharedIDs[ns] << ", nprocs=" << numSharingProcsPerID[ns] << ", procs: ";
00451       for(int sp=0; sp<numSharingProcsPerID[ns]; ++sp) {
00452         os << sharingProcs[offset++] << " ";
00453       }
00454       os << FEI_ENDL;
00455     }
00456     os << FEI_ENDL;
00457   }
00458 
00459   if (numShared == 0) return(0);
00460 
00461   int idx = snl_fei::binarySearch(idType, idTypes_);
00462   if (idx < 0) ERReturn(-1);
00463 
00464   fei::SharedIDs* shIDs = NULL;
00465   getSharedIDs_private(idType, shIDs);
00466 
00467   int offset = 0;
00468   for(int i=0; i<numShared; ++i) {
00469     CHK_ERR( shIDs->addSharedID(sharedIDs[i], numSharingProcsPerID[i],
00470                                 &(sharingProcs[offset])) );
00471     offset += numSharingProcsPerID[i];
00472 
00473     fei::Record* rec = recordCollections_[idx]->getRecordWithID(sharedIDs[i]);
00474     if (rec == NULL) {
00475       CHK_ERR( addDOFs(idType, 1, &(sharedIDs[i])) );
00476     }
00477   }
00478 
00479   newInitData_ = true;
00480   sharedRecordsSynchronized_ = false;
00481 
00482   return(0);
00483 }
00484 
00485 //----------------------------------------------------------------------------
00486 int fei::VectorSpace::initSharedIDs(int numShared,
00487                                     int idType,
00488                                     const int* sharedIDs,
00489                                     const int* numSharingProcsPerID,
00490                                     const int* const* sharingProcs)
00491 {
00492   if (output_level_ >= fei::BRIEF_LOGS && output_stream_ != NULL) {
00493     FEI_OSTREAM& os = *output_stream_;
00494     os << dbgprefix_<<"initSharedIDs n=" <<numShared<<", idT="<<idType<< FEI_ENDL;
00495     for(int ns=0; ns<numShared; ++ns) {
00496       os << dbgprefix_<<"#sharedID="<<sharedIDs[ns] << ", nprocs=" << numSharingProcsPerID[ns] << ", procs: ";
00497       for(int sp=0; sp<numSharingProcsPerID[ns]; ++sp) {
00498         os << sharingProcs[ns][sp] << " ";
00499       }
00500       os << FEI_ENDL;
00501     }
00502     os << FEI_ENDL;
00503   }
00504 
00505   if (numShared == 0) return(0);
00506 
00507   fei::SharedIDs* shIDs = NULL;
00508   getSharedIDs_private(idType, shIDs);
00509 
00510   int idx = snl_fei::binarySearch(idType, idTypes_);
00511   if (idx < 0) ERReturn(-1);
00512 
00513   for(int i=0; i<numShared; ++i) {
00514     CHK_ERR( shIDs->addSharedID(sharedIDs[i], numSharingProcsPerID[i],
00515                                  sharingProcs[i]) );
00516 
00517     fei::Record* rec = recordCollections_[idx]->getRecordWithID(sharedIDs[i]);
00518     if (rec == NULL) {
00519       CHK_ERR( addDOFs(idType, 1, &(sharedIDs[i])) );
00520     }
00521   }
00522 
00523   newInitData_ = true;
00524   sharedRecordsSynchronized_ = false;
00525 
00526   return(0);
00527 }
00528 
00529 //----------------------------------------------------------------------------
00530 int fei::VectorSpace::addVectorSpace(fei::VectorSpace* inputSpace)
00531 {
00532   idTypes_ = inputSpace->idTypes_;
00533 
00534   std::map<int,unsigned>::const_iterator
00535     f_iter = inputSpace->fieldDatabase_.begin(),
00536     f_end = inputSpace->fieldDatabase_.end();
00537 
00538   for(; f_iter != f_end; ++f_iter) {
00539     const std::pair<const int,unsigned>& fpair = *f_iter;
00540     int fieldsize = fpair.second;
00541     defineFields(1, &(fpair.first), &fieldsize);
00542   }
00543 
00544   int i, len = inputSpace->fieldMasks_.size();
00545   fieldMasks_.resize(len);
00546   for(i=0; i<len; ++i) {
00547     fieldMasks_[i] = new fei::FieldMask(*(inputSpace->fieldMasks_[i]));
00548   }
00549 
00550   len = inputSpace->recordCollections_.size();
00551   recordCollections_.resize(len);
00552   for(i=0; i<len; ++i) {
00553     recordCollections_[i] =
00554       new snl_fei::RecordCollection(*(inputSpace->recordCollections_[i]));
00555   }
00556 
00557   sharedIDTypes_ = inputSpace->sharedIDTypes_;
00558 
00559   len = inputSpace->sharedIDTables_.size();
00560   sharedIDTables_.resize(len);
00561   for(i=0; i<len; ++i) {
00562     sharedIDTables_[i] = new fei::SharedIDs(*(inputSpace->sharedIDTables_[i]));
00563   }
00564 
00565   newInitData_ = true;
00566   sharedRecordsSynchronized_ = false;
00567 
00568   return(0);
00569 }
00570 
00571 //----------------------------------------------------------------------------
00572 void fei::VectorSpace::getSharedIDs_private(int idType,
00573                                            fei::SharedIDs*& shIDs)
00574 {
00575   int insertPoint = -1;
00576   int idx = snl_fei::binarySearch(idType, sharedIDTypes_, insertPoint);
00577   if (idx < 0) {
00578     sharedIDTypes_.insert(sharedIDTypes_.begin()+insertPoint, idType);
00579 
00580     shIDs = new fei::SharedIDs;
00581 
00582     sharedIDTables_.insert(sharedIDTables_.begin()+insertPoint, shIDs);
00583   }
00584   else shIDs = sharedIDTables_[idx];
00585 }
00586 
00587 //----------------------------------------------------------------------------
00588 int fei::VectorSpace::initComplete()
00589 {
00590   if (output_level_ >= fei::BRIEF_LOGS && output_stream_ != NULL) {
00591     FEI_OSTREAM& os = *output_stream_;
00592     os <<dbgprefix_<< "initComplete" << FEI_ENDL;
00593   }
00594 
00595   simpleProblem_ = (fieldMasks_.size()==1) && (fieldMasks_[0]->getNumFields()==1);
00596 
00597   //we need to know if any processor has newInitData_.
00598   int localInitData = newInitData_ ? 1 : 0;
00599   int globalInitData = 0;
00600   CHK_ERR( fei::GlobalMax(comm_, localInitData, globalInitData) );
00601   newInitData_ = globalInitData > 0 ? true : false;
00602 
00603   if (newInitData_) {
00604     //setOwners_lowestSharing is a local operation (no communication), which
00605     //basically assumes that each processor holds CORRECT (globally symmetric)
00606     //shared-id/sharing-proc tables. No correctness-checking is performed here.
00607     setOwners_lowestSharing();
00608 
00609     //synchronizeSharedRecords ensures that each sharing processor has the same
00610     //view of the shared records, with respect to the layout of fields, which
00611     //determines how many DOFs and equation-numbers reside at each ID.
00612     //This involves inter-processor communication.
00613     if ( synchronizeSharedRecords() != 0) return(-1);
00614 
00615     //calculateGlobalIndices is also a global operation.
00616     CHK_ERR( calculateGlobalIndices() );
00617 
00618     //finally we need to exchange global indices for shared records. i.e., the
00619     //processors that own shared records, need to send the global indices for
00620     //those records to the sharing-but-not-owning processors.
00621     if (fei::numProcs(comm_) > 1) {
00622       CHK_ERR( exchangeGlobalIndices() );
00623     }
00624   }
00625 
00626   newInitData_ = false;
00627 
00628   return(0);
00629 }
00630 
00631 //----------------------------------------------------------------------------
00632 int fei::VectorSpace::getGlobalIndex(int idType,
00633                                      int ID,
00634                                      int fieldID,
00635                                      int fieldOffset,
00636                                      int whichComponentOfField,
00637                                      int& globalIndex)
00638 {
00639   int idindex = snl_fei::binarySearch(idType, idTypes_);
00640   if (idindex < 0) return(-1);
00641 
00642   unsigned fieldSize = 0;
00643   if (fieldOffset > 0) {
00644     fieldSize = getFieldSize(fieldID);
00645   }
00646 
00647   try {
00648     globalIndex = recordCollections_[idindex]->getGlobalIndex(ID,
00649                                                          fieldID,
00650                                                          fieldSize,
00651                                                          fieldOffset,
00652                                                          whichComponentOfField,
00653                                                          &eqnNumbers_[0]);
00654   }
00655   catch (std::runtime_error& exc) {
00656     FEI_OSTRINGSTREAM osstr;
00657     osstr << "VectorSpace::getGlobalIndex caught exception: " << exc.what();
00658     FEI_CERR << osstr.str()<<FEI_ENDL;
00659     ERReturn(-1);
00660   }
00661 
00662   return(0);
00663 }
00664 
00665 //----------------------------------------------------------------------------
00666 int fei::VectorSpace::getGlobalIndex(int idType,
00667                                      int ID,
00668                                      int fieldID,
00669                                      int& globalIndex)
00670 {
00671   return( getGlobalIndex(idType, ID, fieldID, 0, 0, globalIndex) );
00672 }
00673 
00674 //----------------------------------------------------------------------------
00675 int fei::VectorSpace::getGlobalBlkIndex(int idType,
00676                                         int ID,
00677                                         int& globalBlkIndex)
00678 {
00679   int idindex = snl_fei::binarySearch(idType, idTypes_);
00680   if (idindex < 0) return(-1);
00681 
00682   CHK_ERR(recordCollections_[idindex]->getGlobalBlkIndex(ID, globalBlkIndex));
00683 
00684   return(0);
00685 }
00686 
00687 //----------------------------------------------------------------------------
00688 int fei::VectorSpace::getGlobalIndices(int numIDs,
00689                                        const int* IDs,
00690                                        int idType,
00691                                        int fieldID,
00692                                        int* globalIndices)
00693 {
00694   int idindex = snl_fei::binarySearch(idType, idTypes_);
00695   if (idindex < 0) return(-1);
00696 
00697   unsigned fieldSize = getFieldSize(fieldID);
00698   int offset = 0;
00699 
00700   for(int i=0; i<numIDs; ++i) {
00701     try {
00702       globalIndices[offset] =
00703         recordCollections_[idindex]->getGlobalIndex(IDs[i],
00704                                                     fieldID,
00705                                                     fieldSize,
00706                                                     0, 0,
00707                                                     &eqnNumbers_[0]);
00708       if (fieldSize>1) {
00709         int eqn = globalIndices[offset];
00710         for(unsigned j=1; j<fieldSize; ++j) {
00711           globalIndices[offset+j] = eqn+j;
00712         }
00713       }
00714     }
00715     catch (...) {
00716       for(unsigned j=0; j<fieldSize; ++j) {
00717         globalIndices[offset+j] = -1;
00718       }
00719     }
00720 
00721     offset += fieldSize;
00722   }
00723 
00724   return(0);
00725 }
00726 
00727 //----------------------------------------------------------------------------
00728 int fei::VectorSpace::getGlobalBlkIndices(int numIDs,
00729                                           const int* IDs,
00730                                           int idType,
00731                                           int* globalBlkIndices)
00732 {
00733   int err;
00734   int idindex = snl_fei::binarySearch(idType, idTypes_);
00735   if (idindex < 0) return(-1);
00736 
00737   int offset = 0;
00738 
00739   for(int i=0; i<numIDs; ++i) {
00740     err = recordCollections_[idindex]->getGlobalBlkIndex(IDs[i],
00741                                                      globalBlkIndices[offset]);
00742     if (err != 0) {
00743       globalBlkIndices[offset] = -1;
00744     }
00745     ++offset;
00746   }
00747 
00748   return(0);
00749 }
00750 
00751 //----------------------------------------------------------------------------
00752 int fei::VectorSpace::getGlobalIndices(int numIDs,
00753                                        const int* IDs,
00754                                        const int* idTypes,
00755                                        const int* fieldIDs,
00756                                        int* globalIndices)
00757 {
00758   int err;
00759   int offset = 0;
00760   for(int i=0; i<numIDs; ++i) {
00761     unsigned fieldSize = getFieldSize(fieldIDs[i]);
00762     err = getGlobalIndex(idTypes[i], IDs[i], fieldIDs[i], 0, 0,
00763                          globalIndices[offset]);
00764     if (err) {
00765       for(unsigned j=1; j<fieldSize; ++j) {
00766         globalIndices[offset+j] = -1;
00767       }
00768     }
00769     else {
00770       if (fieldSize>1) {
00771         int eqn = globalIndices[offset];
00772         for(unsigned j=1; j<fieldSize; ++j) {
00773           globalIndices[offset+j] = eqn+j;
00774         }
00775       }
00776     }
00777     offset += fieldSize;
00778   }
00779 
00780   return(0);
00781 }
00782 
00783 //----------------------------------------------------------------------------
00784 void fei::VectorSpace::getGlobalBlkIndices(const fei::Pattern* pattern,
00785                                            const fei::Record*const* records,
00786                                            std::vector<int>& indices)
00787 {
00788   int numRecords = pattern->getNumIDs();
00789   indices.resize(numRecords);
00790   int numIndices;
00791   getGlobalBlkIndices(numRecords, records, numRecords, &indices[0],
00792                       numIndices);
00793 }
00794 
00795 //----------------------------------------------------------------------------
00796 void fei::VectorSpace::getGlobalIndices(const fei::Pattern* pattern,
00797                                         const fei::Record*const* records,
00798                                         std::vector<int>& indices)
00799 {
00800   int numRecords = pattern->getNumIDs();
00801   int numIndices = pattern->getNumIndices();
00802   indices.resize(numIndices);
00803   int* indices_ptr = &indices[0];
00804 
00805   fei::Pattern::PatternType pType = pattern->getPatternType();
00806 
00807   if (pType == fei::Pattern::GENERAL ||
00808       pType == fei::Pattern::SINGLE_IDTYPE) {
00809     const int* numFieldsPerID = pattern->getNumFieldsPerID();
00810     const int* fieldIDs = pattern->getFieldIDs();
00811     int totalNumFields = pattern->getTotalNumFields();
00812 
00813     std::vector<int> fieldSizes(totalNumFields);
00814 
00815     for(int j=0; j<totalNumFields; ++j) {
00816       fieldSizes[j] = getFieldSize(fieldIDs[j]);
00817     }
00818 
00819     getGlobalIndices(numRecords, records, numFieldsPerID,
00820                      fieldIDs, &(fieldSizes[0]),
00821                      numIndices, indices_ptr, numIndices);
00822   }
00823   else if (pType == fei::Pattern::SIMPLE) {
00824     const int* fieldIDs = pattern->getFieldIDs();
00825 
00826     int fieldID = fieldIDs[0];
00827     unsigned fieldSize = getFieldSize(fieldID);
00828 
00829     getGlobalIndices(numRecords, records,
00830                      fieldID, fieldSize,
00831                      numIndices, indices_ptr, numIndices);
00832   }
00833   else if (pType == fei::Pattern::NO_FIELD) {
00834     getGlobalBlkIndices(numRecords, records, numIndices, indices_ptr, numIndices);
00835   }
00836 }
00837 
00838 //----------------------------------------------------------------------------
00839 void fei::VectorSpace::getGlobalIndices(int numRecords,
00840                                         const fei::Record*const* records,
00841                                         int fieldID,
00842                                         int fieldSize,
00843                                         int indicesAllocLen,
00844                                         int* indices,
00845                                         int& numIndices)
00846 {
00847   numIndices = 0;
00848   int* eqnPtr = &eqnNumbers_[0];
00849 
00850   int len = numRecords;
00851   if (len*fieldSize >= indicesAllocLen) {
00852     len = indicesAllocLen/fieldSize;
00853   }
00854 
00855   if (fieldSize == 1 && simpleProblem_) {
00856     for(int i=0; i<len; ++i) {
00857       const fei::Record* record = records[i];
00858       indices[numIndices++] = *(eqnPtr+record->getOffsetIntoEqnNumbers());
00859     }    
00860     return;
00861   }
00862 
00863   if (fieldSize == 1) {
00864     for(int i=0; i<len; ++i) {
00865       const fei::Record* record = records[i];
00866 
00867       int eqnOffset = 0, numInstances = 0;
00868       int* eqnNumbers = eqnPtr+record->getOffsetIntoEqnNumbers();
00869 
00870       const fei::FieldMask* fieldMask = record->getFieldMask();
00871       fieldMask->getFieldEqnOffset(fieldID, eqnOffset, numInstances);
00872       indices[numIndices++] = eqnNumbers[eqnOffset];
00873     }
00874   }
00875   else {
00876     for(int i=0; i<len; ++i) {
00877       const fei::Record* record = records[i];
00878 
00879       int* eqnNumbers = eqnPtr+record->getOffsetIntoEqnNumbers();
00880 
00881       int eqnOffset = 0, numInstances = 0;
00882       if (!simpleProblem_) {
00883         const fei::FieldMask* fieldMask = record->getFieldMask();
00884         fieldMask->getFieldEqnOffset(fieldID, eqnOffset, numInstances);
00885       }
00886 
00887       for(int fs=0; fs<fieldSize; ++fs) {
00888         indices[numIndices++] = eqnNumbers[eqnOffset+fs];
00889       }
00890     }
00891   }
00892 }
00893 
00894 //----------------------------------------------------------------------------
00895 void fei::VectorSpace::getGlobalIndices(int numRecords,
00896                                         const fei::Record*const* records,
00897                                         const int* numFieldsPerID,
00898                                         const int* fieldIDs,
00899                                         const int* fieldSizes,
00900                                         int indicesAllocLen,
00901                                         int* indices,
00902                                         int& numIndices)
00903 {
00904   numIndices = 0;
00905   int fld_offset = 0;
00906   int* eqnPtr = &eqnNumbers_[0];
00907 
00908   for(int i=0; i<numRecords; ++i) {
00909     const fei::Record* record = records[i];
00910 
00911     const fei::FieldMask* fieldMask = record->getFieldMask();
00912     int* eqnNumbers = eqnPtr + record->getOffsetIntoEqnNumbers();
00913 
00914     for(int nf=0; nf<numFieldsPerID[i]; ++nf) {
00915       int eqnOffset = 0, numInstances = 0;
00916       if (!simpleProblem_) {
00917         fieldMask->getFieldEqnOffset(fieldIDs[fld_offset], eqnOffset, numInstances);
00918       }
00919 
00920       for(int fs=0; fs<fieldSizes[fld_offset]; ++fs) {
00921         indices[numIndices++] = eqnNumbers[eqnOffset+fs];
00922       }
00923 
00924       ++fld_offset;
00925     }
00926   }
00927 }
00928 
00929 //----------------------------------------------------------------------------
00930 void fei::VectorSpace::getGlobalBlkIndices(int numRecords,
00931                                            const fei::Record*const* records,
00932                                            int indicesAllocLen,
00933                                            int* indices,
00934                                            int& numIndices)
00935 {
00936   numIndices = 0;
00937   for(int i=0; i<numRecords; ++i) {
00938     if (numIndices < indicesAllocLen) {
00939       indices[numIndices++] = records[i]->getNumber();
00940     }
00941     else ++numIndices;
00942   }
00943 }
00944 
00945 //----------------------------------------------------------------------------
00946 int fei::VectorSpace::getGlobalIndex(int idType,
00947                                      int ID,
00948                                      int& globalIndex)
00949 {
00950   int idindex = snl_fei::binarySearch(idType, idTypes_);
00951   if (idindex < 0) return(-1);
00952 
00953   fei::Record* record = recordCollections_[idindex]->getRecordWithID(ID);
00954   if (record == NULL) {
00955     ERReturn(-1);
00956   }
00957 
00958   const int* eqnNums = &eqnNumbers_[0]
00959                      + record->getOffsetIntoEqnNumbers();
00960 
00961   if (eqnNums != NULL) { globalIndex = eqnNums[0]; return(0); }
00962   return(-1);
00963 }
00964 
00965 //----------------------------------------------------------------------------
00966 int fei::VectorSpace::getNumDegreesOfFreedom(int idType,
00967                                              int ID)
00968 {
00969   int idindex = snl_fei::binarySearch(idType, idTypes_);
00970   if (idindex < 0) return(0);
00971 
00972   fei::Record* record = recordCollections_[idindex]->getRecordWithID(ID);
00973   if (record == NULL) {
00974     ERReturn(-1);
00975   }
00976 
00977   return( record->getFieldMask()->getNumIndices() );
00978 }
00979 
00980 //----------------------------------------------------------------------------
00981 int fei::VectorSpace::getNumFields()
00982 {
00983   return(fieldDatabase_.size());
00984 }
00985 
00986 //----------------------------------------------------------------------------
00987 void fei::VectorSpace::getFields(std::vector<int>& fieldIDs)
00988 {
00989   unsigned numFields = fieldDatabase_.size();
00990 
00991   fieldIDs.resize(numFields);
00992 
00993   fei::copyKeysToArray<std::map<int,unsigned> >(fieldDatabase_, numFields,
00994                                                     &fieldIDs[0]);
00995 }
00996 
00997 //----------------------------------------------------------------------------
00998 size_t fei::VectorSpace::getNumIDTypes()
00999 {
01000   return(idTypes_.size());
01001 }
01002 
01003 //----------------------------------------------------------------------------
01004 void fei::VectorSpace::getIDTypes(std::vector<int>& idTypes) const
01005 {
01006   size_t numIDTypes = idTypes_.size();
01007   idTypes.resize(numIDTypes);
01008   for(size_t i=0; i<numIDTypes; ++i) idTypes[i] = idTypes_[i];
01009 }
01010 
01011 //----------------------------------------------------------------------------
01012 int fei::VectorSpace::getNumFields(int idType,
01013                                    int ID)
01014 {
01015   int idindex = snl_fei::binarySearch(idType, idTypes_);
01016   if (idindex < 0) return(0);
01017 
01018   fei::Record* record = recordCollections_[idindex]->getRecordWithID(ID);
01019   if (record == NULL) {
01020     ERReturn(-1);
01021   }
01022 
01023   return( record->getFieldMask()->getNumFields() );
01024 }
01025 
01026 //----------------------------------------------------------------------------
01027 bool fei::VectorSpace::isLocal(int idType, int ID)
01028 {
01029   int idindex = snl_fei::binarySearch(idType, idTypes_);
01030   if (idindex < 0) return(false);
01031 
01032   fei::Record* record = recordCollections_[idindex]->getRecordWithID(ID);
01033   if (record == NULL) {
01034     return(false);
01035   }
01036 
01037   return(true);
01038 }
01039 
01040 //----------------------------------------------------------------------------
01041 bool fei::VectorSpace::isLocallyOwned(int idType, int ID)
01042 {
01043   int idindex = snl_fei::binarySearch(idType, idTypes_);
01044   if (idindex < 0) return(false);
01045 
01046   fei::Record* record = recordCollections_[idindex]->getRecordWithID(ID);
01047   if (record == NULL) {
01048     return(false);
01049   }
01050   if (record->getOwnerProc() == fei::localProc(comm_)) {
01051     return(true);
01052   }
01053 
01054   return(false);
01055 }
01056 
01057 //----------------------------------------------------------------------------
01058 unsigned fei::VectorSpace::getFieldSize(int fieldID)
01059 {
01060   std::map<int,unsigned>::const_iterator
01061     f_iter = fieldDatabase_.find(fieldID);
01062 
01063   if (f_iter == fieldDatabase_.end()) {
01064     FEI_OSTRINGSTREAM osstr;
01065     osstr << "fei::VectorSpace";
01066     if (name_.length() > 0) {
01067       osstr << "(name: "<<name_<<")";
01068     }
01069     osstr << "::getFieldSize: fieldID " << fieldID << " not found.";
01070     throw std::runtime_error(osstr.str());
01071   }
01072 
01073   return((*f_iter).second);
01074 }
01075 
01076 //----------------------------------------------------------------------------
01077 void fei::VectorSpace::getFields(int idType, int ID, std::vector<int>& fieldIDs)
01078 {
01079   int idindex = snl_fei::binarySearch(idType, idTypes_);
01080   if (idindex < 0) {
01081     fieldIDs.resize(0);
01082     return;
01083   }
01084 
01085   fei::Record* record = recordCollections_[idindex]->getRecordWithID(ID);
01086   if (record == NULL) {
01087     voidERReturn;
01088   }
01089 
01090   fei::FieldMask* fieldMask = record->getFieldMask();
01091   std::vector<int>& maskFieldIDs = fieldMask->getFieldIDs();
01092   int numFields = maskFieldIDs.size();
01093   fieldIDs.resize(numFields);
01094   for(int i=0; i<numFields; ++i) {
01095     fieldIDs[i] = maskFieldIDs[i];
01096   }
01097 }
01098 
01099 //----------------------------------------------------------------------------
01100 void fei::VectorSpace::getGlobalIndexOffsets(std::vector<int>& globalOffsets) const
01101 {
01102   globalOffsets = globalOffsets_;
01103 }
01104 
01105 //----------------------------------------------------------------------------
01106 void fei::VectorSpace::getGlobalBlkIndexOffsets(std::vector<int>& globalBlkOffsets) const
01107 {
01108   globalBlkOffsets = globalIDOffsets_;
01109 }
01110 
01111 //----------------------------------------------------------------------------
01112 int fei::VectorSpace::getOwnerProcPtIndex(int globalIndex)
01113 {
01114   if (globalIndex < 0) return(-1);
01115 
01116   unsigned len = globalOffsets_.size();
01117   for(int i=0; i<(int)(len-1); ++i) {
01118     if (globalIndex < globalOffsets_[i+1]) {
01119       return(i);
01120     }
01121   }
01122 
01123   return(-1);
01124 }
01125 
01126 //----------------------------------------------------------------------------
01127 int fei::VectorSpace::getOwnerProcBlkIndex(int globalIndex)
01128 {
01129   if (globalIndex < 0) return(-1);
01130 
01131   unsigned len = globalOffsets_.size();
01132   for(int i=0; i<(int)(len-1); ++i) {
01133     if (globalIndex < globalIDOffsets_[i+1]) {
01134       return(i);
01135     }
01136   }
01137 
01138   return(-1);
01139 }
01140 
01141 //----------------------------------------------------------------------------
01142 int fei::VectorSpace::getNumOwnedAndSharedIDs(int idType)
01143 {
01144   int idx = snl_fei::binarySearch(idType, idTypes_);
01145   if (idx < 0) return(0);
01146 
01147   return( recordCollections_[idx]->getNumRecords() );
01148 }
01149 
01150 //----------------------------------------------------------------------------
01151 int fei::VectorSpace::getNumOwnedIDs(int idType)
01152 {
01153   int idx = snl_fei::binarySearch(idType, idTypes_);
01154   if (idx < 0) return(0);
01155 
01156   fei::RecordAttributeCounter attrCounter(fei::localProc(comm_));
01157   runRecords(attrCounter);
01158 
01159   return( attrCounter.numLocallyOwnedIDs_ );
01160 }
01161 
01162 //----------------------------------------------------------------------------
01163 int fei::VectorSpace::getNumSharedIDs(int idType,
01164                                           int& numShared)
01165 {
01166   int idx = snl_fei::binarySearch(idType, sharedIDTypes_);
01167   if (idx < 0) {
01168     numShared = 0;
01169     return(0);
01170   }
01171 
01172   fei::SharedIDs* sharedIDs = sharedIDTables_[idx];
01173 
01174   numShared = sharedIDs->getSharedIDs().getMap().size();
01175 
01176   return(0);
01177 }
01178 
01179 //----------------------------------------------------------------------------
01180 int fei::VectorSpace::getOwnedAndSharedIDs(int idType,
01181                                       int lenList,
01182                                       int* IDs,
01183                                       int& numLocalIDs)
01184 {
01185   int idx = snl_fei::binarySearch(idType, idTypes_);
01186   if (idx < 0) return(-1);
01187 
01188   snl_fei::RecordCollection* records = recordCollections_[idx];
01189 
01190   snl_fei::RecordCollection::map_type& rmap = records->getRecords();
01191 
01192   numLocalIDs = rmap.size();
01193 
01194   fei::copyKeysToArray(rmap, lenList, IDs);
01195 
01196   return(0);
01197 }
01198 
01199 //----------------------------------------------------------------------------
01200 int fei::VectorSpace::getOwnedIDs(int idType,
01201                                          int lenList,
01202                                          int* IDs,
01203                                          int& numLocalIDs)
01204 {
01205   int idx = snl_fei::binarySearch(idType, idTypes_);
01206   if (idx < 0) return(-1);
01207 
01208   snl_fei::RecordCollection* records = recordCollections_[idx];
01209 
01210   snl_fei::RecordCollection::map_type& rmap = records->getRecords();
01211 
01212   numLocalIDs = 0;
01213 
01214   snl_fei::RecordCollection::map_type::iterator
01215     r_iter = rmap.begin(),
01216     r_end  = rmap.end();
01217 
01218   for(; r_iter != r_end; ++r_iter) {
01219     fei::Record& thisrecord = *((*r_iter).second);
01220 
01221     if (thisrecord.getOwnerProc() == fei::localProc(comm_)) {
01222       if (numLocalIDs < lenList) {
01223         IDs[numLocalIDs] = thisrecord.getID();
01224       }
01225       ++numLocalIDs;
01226     }
01227   }
01228 
01229   return(0);
01230 }
01231 
01232 //----------------------------------------------------------------------------
01233 int fei::VectorSpace::getNumIndices_SharedAndOwned() const
01234 {
01235   return(eqnNumbers_.size());
01236 }
01237 
01238 //----------------------------------------------------------------------------
01239 int fei::VectorSpace::getIndices_SharedAndOwned(std::vector<int>& globalIndices) const
01240 {
01241   if (eqnNumbers_.size() == 0) {
01242     globalIndices.resize(0);
01243     return(0);
01244   }
01245 
01246   size_t numIndices = eqnNumbers_.size();
01247   const int* indicesPtr = &eqnNumbers_[0];
01248 
01249   globalIndices.resize(numIndices);
01250   for(size_t i=0; i<numIndices; ++i) {
01251     globalIndices[i] = indicesPtr[i];
01252   }
01253 
01254   return(0);
01255 }
01256 
01257 //----------------------------------------------------------------------------
01258 int fei::VectorSpace::getNumBlkIndices_SharedAndOwned(int& numBlkIndices) const
01259 {
01260   numBlkIndices = 0;
01261   for(size_t i=0; i<recordCollections_.size(); ++i) {
01262     numBlkIndices += recordCollections_[i]->getNumRecords();
01263   }
01264 
01265   return(0);
01266 }
01267 
01268 //----------------------------------------------------------------------------
01269 int fei::VectorSpace::getBlkIndices_SharedAndOwned(int lenBlkIndices,
01270                                                    int* globalBlkIndices,
01271                                                    int* blkSizes,
01272                                                    int& numBlkIndices)
01273 {
01274   if (!sharedRecordsSynchronized_) {
01275     numBlkIndices = 0;
01276     return(-1);
01277   }
01278 
01279   fei::BlkIndexAccessor blkIndAccessor(lenBlkIndices,
01280                                   globalBlkIndices, blkSizes);
01281   runRecords(blkIndAccessor);
01282 
01283   numBlkIndices = blkIndAccessor.numBlkIndices_;
01284 
01285   return(0);
01286 }
01287 
01288 //----------------------------------------------------------------------------
01289 int fei::VectorSpace::getGlobalNumIndices() const
01290 {
01291   if (globalOffsets_.size() < 1) return(0);
01292   return(globalOffsets_[globalOffsets_.size()-1]);
01293 }
01294 
01295 //----------------------------------------------------------------------------
01296 int fei::VectorSpace::getNumIndices_Owned() const
01297 {
01298   if (!sharedRecordsSynchronized_) {
01299     return(-1);
01300   }
01301 
01302   int localProc = fei::localProc(comm_);
01303   int numIndices = globalOffsets_[localProc+1]-globalOffsets_[localProc];
01304 
01305   return(numIndices);
01306 }
01307 
01308 //----------------------------------------------------------------------------
01309 int fei::VectorSpace::getIndices_Owned(int lenIndices,
01310                                        int* globalIndices,
01311                                        int& numIndices) const
01312 {
01313   if (!sharedRecordsSynchronized_) {
01314     numIndices = 0;
01315     return(-1);
01316   }
01317 
01318   int localProc = fei::localProc(comm_);
01319   numIndices = globalOffsets_[localProc+1]-globalOffsets_[localProc];
01320 
01321   int len = lenIndices >= numIndices ? numIndices : lenIndices;
01322 
01323   int firstOffset = globalOffsets_[localProc];
01324   for(int i=0; i<len; ++i) {
01325     globalIndices[i] = firstOffset+i;
01326   }
01327 
01328   return(0);
01329 }
01330 
01331 //----------------------------------------------------------------------------
01332 int fei::VectorSpace::getNumBlkIndices_Owned() const
01333 {
01334   if (!sharedRecordsSynchronized_) {
01335     return(-1);
01336   }
01337 
01338   int localProc = fei::localProc(comm_);
01339   int numBlkIndices = globalIDOffsets_[localProc+1]-globalIDOffsets_[localProc];
01340 
01341   return(numBlkIndices);
01342 }
01343 
01344 //----------------------------------------------------------------------------
01345 int fei::VectorSpace::getGlobalNumBlkIndices() const
01346 {
01347   int numBlkIndices = 0;
01348   unsigned len = globalIDOffsets_.size();
01349   if (len > 0) {
01350     numBlkIndices = globalIDOffsets_[len-1];
01351   }
01352 
01353   return(numBlkIndices);
01354 }
01355 
01356 //----------------------------------------------------------------------------
01357 int fei::VectorSpace::getBlkIndices_Owned(int lenBlkIndices,
01358                                           int* globalBlkIndices,
01359                                           int* blkSizes,
01360                                           int& numBlkIndices)
01361 {
01362   if (!sharedRecordsSynchronized_) {
01363     numBlkIndices = 0;
01364     return(-1);
01365   }
01366 
01367   int localProc = fei::localProc(comm_);
01368   fei::BlkIndexAccessor blkIndAccessor(localProc, lenBlkIndices,
01369                                            globalBlkIndices, blkSizes);
01370   runRecords(blkIndAccessor);
01371 
01372   numBlkIndices = blkIndAccessor.numBlkIndices_;
01373 
01374   return(0);
01375 }
01376 
01377 //----------------------------------------------------------------------------
01378 int fei::VectorSpace::getRecordCollection(int idType,
01379                                           snl_fei::RecordCollection*& records)
01380 {
01381   int idx = snl_fei::binarySearch(idType, idTypes_);
01382   if (idx < 0) return(-1);
01383 
01384   records = recordCollections_[idx];
01385   return(0);
01386 }
01387 
01388 //----------------------------------------------------------------------------
01389 int fei::VectorSpace::getRecordCollection(int idType,
01390                                           const snl_fei::RecordCollection*& records) const
01391 {
01392   int idx = snl_fei::binarySearch(idType, idTypes_);
01393   if (idx < 0) return(-1);
01394 
01395   records = recordCollections_[idx];
01396   return(0);
01397 }
01398 
01399 //----------------------------------------------------------------------------
01400 int fei::VectorSpace::setOwners_lowestSharing()
01401 {
01402   //first, add localProc to each of the sharing-proc lists, in case it wasn't
01403   //included via initSharedIDs().
01404   int localProc = fei::localProc(comm_);
01405 
01406   for(size_t i=0; i<sharedIDTables_.size(); ++i) {
01407     fei::SharedIDs::table_type& shid_table = sharedIDTables_[i]->getSharedIDs();
01408 
01409     fei::SharedIDs::table_type::iterator
01410       t_iter = shid_table.begin(),
01411       t_end = shid_table.end();
01412 
01413     for(; t_iter != t_end; ++t_iter) {
01414       fei::SharedIDs::table_type::row_type* shProcs = (*t_iter).second;
01415       shProcs->insert(localProc);
01416     }
01417   }
01418 
01419   //now set the owningProcs for the SharedIDs records, and the owning procs on
01420   //the appropriate records in the recordCollections. Set the owner to be the
01421   //lowest-numbered sharing proc in all cases.
01422   for(size_t i=0; i<sharedIDTypes_.size(); ++i) {
01423     fei::SharedIDs::table_type& shid_table = sharedIDTables_[i]->getSharedIDs();
01424 
01425     std::vector<int>& owningProcs = sharedIDTables_[i]->getOwningProcs();
01426 
01427     int len = shid_table.getMap().size();
01428     owningProcs.resize(len);
01429     int j = 0;
01430 
01431     fei::SharedIDs::table_type::iterator
01432       t_iter = shid_table.begin(),
01433       t_end = shid_table.end();
01434 
01435     for(; t_iter != t_end; ++t_iter, ++j) {
01436       fei::SharedIDs::table_type::row_type* shProcs = (*t_iter).second;
01437       int lowest = *(shProcs->begin());
01438       owningProcs[j] = lowest;
01439     }
01440     
01441     int idx = snl_fei::binarySearch(sharedIDTypes_[i], idTypes_);
01442     if (idx < 0) ERReturn(-1);
01443 
01444     if (output_level_ >= fei::FULL_LOGS && output_stream_ != NULL) {
01445       recordCollections_[idx]->setDebugOutput(output_stream_);
01446     }
01447 
01448     recordCollections_[idx]->setOwners_lowestSharing(sharedIDTables_[i]);
01449   }
01450 
01451   return(0);
01452 }
01453 
01454 //----------------------------------------------------------------------------
01455 int fei::VectorSpace::calculateGlobalIndices()
01456 {
01457   int localProc = fei::localProc(comm_);
01458   int numProcs = fei::numProcs(comm_);
01459   std::vector<int> localOffsets(numProcs +1, 0);
01460   std::vector<int> localIDOffsets(numProcs+1, 0);
01461   globalOffsets_.resize(numProcs + 1, 0);
01462 
01463   globalIDOffsets_.assign(globalIDOffsets_.size(), 0);
01464 
01465   //first we'll calculate the number of local degrees of freedom, and the
01466   //number of local identifiers.
01467   fei::RecordAttributeCounter counter(localProc);
01468   runRecords(counter);
01469 
01470   int numLocalDOF = counter.numLocalDOF_;
01471   int numLocalIDs = counter.numLocalIDs_;
01472   int numRemoteSharedDOF = counter.numRemoteSharedDOF_;
01473 
01474   eqnNumbers_.resize(numLocalDOF+numRemoteSharedDOF);
01475 
01476   localOffsets[localProc] = numLocalDOF;
01477   CHK_MPI( fei::GlobalMax(comm_, localOffsets, globalOffsets_) );
01478 
01479   localIDOffsets[localProc] = numLocalIDs;
01480   CHK_MPI( fei::GlobalMax(comm_, localIDOffsets, globalIDOffsets_) );
01481 
01482   //Now globalOffsets_ contains numLocalDOF for proc i, in the i-th position.
01483   //(and similarly for globalIDOffsets_)
01484   //So all we need to do is turn that data into global-offsets (i.e., the
01485   //starting global-offset for each processor).
01486   int localOffset = 0;
01487   int localIDOffset = 0;
01488   for(int p=0; p<numProcs; ++p) {
01489     numLocalDOF = globalOffsets_[p];
01490     globalOffsets_[p] = localOffset;
01491     localOffset += numLocalDOF;
01492     numLocalIDs = globalIDOffsets_[p];
01493     globalIDOffsets_[p] = localIDOffset;
01494     localIDOffset += numLocalIDs;
01495   }
01496   globalOffsets_[numProcs] = localOffset;
01497   globalIDOffsets_[numProcs] = localIDOffset;
01498 
01499   firstLocalOffset_ = globalOffsets_[localProc];
01500   lastLocalOffset_ = globalOffsets_[localProc+1] - 1;
01501 
01502   if (output_level_ >= fei::BRIEF_LOGS && output_stream_ != NULL) {
01503     FEI_OSTREAM& os = *output_stream_;
01504     os <<dbgprefix_<< "  firstLocalOffset_: " << firstLocalOffset_ << ", lastLocalOffset_: "
01505       << lastLocalOffset_ << FEI_ENDL;
01506   }
01507 
01508   //Now we're ready to set the equation-numbers on all local records.
01509   CHK_ERR( setLocalEqnNumbers() );
01510 
01511   return(0);
01512 }
01513 
01514 //----------------------------------------------------------------------------
01515 int fei::VectorSpace::synchronizeSharedRecords()
01516 {
01517   if (output_level_ >= fei::FULL_LOGS && output_stream_ != NULL) {
01518     FEI_OSTREAM& os = *output_stream_;
01519     os<<dbgprefix_<<"#synchronizeSharedRecords num-field-masks: "<<fieldMasks_.size()<<FEI_ENDL;
01520     for(unsigned fm=0; fm<fieldMasks_.size(); ++fm) {
01521       os << dbgprefix_<<"#     maskID["<<fm<<"]: " << fieldMasks_[fm]->getMaskID() << FEI_ENDL;
01522     }
01523   }
01524 
01525   bool safetyCheck = checkSharedIDs_;
01526 
01527   int numProcs = fei::numProcs(comm_);
01528   int localProc = fei::localProc(comm_);
01529   int numShTables = sharedIDTypes_.size();
01530 
01531   if (numProcs < 2) {
01532     sharedRecordsSynchronized_ = true;
01533     return(0);
01534   }
01535 
01536   if (safetyCheck) {
01537     if (localProc == 0 && output_level_ >= fei::BRIEF_LOGS) {
01538       FEI_COUT << "fei::VectorSpace: global consistency-check of shared ID"
01539            << " data (involves all-to-all communication). This is done "
01540            << "only if requested by parameter 'FEI_CHECK_SHARED_IDS true'."
01541            << FEI_ENDL;
01542     }
01543 
01544     int totalNumShTables = 0;
01545     CHK_ERR( fei::GlobalSum(comm_, numShTables, totalNumShTables) );
01546     if (totalNumShTables != numShTables * numProcs) {
01547       //not all processors have the same number of shared-id tables. This means
01548       //that one or more processors is 'empty', which may not be an error. But
01549       //it does mean that the safety check can't be performed because the safety
01550       //check involves all-to-all communication and if one or more processors
01551       //don't participate then we'll hang...
01552       safetyCheck = false;
01553     }
01554   }
01555 
01556   //Create a list of fei::comm_maps which will be the communication-patterns
01557   //for each of the sharedIDTables. The sharedIDTables map lists of processors
01558   //to each shared ID. The communication-pattern will be kind of a transpose of
01559   //that, mappings lists of IDs to owning or sharing processors.
01560   //
01561 
01562   int local_err = 0;
01563 
01564   for(int i=0; i<numShTables; ++i) {
01565 
01566     fei::SharedIDs* shared = sharedIDTables_[i];
01567     
01568     //now create/initialize ownerPatterns which map owning processors to lists
01569     //of ids that are shared locally, and sharerPatterns which map sharing
01570     //processors to lists of ids that are owned locally.
01571     fei::comm_map* ownerPattern = new fei::comm_map(1, numProcs);
01572 
01573     ownerPatterns_.push_back(ownerPattern);
01574 
01575     fei::comm_map* sharerPattern = 
01576             new fei::comm_map(1, numProcs);
01577 
01578     sharerPatterns_.push_back(sharerPattern);
01579 
01580     std::vector<int>& owningProcs = shared->getOwningProcs();
01581 
01582     fei::SharedIDs::table_type& shtable = shared->getSharedIDs();
01583 
01584     fei::SharedIDs::table_type::iterator
01585       s_iter = shtable.begin(),
01586       s_end = shtable.end();
01587     
01588     int j = 0;
01589     for(; s_iter != s_end; ++s_iter, ++j) {
01590       int ID = (*s_iter).first;
01591       fei::SharedIDs::table_type::row_type* shProcs = (*s_iter).second;
01592 
01593       int owner = owningProcs[j];
01594 
01595       if (owner == localProc) {
01596         fei::SharedIDs::table_type::row_type::const_iterator
01597           p_iter = shProcs->begin(),
01598           p_end = shProcs->end();
01599         for(; p_iter != p_end; ++p_iter) {
01600           if (*p_iter != localProc) {
01601             sharerPattern->addIndices(*p_iter, 1, &ID);
01602           }
01603         }
01604       }
01605       else {
01606         ownerPattern->addIndices(owner, 1, &ID);
01607       }
01608     }
01609 
01610     if (safetyCheck) {
01611       fei::comm_map* checkPattern = NULL;
01612       CHK_ERR( fei::mirrorCommPattern(comm_, ownerPattern, checkPattern) );
01613       fei::Barrier(comm_);
01614       if (output_level_ >= fei::FULL_LOGS && output_stream_ != NULL) {
01615         FEI_OSTREAM& os = *output_stream_;
01616         fei::comm_map::map_type& owner_map = ownerPattern->getMap();
01617         int numKeys = owner_map.size();
01618         fei::comm_map::map_type::const_iterator
01619           omap_iter = owner_map.begin(),
01620           omap_end = owner_map.end();
01621 
01622         os << dbgprefix_<<"#  synchronizeSharedRecords" << FEI_ENDL
01623            << dbgprefix_<<"#  ownerPattern, num-procs-to-send-to: " << numKeys << FEI_ENDL;
01624         for(int sk=0; omap_iter != omap_end; ++sk, ++omap_iter) {
01625           os << dbgprefix_<<"#    sendProc["<<sk<<"]: " << omap_iter->first << " IDs: ";
01626           fei::comm_map::row_type::const_iterator
01627             val_iter = omap_iter->second->begin(),
01628             val_end =  omap_iter->second->end();
01629           for(; val_iter != val_end; ++val_iter) {
01630             os << *val_iter << " ";
01631           }
01632           os << FEI_ENDL;
01633         }
01634 
01635         fei::comm_map::map_type& check_map = checkPattern->getMap();
01636         int numCheckKeys = check_map.size();
01637         fei::comm_map::map_type::const_iterator
01638           cmap_iter = check_map.begin(),
01639           cmap_end = check_map.end();
01640 
01641         os <<dbgprefix_<< "#  synchronizeSharedRecords" << FEI_ENDL
01642            <<dbgprefix_<< "#  checkPattern (send mirror), num-procs: "
01643            << numCheckKeys << FEI_ENDL;
01644         for(int sk=0; cmap_iter != cmap_end; ++sk, ++cmap_iter) {
01645           os <<dbgprefix_<< "#    proc["<<sk<<"]: " << cmap_iter->first << " IDs: ";
01646           fei::comm_map::row_type::const_iterator
01647           val_iter = cmap_iter->second->begin(),
01648             val_end = cmap_iter->second->end();
01649           for(; val_iter != val_end; ++val_iter) {
01650             os << *val_iter << " ";
01651           }
01652           os << FEI_ENDL;
01653         }
01654       }
01655 
01656       int err = 0;
01657       bool quiet = false;
01658       if (!checkPattern->equal(*sharerPattern, quiet)) {
01659         //FEI_CERR << "shared-ID safety-check failed..."
01660         //     << FEI_ENDL;
01661         err = -1;
01662       }
01663       int globalErr = 0;
01664       CHK_ERR( fei::GlobalSum(comm_, err, globalErr) );
01665 
01666       delete checkPattern;
01667 
01668       if (globalErr != 0) {
01669         return(globalErr);
01670       }
01671     }
01672 
01673     int idx = snl_fei::binarySearch(sharedIDTypes_[i], idTypes_);
01674     if (idx < 0) ERReturn(-1);
01675 
01676     local_err += exchangeFieldInfo(ownerPattern, sharerPattern,
01677                                    recordCollections_[idx], fieldMasks_);
01678   }
01679 
01680   int global_err = 0;
01681   CHK_ERR( fei::GlobalSum(comm_, local_err, global_err) );
01682 
01683   if (global_err != 0) {
01684     ERReturn(-1);
01685   }
01686 
01687   sharedRecordsSynchronized_ = true;
01688 
01689   return(0);
01690 }
01691 
01692 //----------------------------------------------------------------------------
01693 int fei::VectorSpace::exchangeGlobalIndices()
01694 {
01695   size_t numShTables = sharedIDTypes_.size();
01696   for(size_t i=0; i<numShTables; ++i) {
01697     int idx = snl_fei::binarySearch(sharedIDTypes_[i], idTypes_);
01698     if (idx < 0) ERReturn(-1);
01699 
01700     snl_fei::RecordMsgHandler recmsghndlr(fei::localProc(comm_),
01701                                  recordCollections_[idx], *ptBlkMap_,
01702                                           fieldMasks_, eqnNumbers_);
01703     recmsghndlr.setTask(snl_fei::RecordMsgHandler::_EqnNumbers_);
01704 
01705     recmsghndlr.setSendPattern(sharerPatterns_[i]);
01706     recmsghndlr.setRecvPattern(ownerPatterns_[i]);
01707     CHK_ERR( fei::exchange(comm_, &recmsghndlr) );
01708   }
01709 
01710   return(0);
01711 }
01712 
01713 //----------------------------------------------------------------------------
01714 void fei::VectorSpace::runRecords(fei::Record_Operator& record_op)
01715 {
01716   for(size_t rec=0; rec<recordCollections_.size(); ++rec) {
01717     snl_fei::RecordCollection* records = recordCollections_[rec];
01718 
01719     snl_fei::RecordCollection::map_type& rmap = records->getRecords();
01720 
01721     snl_fei::RecordCollection::map_type::iterator
01722       r_iter = rmap.begin(),
01723       r_end  = rmap.end();
01724 
01725     for(; r_iter != r_end; ++r_iter) {
01726       fei::Record& thisrecord = *((*r_iter).second);
01727 
01728       record_op(thisrecord);
01729     }
01730   }
01731 }
01732 
01733 //----------------------------------------------------------------------------
01734 int fei::VectorSpace::setLocalEqnNumbers()
01735 {
01736   int proc = fei::localProc(comm_);
01737   int eqnNumber = firstLocalOffset_;
01738   int idNumber = globalIDOffsets_[proc];
01739 
01740   int numProcs = fei::numProcs(comm_);
01741   int localProc = fei::localProc(comm_);
01742 
01743   if (ptBlkMap_ != NULL) {
01744     delete ptBlkMap_;
01745   }
01746   ptBlkMap_ = new snl_fei::PointBlockMap;
01747 
01748   int maxNumIndices = 0;
01749   for(unsigned i=0; i<fieldMasks_.size(); ++i) {
01750     if (fieldMasks_[i]->getNumIndices() > maxNumIndices) {
01751       maxNumIndices = fieldMasks_[i]->getNumIndices();
01752     }
01753   }
01754 
01755   if (maxNumIndices == 1) {
01756     ptBlkMap_->setPtEqualBlk();
01757   }
01758 
01759   FEI_OSTREAM* id2eqnStream = NULL;
01760   if (output_level_ >= fei::BRIEF_LOGS) {
01761     std::string path = fei::LogManager::getLogManager().getOutputPath();
01762     if (path == "") path = ".";
01763     FEI_OSTRINGSTREAM osstr;
01764     osstr << path << "/fei_ID2Eqn";
01765     if (name_.size() > 0) osstr << "_" << name_;
01766     osstr << "." <<numProcs<< "." << localProc;
01767 
01768     id2eqnStream = new FEI_OFSTREAM(osstr.str().c_str(), IOS_OUT);
01769     FEI_OSTREAM& os = *id2eqnStream;
01770     os << "# Each line contains:\n#   ID   blk-eqn   eqn" << FEI_ENDL;
01771   }
01772 
01773   int eqnNumberOffset = 0;
01774   int maxNumDOF = 0;
01775 
01776   for(size_t rec=0; rec<recordCollections_.size(); ++rec) {
01777     snl_fei::RecordCollection* records = recordCollections_[rec];
01778 
01779     snl_fei::RecordCollection::map_type& rmap = records->getRecords();
01780 
01781     snl_fei::RecordCollection::map_type::iterator
01782       r_iter = rmap.begin(),
01783       r_end = rmap.end();
01784 
01785     int* eqnNumPtr = &eqnNumbers_[0];
01786 
01787     for(; r_iter != r_end; ++r_iter) {
01788       fei::Record& thisrecord = *((*r_iter).second);
01789 
01790       fei::FieldMask* mask = thisrecord.getFieldMask();
01791 
01792       thisrecord.setOffsetIntoEqnNumbers(eqnNumberOffset);
01793 
01794       int owner = thisrecord.getOwnerProc();
01795       if (owner == proc) {
01796         thisrecord.setNumber(idNumber++);
01797       }
01798 
01799       int* eqnNumbers = eqnNumPtr
01800                       + thisrecord.getOffsetIntoEqnNumbers();
01801 
01802       int numDOF = mask->getNumIndices();
01803       eqnNumberOffset += numDOF;
01804 
01805       if (output_level_ >= fei::BRIEF_LOGS) {
01806         for(int ii=0; ii<numDOF; ++ii) {
01807           if (isLogEqn(eqnNumber+ii) && output_stream_ != NULL) {
01808             FEI_OSTREAM& os = *output_stream_;
01809             os <<dbgprefix_<< "setLocalEqnNumbers: ID "<<thisrecord.getID()
01810                << " <--> eqn " << eqnNumber+ii<<FEI_ENDL;
01811           }
01812         }
01813       }
01814 
01815       if (owner == proc) {
01816         int offset = 0;
01817         for(int n=0; n<numDOF; ++n) {
01818           eqnNumbers[offset++] = eqnNumber++;
01819         }
01820       }
01821 
01822       if (numDOF > maxNumDOF) maxNumDOF = numDOF;
01823 
01824       if (owner == proc) {
01825         int thiseqn = eqnNumber-numDOF;
01826         int thisrecordnumber = thisrecord.getNumber();
01827         if (maxNumIndices > 1) {
01828           CHK_ERR( ptBlkMap_->setEqn(thiseqn, thisrecordnumber, numDOF) );
01829           if (numDOF > 1) {
01830             for(int i=1; i<numDOF; ++i) {
01831               CHK_ERR( ptBlkMap_->setEqn(thiseqn+i, thisrecordnumber, numDOF) );
01832             }
01833           }
01834         }
01835       }
01836 
01837       if (id2eqnStream != NULL) {
01838         if (owner == proc) {
01839           FEI_OSTREAM& os = *id2eqnStream;
01840           for(int n=0; n<numDOF; ++n) {
01841             os << thisrecord.getID() << " " << thisrecord.getNumber() << " "
01842                << eqnNumber-numDOF+n<<FEI_ENDL;
01843           }
01844         }
01845       }
01846     }
01847 
01848   }
01849 
01850   ptBlkMap_->setMaxBlkEqnSize(maxNumDOF);
01851 
01852   int globalMaxNumDOF;
01853   CHK_ERR( fei::GlobalMax(comm_, maxNumDOF, globalMaxNumDOF) );
01854 
01855   if (globalMaxNumDOF == 1) {
01856     ptBlkMap_->setPtEqualBlk();
01857   }
01858 
01859   delete id2eqnStream;
01860 
01861   return(0);
01862 }
01863 
01864 //----------------------------------------------------------------------------
01865 int fei::VectorSpace::exchangeFieldInfo(fei::comm_map* ownerPattern,
01866                                         fei::comm_map* sharerPattern,
01867                                   snl_fei::RecordCollection* recordCollection,
01868                                       std::vector<fei::FieldMask*>& fieldMasks)
01869 {
01870   //ownerPattern maps owning processors to lists of IDs that we (the local
01871   //processor) share.
01872   //
01873   //sharerPattern maps sharing processors to lists of IDs that we own.
01874   //
01875   //In this function we need to perform these tasks:
01876   //1. processors exchange and combine their sets of field-masks so that all
01877   //   processors will have the super-set of field-masks that they need.
01878   //2. sharing processors send maskIDs for their shared IDs to the owning
01879   //   processors. The owning processors then combine masks as necessary to
01880   //   make sure each shared ID has the union of field-masks that are held by
01881   //   each of the sharing processors. all owning processors now send their
01882   //   maskIDs out to the sharing processors. At this point all processors
01883   //   should have the same view of the masks that belong on shared IDs.
01884   //3. exchange info describing inactive DOF offsets for shared records.
01885   //
01886 
01887   int numProcs = fei::numProcs(comm_);
01888   if (numProcs < 2) return(0);
01889 
01890   if (ptBlkMap_ == 0) ptBlkMap_ = new snl_fei::PointBlockMap;
01891 
01892   snl_fei::RecordMsgHandler recMsgHandler(fei::localProc(comm_),
01893                                           recordCollection,
01894                                           *ptBlkMap_,
01895                                           fieldMasks, eqnNumbers_);
01896 
01897   //Step 1a.
01898   recMsgHandler.setTask(snl_fei::RecordMsgHandler::_FieldMasks_);
01899 
01900   recMsgHandler.setSendPattern(ownerPattern);
01901   recMsgHandler.setRecvPattern(sharerPattern);
01902   CHK_ERR( fei::exchange(comm_, &recMsgHandler) );
01903 
01904   //Step 2a.
01905   recMsgHandler.setTask(snl_fei::RecordMsgHandler::_MaskIDs_);
01906 
01907   recMsgHandler.setSendPattern(ownerPattern);
01908   recMsgHandler.setRecvPattern(sharerPattern);
01909   CHK_ERR( fei::exchange(comm_, &recMsgHandler) );
01910 
01911   //Step 1b.
01912   recMsgHandler.setTask(snl_fei::RecordMsgHandler::_FieldMasks_);
01913 
01914   recMsgHandler.setSendPattern(sharerPattern);
01915   recMsgHandler.setRecvPattern(ownerPattern);
01916   CHK_ERR( fei::exchange(comm_, &recMsgHandler) );
01917 
01918   //Step 2b.
01919   recMsgHandler.setTask(snl_fei::RecordMsgHandler::_MaskIDs_);
01920 
01921   recMsgHandler.setSendPattern(sharerPattern);
01922   recMsgHandler.setRecvPattern(ownerPattern);
01923   CHK_ERR( fei::exchange(comm_, &recMsgHandler) );
01924 
01925   return(0);
01926 }
01927 
01928 //----------------------------------------------------------------------------
01929 void fei::VectorSpace::setName(const char* name)
01930 {
01931   if (name == NULL) return;
01932 
01933   if (name_ == name) return;
01934 
01935   name_ = name;
01936   dbgprefix_ = "VecSpc_"+name_+": ";
01937 }
01938 

Generated on Wed May 12 21:30:42 2010 for FEI by  doxygen 1.4.7