FEI Version of the Day
SNL_FEI_Structure.hpp
00001 #ifndef _SNL_FEI_Structure_hpp_
00002 #define _SNL_FEI_Structure_hpp_
00003 
00004 /*--------------------------------------------------------------------*/
00005 /*    Copyright 2005 Sandia Corporation.                              */
00006 /*    Under the terms of Contract DE-AC04-94AL85000, there is a       */
00007 /*    non-exclusive license for use of this work by or on behalf      */
00008 /*    of the U.S. Government.  Export of this program may require     */
00009 /*    a license from the United States Government.                    */
00010 /*--------------------------------------------------------------------*/
00011 
00012 #include <fei_fwd.hpp>
00013 #include <fei_defs.h>
00014 #include <fei_constants.hpp>
00015 #include "fei_TemplateUtils.hpp"
00016 #include <snl_fei_PointBlockMap.hpp>
00017 #include <fei_EqnBuffer.hpp>
00018 #include <fei_FieldDofMap.hpp>
00019 #include <fei_CSRMat.hpp>
00020 #include <fei_CSVec.hpp>
00021 
00022 #include <fei_NodeCommMgr.hpp>
00023 #include <fei_NodeDatabase.hpp>
00024 #include <fei_NodeDescriptor.hpp>
00025 
00026 #include <fei_Lookup.hpp>
00027 
00043 class SNL_FEI_Structure : public Lookup {
00044  public:
00053    SNL_FEI_Structure(MPI_Comm comm);
00054 
00056    virtual ~SNL_FEI_Structure();
00057 
00073    int parameters(int numParams, const char*const* paramStrings);
00074 
00075    int initFields(int numFields, const int* fieldSizes, const int* fieldIDs,
00076                   const int* fieldTypes = NULL);
00077 
00078    int initElemBlock(GlobalID elemBlockID,
00079          int numElements,
00080          int numNodesPerElement,
00081          const int* numFieldsPerNode,
00082          const int* const* nodalFieldIDs,
00083          int numElemDofFieldsPerElement,
00084          const int* elemDofFieldIDs,
00085          int interleaveStrategy);
00086 
00087    int initElem(GlobalID elemBlockID,
00088     GlobalID elemID,
00089     const GlobalID* elemConn);
00090 
00091    int initSlaveVariable(GlobalID slaveNodeID, 
00092        int slaveFieldID,
00093        int offsetIntoSlaveField,
00094        int numMasterNodes,
00095        const GlobalID* masterNodeIDs,
00096        const int* masterFieldIDs,
00097        const double* weights,
00098        double rhsValue);
00099 
00100    int deleteMultCRs();
00101 
00102    int initSharedNodes(int numSharedNodes,
00103            const GlobalID *sharedNodeIDs,  
00104            const int* numProcsPerNode, 
00105            const int *const *sharingProcIDs);
00106 
00107    // constraint relation initialization
00108    //- lagrange multiplier formulation
00109    int initCRMult(int numCRNodes,
00110       const GlobalID* CRNodes,
00111       const int *CRFields,
00112       int& CRID);
00113 
00114    // - penalty function formulation
00115    int initCRPen(int numCRNodes,
00116      const GlobalID* CRNodes, 
00117      const int *CRFields,
00118      int& CRID); 
00119 
00120    int initComplete(bool generateGraph = true);
00121 
00122    std::map<int,int>& getFieldDatabase() { return(*fieldDatabase_); };
00123 
00125    const int* getFieldIDsPtr()
00126      {
00127        int len = fieldDatabase_->size();
00128        workarray_.resize(len*2);
00129        fei::copyToArrays<std::map<int,int> >(*fieldDatabase_, len,
00130              &workarray_[0],
00131              &workarray_[0]+len);
00132        return( &workarray_[0] );
00133      }
00134 
00136    const int* getFieldSizesPtr()
00137      {
00138        int len = fieldDatabase_->size();
00139        workarray_.resize(len*2);
00140        fei::copyToArrays<std::map<int,int> >(*fieldDatabase_, len,
00141              &workarray_[0],
00142              &workarray_[0]+len);
00143        return( &workarray_[0]+len );
00144      }
00145 
00147    int getNumFields() { return( fieldDatabase_->size() ); };
00148 
00150    int getFieldSize(int fieldID)
00151      {
00152        std::map<int,int>::const_iterator
00153    f_iter = fieldDatabase_->find(fieldID);
00154 
00155        return(f_iter != fieldDatabase_->end() ? (*f_iter).second : -1);
00156      }
00157 
00158    fei::FieldDofMap<int>& getFieldDofMap()
00159      { return fieldDofMap_; }
00160 
00162    bool isInLocalElement(int nodeNumber);
00163 
00164    const int* getNumFieldsPerNode(GlobalID blockID);
00165 
00166    const int* const* getFieldIDsTable(GlobalID blockID);
00167 
00172    int getEqnNumber(int nodeNumber, int fieldID);
00173 
00180    int getOwnerProcForEqn(int eqn);
00181 
00182 
00184    //now the element-block functions
00185 
00186    int getNumElemBlocks() {return(blockIDs_.size());};
00187    const GlobalID* getElemBlockIDs() {return(&blockIDs_[0]);};
00188 
00189    void getElemBlockInfo(GlobalID blockID,
00190                          int& interleaveStrategy, int& lumpingStrategy,
00191                          int& numElemDOF, int& numElements,
00192                          int& numNodesPerElem, int& numEqnsPerElem);
00193 
00194    int addBlock(GlobalID blockID);
00195 
00196    int getBlockDescriptor(GlobalID blockID, BlockDescriptor*& block);
00197 
00201    int getBlockDescriptor_index(int index, BlockDescriptor*& block);
00202 
00204    int getIndexOfBlock(GlobalID blockID);
00205 
00206    int allocateBlockConnectivity(GlobalID blockID);
00207    void destroyConnectivityTables();
00208 
00209    ConnectivityTable& getBlockConnectivity(GlobalID blockID);
00210 
00211    void getScatterIndices_ID(GlobalID blockID, GlobalID elemID,
00212                              int interleaveStrategy,
00213                              int* scatterIndices);
00214 
00215    void getScatterIndices_index(int blockIndex, int elemIndex,
00216                              int interleaveStrategy,
00217                              int* scatterIndices);
00218 
00219    int getBlkScatterIndices_index(int blockIndex,
00220           int elemIndex,
00221           int* scatterIndices);
00222 
00223    void getScatterIndices_ID(GlobalID blockID, GlobalID elemID,
00224                              int interleaveStrategy,
00225                              int* scatterIndices,
00226            int* blkScatterIndices,
00227            int* blkSizes);
00228 
00229    void getScatterIndices_index(int blockIndex, int elemIndex,
00230                              int interleaveStrategy,
00231                              int* scatterIndices,
00232            int* blkScatterIndices,
00233         int* blkSizes);
00234 
00235 
00237    //now the shared-node lookup functions from the Lookup interface.
00238 
00239    int getNumSharedNodes() {return(nodeCommMgr_->getNumSharedNodes());};
00240 
00241    const int* getSharedNodeNumbers() {
00242       return(&(nodeCommMgr_->getSharedNodeNumbers())[0]);
00243    };
00244 
00245    const int* getSharedNodeProcs(int nodeNumber) {
00246       int index = nodeCommMgr_->getSharedNodeIndex_num(nodeNumber);
00247       if (index < 0) return(NULL);
00248       return(&(nodeCommMgr_->getSharedNodeProcs(index))[0]);
00249    };
00250 
00251    int getNumSharingProcs(int nodeNumber) {
00252       int index = nodeCommMgr_->getSharedNodeIndex_num(nodeNumber);
00253       if (index < 0) return(-1);
00254       return(nodeCommMgr_->getSharedNodeProcs(index).size());
00255    };
00256 
00257    int getNumSubdomains(int nodeNumber) {
00258      const NodeDescriptor* node = NULL;
00259      int err = nodeDatabase_->getNodeWithNumber(nodeNumber, node);
00260      if (err != 0) return(-1);
00261      GlobalID nodeID = node->getGlobalNodeID();
00262      return(nodeCommMgr_->getSharedNodeNumSubdomains(nodeID));
00263    }
00264 
00265    int* getSubdomainList(int nodeNumber) {
00266      const NodeDescriptor* node = NULL;
00267      int err = nodeDatabase_->getNodeWithNumber(nodeNumber, node);
00268      if (err != 0) return(NULL);
00269      GlobalID nodeID = node->getGlobalNodeID();
00270      return(&(*(nodeCommMgr_->getSharedNodeSubdomainList(nodeID)))[0]);
00271 
00272    }
00273 
00274    int translateToReducedNodeNumber(int nodeNumber, int proc);
00275 
00277 
00279    int getAssociatedNodeNumber(int eqnNumber)
00280      {
00281        int eqn = translateFromReducedEqn(eqnNumber);
00282        int nodeNumber = nodeDatabase_->getAssociatedNodeNumber(eqn);
00283        int reducedNodeNumber = -1;
00284        if (nodeNumber >= 0) {
00285    reducedNodeNumber = translateToReducedNodeNumber(nodeNumber, localProc_);
00286        }
00287        return( reducedNodeNumber );
00288      }
00289 
00291    int getAssociatedFieldID(int eqnNumber)
00292      {
00293        int eqn = translateFromReducedEqn(eqnNumber);
00294        return( nodeDatabase_->getAssociatedFieldID(eqn) );
00295      }
00296 
00297 
00299    //now the point-eqn to block-eqn queries...
00300 
00301    bool isExactlyBlkEqn(int ptEqn) {
00302       return(blkEqnMapper_->isExactlyBlkEqn(ptEqn));
00303    };
00304 
00305    int ptEqnToBlkEqn(int ptEqn) {
00306       return(blkEqnMapper_->eqnToBlkEqn(ptEqn));
00307    };
00308  
00309    int getOffsetIntoBlkEqn(int blkEqn, int ptEqn) {
00310       return(blkEqnMapper_->getBlkEqnOffset(blkEqn, ptEqn));
00311    };
00312 
00313    int getBlkEqnSize(int blkEqn) {
00314       return(blkEqnMapper_->getBlkEqnSize(blkEqn));
00315    }
00317 
00318 
00319    int getNumActiveNodes() {return(nodeDatabase_->getNodeIDs().size());}
00320 
00321    NodeDatabase& getNodeDatabase() { return( *nodeDatabase_ ); }
00322 
00323    std::map<GlobalID,int>& getActiveNodeIDList()
00324      { return( nodeDatabase_->getNodeIDs() ); }
00325 
00326    std::vector<int>& getGlobalNodeOffsets() {return(globalNodeOffsets_);}
00327    std::vector<int>& getGlobalEqnOffsets() {return(globalEqnOffsets_);}
00328    std::vector<int>& getGlobalBlkEqnOffsets() {return(globalBlkEqnOffsets_);}
00329 
00330    NodeCommMgr& getNodeCommMgr() {return(*nodeCommMgr_);}
00331    EqnCommMgr&  getEqnCommMgr()  {return(*eqnCommMgr_ );}
00332 
00333    void initializeEqnCommMgr();
00334 
00335    void getEqnInfo(int& numGlobalEqns, int& numLocalEqns,
00336                    int& localStartRow, int& localEndRow);
00337 
00338    int getEqnNumbers(GlobalID ID, int idType, int fieldID,
00339          int& numEqns, int* eqnNumbers);
00340 
00341    int getEqnNumbers(int numIDs, const GlobalID* IDs,
00342          int idType, int fieldID,
00343          int& numEqns, int* eqnNumbers);
00344 
00345    void getEqnBlkInfo(int& numGlobalEqnBlks, int& numLocalEqnBlks,
00346                       int& localBlkOffset);
00347 
00348    snl_fei::PointBlockMap& getBlkEqnMapper() {return(*blkEqnMapper_);}
00349 
00350    void destroyMatIndices();
00351 
00352    int getNumMultConstRecords() {return(multCRs_.size());};
00353 
00354    std::map<GlobalID,snl_fei::Constraint<GlobalID>*>&
00355      getMultConstRecords()
00356      {return(multCRs_);};
00357 
00358    int getMultConstRecord(int CRID, snl_fei::Constraint<GlobalID>*& multCR)
00359    {
00360      std::map<int,snl_fei::Constraint<GlobalID>*>::iterator
00361        cr_iter = multCRs_.find(CRID);
00362      int returncode = -1;
00363      if (cr_iter != multCRs_.end()) {
00364        multCR = (*cr_iter).second;
00365        returncode = 0;
00366      }
00367 
00368      return( returncode );
00369    }
00370 
00371    int getNumPenConstRecords() {return(penCRs_.size());}
00372    std::map<GlobalID,snl_fei::Constraint<GlobalID>*>&
00373      getPenConstRecords()
00374      { return(penCRs_); }
00375 
00376    int getPenConstRecord(int CRID, snl_fei::Constraint<GlobalID>*& penCR)
00377    {
00378      std::map<int,snl_fei::Constraint<GlobalID>*>::iterator
00379        cr_iter = penCRs_.find(CRID);
00380      int returncode = -1;
00381      if (cr_iter != penCRs_.end()) {
00382        penCR = (*cr_iter).second;
00383        returncode = 0;
00384      }
00385 
00386      return( returncode );
00387    }
00388 
00389    void addSlaveVariable(SlaveVariable* svar) {slaveVars_->push_back(svar);}
00390 
00391    int calculateSlaveEqns(MPI_Comm comm);
00392 
00393    fei::FillableMat* getSlaveDependencies() {return(slaveMatrix_);}
00394 
00395    EqnBuffer* getSlaveEqns() { return(slaveEqns_); }
00396 
00397    int numSlaveEquations() { return(numSlvs_); }
00398 
00401    bool isSlaveEqn(int eqn);
00402 
00411    bool translateToReducedEqn(int eqn, int& reducedEqn);
00412 
00417    int translateToReducedEqns(EqnCommMgr& eqnCommMgr);
00418 
00423    int translateToReducedEqns(EqnBuffer& eqnBuf);
00424 
00429    int translateToReducedEqns(ProcEqns& procEqns);
00430 
00435    int translateMatToReducedEqns(fei::CSRMat& mat);
00436 
00442    int translateFromReducedEqn(int reducedEqn);
00443 
00450    int getMasterEqnNumbers(int slaveEqn, std::vector<int>*& masterEqns);
00451 
00458    int getMasterEqnCoefs(int slaveEqn, std::vector<double>*& masterCoefs);
00459 
00467    int getMasterEqnRHS(int slaveEqn, double& rhsValue);
00468 
00469    int getNumGlobalEqns() { return( numGlobalEqns_ ); }
00470    int getNumLocalEqns() { return( numLocalEqns_ ); }
00471    int getFirstLocalEqn() { return( localStartRow_ ); }
00472    int getLastLocalEqn() { return( localEndRow_ ); }
00473 
00474    int getFirstReducedEqn() { return( reducedStartRow_ ); }
00475    int getLastReducedEqn()  { return( reducedEndRow_   ); }
00476 
00477    int getNumGlobalEqnBlks() { return( numGlobalEqnBlks_ ); }
00478    int getNumLocalEqnBlks() { return( numLocalEqnBlks_ ); }
00479    int getNumLocalReducedEqnBlks() { return( numLocalReducedEqnBlks_ ); }
00480    int getGlobalMaxBlkSize() { return(globalMaxBlkSize_); }
00481 
00482    int getNumLocalReducedEqns() { return( numLocalReducedRows_ ); }
00483 
00484    int getMatrixRowLengths(std::vector<int>& rowLengths);
00485    int getMatrixStructure(int** colIndices, std::vector<int>& rowLengths);
00486 
00487    int getMatrixStructure(int** ptColIndices, std::vector<int>& ptRowLengths,
00488         int** blkColIndices, int* blkIndices_1D,
00489         std::vector<int>& blkRowLengths,
00490         std::vector<int>& numPtRowsPerBlkRow);
00491 
00492    static int gatherSlaveEqns(MPI_Comm comm,
00493             EqnCommMgr* eqnCommMgr,
00494             EqnBuffer* slaveEqns);
00495 
00496    static int removeCouplings(EqnBuffer& eqnbuf, int& levelsOfCoupling);
00497 
00498    int calcTotalNumElemDOF();
00499    int calcNumMultCREqns();
00500 
00501    MPI_Comm getCommunicator() const { return( comm_ ); }
00502 
00503 #ifdef FEI_HAVE_IOSFWD
00504    int setDbgOut(std::ostream& ostr, const char* path, const char* feiName);
00505 #else
00506    int setDbgOut(ostream& ostr, const char* path, const char* feiName);
00507 #endif
00508 
00509  private:
00510 
00511    NodeDescriptor& findNodeDescriptor(GlobalID nodeID);
00512 
00513    int writeEqn2NodeMap();
00514 
00515    int getElemNodeDescriptors(int blockIndex, int elemIndex,
00516                               NodeDescriptor** nodes);
00517 
00518    int getNodeIndices_simple(NodeDescriptor** nodes, int numNodes,
00519            int fieldID,
00520            int* scatterIndices, int& offset);
00521 
00522    int getNodeIndices_simple(NodeDescriptor** nodes, int numNodes,
00523            int fieldID,
00524            int* scatterIndices, int& offset,
00525            int* blkScatterIndices,
00526            int* blkSizes, int& blkOffset);
00527 
00528    int getNodeMajorIndices(NodeDescriptor** nodes, int numNodes,
00529                            int** fieldIDs, int* fieldsPerNode,
00530                            int* scatterIndices, int& offset);
00531 
00532    int getNodeBlkIndices(NodeDescriptor** nodes, int numNodes,
00533        int* scatterIndices, int& offset);
00534 
00535    int getNodeMajorIndices(NodeDescriptor** nodes, int numNodes,
00536                            int** fieldIDs, int* fieldsPerNode,
00537                            int* scatterIndices, int& offset,
00538          int* blkScatterIndices,
00539          int* blkSizes, int& blkOffset);
00540 
00541    int getNodeMajorIndices(NodeDescriptor** nodes, int numNodes,
00542                            std::vector<int>* fieldIDs,
00543                            std::vector<int>& fieldsPerNode,
00544                            std::vector<int>& scatterIndices);
00545 
00546    int getFieldMajorIndices(NodeDescriptor** nodes, int numNodes,
00547                             int** fieldIDs, int* fieldsPerNode,
00548                             int* scatterIndices, int& offset);
00549 
00550    int getFieldMajorIndices(NodeDescriptor** nodes, int numNodes,
00551                                           std::vector<int>* fieldIDs,
00552                                           std::vector<int>& fieldsPerNode,
00553                                           std::vector<int>& scatterIndices);
00554 
00555    void calcGlobalEqnInfo(int numLocallyOwnedNodes, 
00556         int numLocalEqns,
00557         int numLocalEqnBlks);
00558 
00559    int finalizeActiveNodes();
00560    int finalizeNodeCommMgr();
00561    bool activeNodesInitialized();
00562 
00563    int formMatrixStructure();
00564 
00565    int initElemBlockStructure();
00566    int initMultCRStructure();
00567    int initPenCRStructure();
00568    int createMatrixPosition(int row, int col, const char* callingFunction);
00569    int createMatrixPositions(int row, int numCols, int* cols,
00570            const char* callingFunction);
00571    int createMatrixPositions(fei::CSRMat& mat);
00572 
00573    int createSymmEqnStructure(std::vector<int>& scatterIndices);
00574    int createBlkSymmEqnStructure(std::vector<int>& scatterIndices);
00575 
00576    int storeElementScatterIndices(std::vector<int>& scatterIndices);
00577    int storeElementScatterIndices_noSlaves(std::vector<int>& scatterIndices);
00578    int storeElementScatterBlkIndices_noSlaves(std::vector<int>& scatterIndices);
00579 
00580    void storeLocalNodeIndices(NodeDescriptor& iNode, int iField,
00581                                      NodeDescriptor& jNode, int jField);
00582    void storeNodalColumnIndices(int eqn, NodeDescriptor& node,
00583                  int fieldID);
00584    void storeNodalRowIndices(NodeDescriptor& node, int fieldID, int eqn);
00585    void storeNodalSendIndex(NodeDescriptor& node, int fieldID, int col);
00586    void storeNodalSendIndices(NodeDescriptor& iNode, int iField,
00587                                   NodeDescriptor& jNode, int jField);
00588 
00589    int assembleReducedStructure();
00590 
00591    bool nodalEqnsAllSlaves(const NodeDescriptor* node, std::vector<int>& slaveEqns);
00592 
00593    int initializeBlkEqnMapper();
00594 
00595    int setNumNodesAndEqnsPerBlock();
00596 
00597    void destroyBlockRoster();
00598 
00599 #ifdef FEI_HAVE_IOSFWD
00600    std::ostream& dbgOut() { return( *dbgOStreamPtr_ ); }
00601 #else
00602    ostream& dbgOut() { return( *dbgOStreamPtr_ ); }
00603 #endif
00604 
00605    void addCR(int CRID,
00606        snl_fei::Constraint<GlobalID>*& cr,
00607        std::map<GlobalID,snl_fei::Constraint<GlobalID>* >& crDB);
00608 
00609    int setNodalEqnInfo();
00610    void setElemDOFEqnInfo();
00611    int setMultCREqnInfo();
00612 
00613    SNL_FEI_Structure(const SNL_FEI_Structure& src);
00614    SNL_FEI_Structure& operator=(const SNL_FEI_Structure& src);
00615 
00616    MPI_Comm comm_;
00617 
00618    int localProc_, masterProc_, numProcs_;
00619 
00620    std::map<int,int>* fieldDatabase_;
00621    fei::FieldDofMap<int> fieldDofMap_;
00622    std::vector<int> workarray_;
00623 
00624    std::vector<GlobalID> blockIDs_;
00625    std::vector<BlockDescriptor*> blocks_;
00626    std::vector<ConnectivityTable*> connTables_;
00627 
00628    NodeDatabase* nodeDatabase_;
00629 
00630    bool activeNodesInitialized_;
00631 
00632    std::vector<int> globalNodeOffsets_;
00633    std::vector<int> globalEqnOffsets_;
00634    std::vector<int> globalBlkEqnOffsets_;
00635 
00636    std::vector<SlaveVariable*>* slaveVars_;
00637    EqnBuffer* slaveEqns_;
00638    std::vector<int>* slvEqnNumbers_;
00639    int numSlvs_, lowestSlv_, highestSlv_;
00640    fei::FillableMat* slaveMatrix_;
00641    std::vector<int> globalNumNodesVanished_;
00642    std::vector<int> localVanishedNodeNumbers_;
00643 
00644    NodeCommMgr* nodeCommMgr_;
00645    EqnCommMgr* eqnCommMgr_;
00646    EqnCommMgr* slvCommMgr_;
00647 
00648    int numGlobalEqns_;
00649    int numLocalEqns_;
00650    int localStartRow_;
00651    int localEndRow_;
00652 
00653    int numLocalNodalEqns_;
00654    int numLocalElemDOF_;
00655    int numLocalMultCRs_;
00656 
00657    int reducedStartRow_, reducedEndRow_, numLocalReducedRows_;
00658    fei::FillableMat *Kid_, *Kdi_, *Kdd_;
00659    fei::CSRMat csrD, csrKid, csrKdi, csrKdd, tmpMat1_, tmpMat2_;
00660    int reducedEqnCounter_, reducedRHSCounter_;
00661    std::vector<int> rSlave_, cSlave_;
00662    std::vector<NodeDescriptor*> work_nodePtrs_;
00663 
00664    bool structureFinalized_;
00665    bool generateGraph_;
00666 
00667    fei::ctg_set<int>* sysMatIndices_;
00668 
00669    bool blockMatrix_;
00670    int numGlobalEqnBlks_;
00671    int numLocalEqnBlks_;
00672    int numLocalReducedEqnBlks_;
00673    int localBlkOffset_;
00674    int localReducedBlkOffset_;
00675    int globalMaxBlkSize_;
00676 
00677    int firstLocalNodeNumber_;
00678    int numGlobalNodes_;
00679 
00680    fei::ctg_set<int>* sysBlkMatIndices_;
00681    bool matIndicesDestroyed_;
00682 
00683    std::vector<int> workSpace_;
00684 
00685    snl_fei::PointBlockMap* blkEqnMapper_;
00686 
00687    std::map<GlobalID, snl_fei::Constraint<GlobalID>* > multCRs_;
00688 
00689    std::map<GlobalID, snl_fei::Constraint<GlobalID>* > penCRs_;
00690 
00691    bool checkSharedNodes_;
00692 
00693    std::string name_;
00694 
00695    int outputLevel_;
00696    bool debugOutput_;
00697    std::string dbgPath_;
00698 #ifdef FEI_HAVE_IOSFWD
00699    std::ostream* dbgOStreamPtr_;
00700 #else
00701    ostream* dbgOStreamPtr_;
00702 #endif
00703    bool setDbgOutCalled_;
00704 };
00705 
00706 #endif
00707 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends