Teko Version of the Day
Teko_BlockedReordering.cpp
00001 /*
00002 // @HEADER
00003 // 
00004 // ***********************************************************************
00005 // 
00006 //      Teko: A package for block and physics based preconditioning
00007 //                  Copyright 2010 Sandia Corporation 
00008 //  
00009 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00010 // the U.S. Government retains certain rights in this software.
00011 //  
00012 // Redistribution and use in source and binary forms, with or without
00013 // modification, are permitted provided that the following conditions are
00014 // met:
00015 //  
00016 // 1. Redistributions of source code must retain the above copyright
00017 // notice, this list of conditions and the following disclaimer.
00018 //  
00019 // 2. Redistributions in binary form must reproduce the above copyright
00020 // notice, this list of conditions and the following disclaimer in the
00021 // documentation and/or other materials provided with the distribution.
00022 //  
00023 // 3. Neither the name of the Corporation nor the names of the
00024 // contributors may be used to endorse or promote products derived from
00025 // this software without specific prior written permission. 
00026 //  
00027 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00028 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00030 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00031 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00032 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00033 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00034 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00035 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00036 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00037 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038 //  
00039 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
00040 // 
00041 // ***********************************************************************
00042 // 
00043 // @HEADER
00044 
00045 */
00046 
00047 #include <iostream>
00048 #include <string>
00049 #include <vector>
00050 #include <stack>
00051 
00052 #include "Teko_BlockedReordering.hpp"
00053 #include "Teko_Utilities.hpp"
00054 
00055 #include "Teuchos_VerboseObject.hpp"
00056 #include "Teuchos_RCP.hpp"
00057 #include "Teuchos_StrUtils.hpp"
00058 
00059 #include "Thyra_DefaultProductMultiVector.hpp"
00060 #include "Thyra_DefaultProductVectorSpace.hpp"
00061 
00062 using Teuchos::RCP;
00063 using Teuchos::rcp;
00064 using Teuchos::rcp_dynamic_cast;
00065 using Teuchos::Array;
00066 
00067 namespace Teko {
00068 
00069 void BlockReorderManager::SetBlock(int blockIndex,int reorder)
00070 { 
00071    TEUCHOS_ASSERT(blockIndex<(int) children_.size());
00072 
00073    RCP<BlockReorderManager> child = rcp(new BlockReorderLeaf(reorder));
00074 
00075    children_[blockIndex] = child;
00076 }
00077 
00090 void BlockReorderManager::SetBlock(int blockIndex,const RCP<BlockReorderManager> & reorder)
00091 {
00092    TEUCHOS_ASSERT(blockIndex<(int) children_.size());
00093 
00094    children_[blockIndex] = reorder;
00095 }
00096 
00097 const Teuchos::RCP<BlockReorderManager> BlockReorderManager::GetBlock(int blockIndex)
00098 {
00099    TEUCHOS_ASSERT(blockIndex<(int) children_.size());
00100 
00101    if(children_[blockIndex]==Teuchos::null)
00102       children_[blockIndex] = rcp(new BlockReorderManager());
00103 
00104    return children_[blockIndex];
00105 }
00106 
00107 const Teuchos::RCP<const BlockReorderManager> BlockReorderManager::GetBlock(int blockIndex) const
00108 {
00109    TEUCHOS_ASSERT(blockIndex<(int) children_.size());
00110 
00111    return children_[blockIndex];
00112 }
00113 
00114 std::string BlockReorderManager::toString() const
00115 {
00116    // build the string by recursively calling each child
00117    std::stringstream ss;
00118    ss << "[";
00119    for(unsigned int i=0;i<children_.size();i++) {
00120       if(children_[i]==Teuchos::null) 
00121          ss << " <NULL> ";
00122       else
00123          ss << " " << children_[i]->toString() << " "; 
00124    }
00125    ss << "]";
00126 
00127    return ss.str();
00128 }
00129 
00130 int BlockReorderManager::LargestIndex() const
00131 {
00132    int max = 0;
00133    for(unsigned int i=0;i<children_.size();i++) {
00134       // see if current child is larger 
00135       if(children_[i]!=Teuchos::null) {
00136          int subMax = children_[i]->LargestIndex();
00137          max = max > subMax ? max : subMax;
00138       }
00139    }
00140 
00141    return max;
00142 } 
00143 
00144 Teuchos::RCP<const Thyra::LinearOpBase<double> >
00145 buildReorderedLinearOp(const BlockReorderManager & bmm,
00146                        const Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > & blkOp)
00147 {
00148    return buildReorderedLinearOp(bmm,bmm,blkOp);
00149 }
00150 
00151 Teuchos::RCP<const Thyra::LinearOpBase<double> >
00152 buildReorderedLinearOp(const BlockReorderManager & rowMgr,const BlockReorderManager & colMgr,
00153                        const Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > & blkOp)
00154 {
00155    typedef RCP<const BlockReorderManager> BRMptr;
00156 
00157    int rowSz = rowMgr.GetNumBlocks();
00158    int colSz = colMgr.GetNumBlocks();
00159 
00160    if(rowSz==0 && colSz==0) {
00161       // both are leaf nodes
00162       const BlockReorderLeaf & rowLeaf = dynamic_cast<const BlockReorderLeaf &>(rowMgr);
00163       const BlockReorderLeaf & colLeaf = dynamic_cast<const BlockReorderLeaf &>(colMgr);
00164 
00165       // simply return entry in matrix
00166       Teko::LinearOp linOp = blkOp->getBlock(rowLeaf.GetIndex(),colLeaf.GetIndex());
00167 
00168       // somehow we need to set this operator up
00169       if(linOp==Teuchos::null) {
00170          linOp = Thyra::zero(blkOp->productRange()->getBlock(rowLeaf.GetIndex()),
00171                              blkOp->productDomain()->getBlock(colLeaf.GetIndex()));
00172       }
00173 
00174       return linOp;
00175    }
00176    else if(rowSz==0) {
00177       Teko::BlockedLinearOp reBlkOp = Teko::createBlockedOp();
00178 
00179       // operator will be rowSz by colSz
00180       reBlkOp->beginBlockFill(1,colSz);   
00181 
00182       // fill the column entries
00183       for(int col=0;col<colSz;col++) {
00184          BRMptr colPtr = colMgr.GetBlock(col);
00185 
00186          reBlkOp->setBlock(0,col,buildReorderedLinearOp(rowMgr,*colPtr,blkOp));
00187       } 
00188 
00189       // done building
00190       reBlkOp->endBlockFill();   
00191 
00192       return reBlkOp;
00193    }
00194    else if(colSz==0) {
00195       Teko::BlockedLinearOp reBlkOp = Teko::createBlockedOp();
00196 
00197       // operator will be rowSz by colSz
00198       reBlkOp->beginBlockFill(rowSz,1);   
00199 
00200       // fill the row entries
00201       for(int row=0;row<rowSz;row++) {
00202          BRMptr rowPtr = rowMgr.GetBlock(row);
00203 
00204          reBlkOp->setBlock(row,0,buildReorderedLinearOp(*rowPtr,colMgr,blkOp));
00205       } 
00206 
00207       // done building
00208       reBlkOp->endBlockFill();   
00209 
00210       return reBlkOp;
00211    }
00212    else {
00213       Teko::BlockedLinearOp reBlkOp = Teko::createBlockedOp();
00214   
00215       // this is the general case
00216       TEUCHOS_ASSERT(rowSz>0);
00217       TEUCHOS_ASSERT(colSz>0);
00218 
00219       // operator will be rowSz by colSz
00220       reBlkOp->beginBlockFill(rowSz,colSz);   
00221    
00222       for(int row=0;row<rowSz;row++) {
00223          BRMptr rowPtr = rowMgr.GetBlock(row);
00224    
00225          for(int col=0;col<colSz;col++) {
00226             BRMptr colPtr = colMgr.GetBlock(col);
00227    
00228             reBlkOp->setBlock(row,col,buildReorderedLinearOp(*rowPtr,*colPtr,blkOp));
00229          } 
00230       }
00231 
00232       // done building
00233       reBlkOp->endBlockFill();   
00234 
00235       return reBlkOp;
00236    }
00237 }
00238 
00260 Teuchos::RCP<const Thyra::VectorSpaceBase<double> >
00261 buildReorderedVectorSpace(const BlockReorderManager & mgr,
00262                           const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<double> > & blkSpc)
00263 {
00264    typedef RCP<const BlockReorderManager> BRMptr;
00265 
00266    int sz = mgr.GetNumBlocks();
00267 
00268    if(sz==0) {
00269       // its a  leaf nodes
00270       const BlockReorderLeaf & leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
00271 
00272       // simply return entry in matrix
00273       return blkSpc->getBlock(leaf.GetIndex());
00274    } 
00275    else {
00276       Array<RCP<const Thyra::VectorSpaceBase<double> > > vecSpaces;
00277 
00278       // loop over each row
00279       for(int i=0;i<sz;i++) {
00280          BRMptr blkMgr = mgr.GetBlock(i);
00281 
00282          const RCP<const Thyra::VectorSpaceBase<double> > lvs = buildReorderedVectorSpace(*blkMgr,blkSpc);
00283 
00284          vecSpaces.push_back(lvs);
00285       }
00286 
00287       // build a vector space
00288       const RCP<const Thyra::DefaultProductVectorSpace<double> > vs 
00289             = Thyra::productVectorSpace<double>(vecSpaces);
00290 
00291       // build the vector
00292       return vs;
00293    }
00294 }
00295 
00300 Teuchos::RCP<Thyra::MultiVectorBase<double> >
00301 buildReorderedMultiVector(const BlockReorderManager & mgr,
00302                           const Teuchos::RCP<Thyra::ProductMultiVectorBase<double> > & blkVec)
00303 {
00304    typedef RCP<const BlockReorderManager> BRMptr;
00305 
00306    int sz = mgr.GetNumBlocks();
00307 
00308    if(sz==0) {
00309       // its a  leaf nodes
00310       const BlockReorderLeaf & leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
00311 
00312       // simply return entry in matrix
00313       return blkVec->getNonconstMultiVectorBlock(leaf.GetIndex());
00314    } 
00315    else {
00316       Array<RCP<Thyra::MultiVectorBase<double> > > multiVecs;
00317       Array<RCP<const Thyra::VectorSpaceBase<double> > > vecSpaces;
00318 
00319       // loop over each row
00320       for(int i=0;i<sz;i++) {
00321          BRMptr blkMgr = mgr.GetBlock(i);
00322 
00323          const RCP<Thyra::MultiVectorBase<double> > lmv = buildReorderedMultiVector(*blkMgr,blkVec);
00324          const RCP<const Thyra::VectorSpaceBase<double> > lvs = lmv->range();
00325 
00326          multiVecs.push_back(lmv);
00327          vecSpaces.push_back(lvs);
00328       }
00329 
00330       // build a vector space
00331       const RCP<const Thyra::DefaultProductVectorSpace<double> > vs 
00332             = Thyra::productVectorSpace<double>(vecSpaces);
00333 
00334       // build the vector
00335       return Thyra::defaultProductMultiVector<double>(vs,multiVecs);
00336    }
00337 }
00338 
00343 Teuchos::RCP<const Thyra::MultiVectorBase<double> >
00344 buildReorderedMultiVector(const BlockReorderManager & mgr,
00345                           const Teuchos::RCP<const Thyra::ProductMultiVectorBase<double> > & blkVec)
00346 {
00347    typedef RCP<const BlockReorderManager> BRMptr;
00348 
00349    int sz = mgr.GetNumBlocks();
00350 
00351    if(sz==0) {
00352       // its a  leaf nodes
00353       const BlockReorderLeaf & leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
00354 
00355       // simply return entry in matrix
00356       return blkVec->getMultiVectorBlock(leaf.GetIndex());
00357    } 
00358    else {
00359       Array<RCP<const Thyra::MultiVectorBase<double> > > multiVecs;
00360       Array<RCP<const Thyra::VectorSpaceBase<double> > > vecSpaces;
00361 
00362       // loop over each row
00363       for(int i=0;i<sz;i++) {
00364          BRMptr blkMgr = mgr.GetBlock(i);
00365 
00366          const RCP<const Thyra::MultiVectorBase<double> > lmv = buildReorderedMultiVector(*blkMgr,blkVec);
00367          const RCP<const Thyra::VectorSpaceBase<double> > lvs = lmv->range();
00368 
00369          multiVecs.push_back(lmv);
00370          vecSpaces.push_back(lvs);
00371       }
00372 
00373       // build a vector space
00374       const RCP<const Thyra::DefaultProductVectorSpace<double> > vs 
00375             = Thyra::productVectorSpace<double>(vecSpaces);
00376 
00377       // build the vector
00378       return Thyra::defaultProductMultiVector<double>(vs,multiVecs);
00379    }
00380 }
00381 
00385 void buildNonconstFlatMultiVector(const BlockReorderManager & mgr,
00386                                   const RCP<Thyra::MultiVectorBase<double> > & blkVec,
00387                                   Array<RCP<Thyra::MultiVectorBase<double> > > & multivecs,
00388                                   Array<RCP<const Thyra::VectorSpaceBase<double> > > & vecspaces)
00389 {
00390    typedef RCP<const BlockReorderManager> BRMptr;
00391 
00392    int sz = mgr.GetNumBlocks();
00393 
00394    if(sz==0) {
00395       // its a  leaf nodes
00396       const BlockReorderLeaf & leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
00397       int index = leaf.GetIndex();
00398 
00399       // simply return entry in matrix
00400       multivecs[index] = blkVec;
00401       vecspaces[index] = blkVec->range();
00402    } 
00403    else {
00404       const RCP<Thyra::ProductMultiVectorBase<double> > prodMV
00405             = rcp_dynamic_cast<Thyra::ProductMultiVectorBase<double> >(blkVec);
00406  
00407       // get flattened elements from each child
00408       for(int i=0;i<sz;i++) {
00409          const RCP<Thyra::MultiVectorBase<double> > mv = prodMV->getNonconstMultiVectorBlock(i);
00410          buildNonconstFlatMultiVector(*mgr.GetBlock(i),mv,multivecs,vecspaces);
00411       }
00412    }
00413    
00414 }
00415 
00419 void buildFlatMultiVector(const BlockReorderManager & mgr,
00420                           const RCP<const Thyra::MultiVectorBase<double> > & blkVec,
00421                           Array<RCP<const Thyra::MultiVectorBase<double> > > & multivecs,
00422                           Array<RCP<const Thyra::VectorSpaceBase<double> > > & vecspaces)
00423 {
00424    typedef RCP<const BlockReorderManager> BRMptr;
00425 
00426    int sz = mgr.GetNumBlocks();
00427 
00428    if(sz==0) {
00429       // its a  leaf nodes
00430       const BlockReorderLeaf & leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
00431       int index = leaf.GetIndex();
00432 
00433       // simply return entry in matrix
00434       multivecs[index] = blkVec;
00435       vecspaces[index] = blkVec->range();
00436    } 
00437    else {
00438       const RCP<const Thyra::ProductMultiVectorBase<double> > prodMV
00439             = rcp_dynamic_cast<const Thyra::ProductMultiVectorBase<double> >(blkVec);
00440  
00441       // get flattened elements from each child
00442       for(int i=0;i<sz;i++) {
00443          RCP<const Thyra::MultiVectorBase<double> > mv = prodMV->getMultiVectorBlock(i);
00444          buildFlatMultiVector(*mgr.GetBlock(i),mv,multivecs,vecspaces);
00445       }
00446    }
00447    
00448 }
00449 
00454 Teuchos::RCP<Thyra::MultiVectorBase<double> >
00455 buildFlatMultiVector(const BlockReorderManager & mgr,
00456                      const Teuchos::RCP<Thyra::ProductMultiVectorBase<double> > & blkVec)
00457 {
00458    int numBlocks = mgr.LargestIndex()+1;
00459  
00460    Array<RCP<Thyra::MultiVectorBase<double> > > multivecs(numBlocks);
00461    Array<RCP<const Thyra::VectorSpaceBase<double> > > vecspaces(numBlocks);
00462 
00463    // flatten everything into a vector first
00464    buildNonconstFlatMultiVector(mgr,blkVec,multivecs,vecspaces);
00465 
00466    // build a vector space
00467    const RCP<Thyra::DefaultProductVectorSpace<double> > vs 
00468          = Thyra::productVectorSpace<double>(vecspaces);
00469 
00470    // build the vector
00471    return Thyra::defaultProductMultiVector<double>(vs,multivecs);
00472 }
00473 
00478 Teuchos::RCP<const Thyra::MultiVectorBase<double> >
00479 buildFlatMultiVector(const BlockReorderManager & mgr,
00480                      const Teuchos::RCP<const Thyra::ProductMultiVectorBase<double> > & blkVec)
00481 {
00482    int numBlocks = mgr.LargestIndex()+1;
00483  
00484    Array<RCP<const Thyra::MultiVectorBase<double> > > multivecs(numBlocks);
00485    Array<RCP<const Thyra::VectorSpaceBase<double> > > vecspaces(numBlocks);
00486 
00487    // flatten everything into a vector first
00488    buildFlatMultiVector(mgr,blkVec,multivecs,vecspaces);
00489 
00490    // build a vector space
00491    const RCP<const Thyra::DefaultProductVectorSpace<double> > vs 
00492          = Thyra::productVectorSpace<double>(vecspaces);
00493 
00494    // build the vector
00495    return Thyra::defaultProductMultiVector<double>(vs,multivecs);
00496 }
00497 
00501 void buildFlatVectorSpace(const BlockReorderManager & mgr,
00502                           const RCP<const Thyra::VectorSpaceBase<double> > & blkSpc,
00503                           Array<RCP<const Thyra::VectorSpaceBase<double> > > & vecspaces)
00504 {
00505    typedef RCP<const BlockReorderManager> BRMptr;
00506 
00507    int sz = mgr.GetNumBlocks();
00508 
00509    if(sz==0) {
00510       // its a  leaf nodes
00511       const BlockReorderLeaf & leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
00512       int index = leaf.GetIndex();
00513 
00514       // simply return entry in matrix
00515       vecspaces[index] = blkSpc;
00516    } 
00517    else {
00518       const RCP<const Thyra::ProductVectorSpaceBase<double> > prodSpc
00519             = rcp_dynamic_cast<const Thyra::ProductVectorSpaceBase<double> >(blkSpc);
00520  
00521       // get flattened elements from each child
00522       for(int i=0;i<sz;i++) {
00523          RCP<const Thyra::VectorSpaceBase<double> > space = prodSpc->getBlock(i);
00524          buildFlatVectorSpace(*mgr.GetBlock(i),space,vecspaces);
00525       }
00526    }
00527    
00528 }
00529 
00532 Teuchos::RCP<const Thyra::VectorSpaceBase<double> >
00533 buildFlatVectorSpace(const BlockReorderManager & mgr,
00534                      const Teuchos::RCP<const Thyra::VectorSpaceBase<double> > & blkSpc)
00535 {
00536    int numBlocks = mgr.LargestIndex()+1;
00537  
00538    Array<RCP<const Thyra::VectorSpaceBase<double> > > vecspaces(numBlocks);
00539 
00540    // flatten everything into a vector first
00541    buildFlatVectorSpace(mgr,blkSpc,vecspaces);
00542 
00543    // build a vector space
00544    return Thyra::productVectorSpace<double>(vecspaces);
00545 }
00546 
00548 // The next three functions are useful for parsing the string
00549 // description of a BlockReorderManager.
00551 
00552 // this function tokenizes a string, breaking out whitespace but saving the
00553 // brackets [,] as special tokens.
00554 static void tokenize(std::string srcInput,std::string whitespace,std::string prefer,
00555               std::vector<std::string> & tokens)
00556 {
00557    std::string input = srcInput;
00558    std::vector<std::string> wsTokens;
00559    std::size_t endPos   = input.length()-1;
00560    while(endPos<input.length()) {
00561       std::size_t next = input.find_first_of(whitespace);
00562 
00563 
00564       // get the sub string
00565       std::string s;
00566       if(next!=std::string::npos) {
00567          s = input.substr(0,next);
00568 
00569          // break out the old substring
00570          input = input.substr(next+1,endPos);
00571       }
00572       else {
00573          s = input;
00574          input = "";
00575       }
00576 
00577       endPos   = input.length()-1;
00578 
00579       // add it to the WS tokens list
00580       if(s=="") continue;
00581       wsTokens.push_back(s);
00582    }
00583 
00584    for(unsigned int i=0;i<wsTokens.size();i++) {
00585       // get string to break up
00586       input = wsTokens[i];
00587 
00588       std::size_t endPos   = input.length()-1;
00589       while(endPos<input.length()) {
00590          std::size_t next = input.find_first_of(prefer);
00591 
00592          std::string s = input;
00593          if(next>0 && next<input.length()) {
00594 
00595             // get the sub string
00596             s = input.substr(0,next);
00597  
00598             input = input.substr(next,endPos);
00599          }
00600          else if(next==0) {
00601             // get the sub string
00602             s = input.substr(0,next+1);
00603  
00604             input = input.substr(next+1,endPos);
00605          }
00606          else input = "";
00607 
00608          // break out the old substring
00609          endPos   = input.length()-1;
00610 
00611          // add it to the tokens list
00612          tokens.push_back(s);
00613       }
00614    }
00615 }
00616 
00617 // this function takes a set of tokens and returns the first "block", i.e. those
00618 // values (including) brackets that correspond to the first block
00619 static std::vector<std::string>::const_iterator 
00620 buildSubBlock(std::vector<std::string>::const_iterator begin,
00621               std::vector<std::string>::const_iterator end, std::vector<std::string> & subBlock)
00622 {
00623    std::stack<std::string> matched;
00624    std::vector<std::string>::const_iterator itr;
00625    for(itr=begin;itr!=end;++itr) { 
00626 
00627       subBlock.push_back(*itr);
00628 
00629       // push/pop brackets as they are discovered
00630       if(*itr=="[") matched.push("["); 
00631       else if(*itr=="]") matched.pop(); 
00632 
00633       // found all matching brackets
00634       if(matched.empty()) 
00635          return itr;
00636    }
00637 
00638    TEUCHOS_ASSERT(matched.empty());
00639 
00640    return itr-1;
00641 }
00642 
00643 // This function takes a tokenized vector and converts it to a block reorder manager
00644 static RCP<BlockReorderManager> blockedReorderFromTokens(const std::vector<std::string> & tokens)
00645 {
00646    // base case
00647    if(tokens.size()==1)
00648       return rcp(new Teko::BlockReorderLeaf(Teuchos::StrUtils::atoi(tokens[0])));
00649 
00650    // check first and last character
00651    TEUCHOS_ASSERT(*(tokens.begin())=="[")
00652    TEUCHOS_ASSERT(*(tokens.end()-1)=="]");
00653 
00654    std::vector<RCP<Teko::BlockReorderManager> > vecRMgr;
00655    std::vector<std::string>::const_iterator itr = tokens.begin()+1; 
00656    while(itr!=tokens.end()-1) {
00657       // figure out which tokens are relevant for this block
00658       std::vector<std::string> subBlock;
00659       itr = buildSubBlock(itr,tokens.end()-1,subBlock); 
00660 
00661       // build the child block reorder manager
00662       vecRMgr.push_back(blockedReorderFromTokens(subBlock));
00663 
00664       // move the iterator one more
00665       itr++;
00666    }
00667 
00668    // build the parent reorder manager
00669    RCP<Teko::BlockReorderManager> rMgr = rcp(new Teko::BlockReorderManager(vecRMgr.size()));
00670    for(unsigned int i=0;i<vecRMgr.size();i++)
00671       rMgr->SetBlock(i,vecRMgr[i]);
00672 
00673    return rMgr;
00674 }
00675 
00677 
00689 Teuchos::RCP<const BlockReorderManager> blockedReorderFromString(std::string & reorder)
00690 {
00691    // vector of tokens to use
00692    std::vector<std::string> tokens;
00693    
00694    // manager to be returned
00695 
00696    // build tokens vector
00697    tokenize(reorder," \t\n","[]",tokens);
00698 
00699    // parse recursively and build reorder manager
00700    Teuchos::RCP<BlockReorderManager> mgr = blockedReorderFromTokens(tokens);
00701 
00702    return mgr;
00703 }
00704 
00705 } // end namespace Teko
 All Classes Files Functions Variables