Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_BlockedReordering.cpp
1 /*
2 // @HEADER
3 //
4 // ***********************************************************************
5 //
6 // Teko: A package for block and physics based preconditioning
7 // Copyright 2010 Sandia Corporation
8 //
9 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 */
46 
47 #include <iostream>
48 #include <string>
49 #include <vector>
50 #include <stack>
51 
52 #include "Teko_BlockedReordering.hpp"
53 #include "Teko_Utilities.hpp"
54 
55 #include "Teuchos_VerboseObject.hpp"
56 #include "Teuchos_RCP.hpp"
57 #include "Teuchos_StrUtils.hpp"
58 
59 #include "Thyra_DefaultProductMultiVector.hpp"
60 #include "Thyra_DefaultProductVectorSpace.hpp"
61 
62 using Teuchos::Array;
63 using Teuchos::RCP;
64 using Teuchos::rcp;
65 using Teuchos::rcp_dynamic_cast;
66 
67 namespace Teko {
68 
69 void BlockReorderManager::SetBlock(int blockIndex, int reorder) {
70  TEUCHOS_ASSERT(blockIndex < (int)children_.size());
71 
72  RCP<BlockReorderManager> child = rcp(new BlockReorderLeaf(reorder));
73 
74  children_[blockIndex] = child;
75 }
76 
89 void BlockReorderManager::SetBlock(int blockIndex, const RCP<BlockReorderManager> &reorder) {
90  TEUCHOS_ASSERT(blockIndex < (int)children_.size());
91 
92  children_[blockIndex] = reorder;
93 }
94 
95 const Teuchos::RCP<BlockReorderManager> BlockReorderManager::GetBlock(int blockIndex) {
96  TEUCHOS_ASSERT(blockIndex < (int)children_.size());
97 
98  if (children_[blockIndex] == Teuchos::null)
99  children_[blockIndex] = rcp(new BlockReorderManager());
100 
101  return children_[blockIndex];
102 }
103 
104 const Teuchos::RCP<const BlockReorderManager> BlockReorderManager::GetBlock(int blockIndex) const {
105  TEUCHOS_ASSERT(blockIndex < (int)children_.size());
106 
107  return children_[blockIndex];
108 }
109 
110 std::string BlockReorderManager::toString() const {
111  // build the string by recursively calling each child
112  std::stringstream ss;
113  ss << "[";
114  for (unsigned int i = 0; i < children_.size(); i++) {
115  if (children_[i] == Teuchos::null)
116  ss << " <NULL> ";
117  else
118  ss << " " << children_[i]->toString() << " ";
119  }
120  ss << "]";
121 
122  return ss.str();
123 }
124 
126  int max = 0;
127  for (unsigned int i = 0; i < children_.size(); i++) {
128  // see if current child is larger
129  if (children_[i] != Teuchos::null) {
130  int subMax = children_[i]->LargestIndex();
131  max = max > subMax ? max : subMax;
132  }
133  }
134 
135  return max;
136 }
137 
138 Teuchos::RCP<const Thyra::LinearOpBase<double> > buildReorderedLinearOp(
139  const BlockReorderManager &bmm,
140  const Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > &blkOp) {
141  return buildReorderedLinearOp(bmm, bmm, blkOp);
142 }
143 
144 Teuchos::RCP<const Thyra::LinearOpBase<double> > buildReorderedLinearOp(
145  const BlockReorderManager &rowMgr, const BlockReorderManager &colMgr,
146  const Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > &blkOp) {
147  typedef RCP<const BlockReorderManager> BRMptr;
148 
149  int rowSz = rowMgr.GetNumBlocks();
150  int colSz = colMgr.GetNumBlocks();
151 
152  if (rowSz == 0 && colSz == 0) {
153  // both are leaf nodes
154  const BlockReorderLeaf &rowLeaf = dynamic_cast<const BlockReorderLeaf &>(rowMgr);
155  const BlockReorderLeaf &colLeaf = dynamic_cast<const BlockReorderLeaf &>(colMgr);
156 
157  // simply return entry in matrix
158  Teko::LinearOp linOp = blkOp->getBlock(rowLeaf.GetIndex(), colLeaf.GetIndex());
159 
160  // somehow we need to set this operator up
161  if (linOp == Teuchos::null) {
162  linOp = Thyra::zero(blkOp->productRange()->getBlock(rowLeaf.GetIndex()),
163  blkOp->productDomain()->getBlock(colLeaf.GetIndex()));
164  }
165 
166  return linOp;
167  } else if (rowSz == 0) {
168  Teko::BlockedLinearOp reBlkOp = Teko::createBlockedOp();
169 
170  // operator will be rowSz by colSz
171  reBlkOp->beginBlockFill(1, colSz);
172 
173  // fill the column entries
174  for (int col = 0; col < colSz; col++) {
175  BRMptr colPtr = colMgr.GetBlock(col);
176 
177  reBlkOp->setBlock(0, col, buildReorderedLinearOp(rowMgr, *colPtr, blkOp));
178  }
179 
180  // done building
181  reBlkOp->endBlockFill();
182 
183  return reBlkOp;
184  } else if (colSz == 0) {
185  Teko::BlockedLinearOp reBlkOp = Teko::createBlockedOp();
186 
187  // operator will be rowSz by colSz
188  reBlkOp->beginBlockFill(rowSz, 1);
189 
190  // fill the row entries
191  for (int row = 0; row < rowSz; row++) {
192  BRMptr rowPtr = rowMgr.GetBlock(row);
193 
194  reBlkOp->setBlock(row, 0, buildReorderedLinearOp(*rowPtr, colMgr, blkOp));
195  }
196 
197  // done building
198  reBlkOp->endBlockFill();
199 
200  return reBlkOp;
201  } else {
202  Teko::BlockedLinearOp reBlkOp = Teko::createBlockedOp();
203 
204  // this is the general case
205  TEUCHOS_ASSERT(rowSz > 0);
206  TEUCHOS_ASSERT(colSz > 0);
207 
208  // operator will be rowSz by colSz
209  reBlkOp->beginBlockFill(rowSz, colSz);
210 
211  for (int row = 0; row < rowSz; row++) {
212  BRMptr rowPtr = rowMgr.GetBlock(row);
213 
214  for (int col = 0; col < colSz; col++) {
215  BRMptr colPtr = colMgr.GetBlock(col);
216 
217  reBlkOp->setBlock(row, col, buildReorderedLinearOp(*rowPtr, *colPtr, blkOp));
218  }
219  }
220 
221  // done building
222  reBlkOp->endBlockFill();
223 
224  return reBlkOp;
225  }
226 }
227 
249 Teuchos::RCP<const Thyra::VectorSpaceBase<double> > buildReorderedVectorSpace(
250  const BlockReorderManager &mgr,
251  const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<double> > &blkSpc) {
252  typedef RCP<const BlockReorderManager> BRMptr;
253 
254  int sz = mgr.GetNumBlocks();
255 
256  if (sz == 0) {
257  // its a leaf nodes
258  const BlockReorderLeaf &leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
259 
260  // simply return entry in matrix
261  return blkSpc->getBlock(leaf.GetIndex());
262  } else {
263  Array<RCP<const Thyra::VectorSpaceBase<double> > > vecSpaces;
264 
265  // loop over each row
266  for (int i = 0; i < sz; i++) {
267  BRMptr blkMgr = mgr.GetBlock(i);
268 
269  const RCP<const Thyra::VectorSpaceBase<double> > lvs =
270  buildReorderedVectorSpace(*blkMgr, blkSpc);
271 
272  vecSpaces.push_back(lvs);
273  }
274 
275  // build a vector space
276  const RCP<const Thyra::DefaultProductVectorSpace<double> > vs =
277  Thyra::productVectorSpace<double>(vecSpaces);
278 
279  // build the vector
280  return vs;
281  }
282 }
283 
288 Teuchos::RCP<Thyra::MultiVectorBase<double> > buildReorderedMultiVector(
289  const BlockReorderManager &mgr,
290  const Teuchos::RCP<Thyra::ProductMultiVectorBase<double> > &blkVec) {
291  typedef RCP<const BlockReorderManager> BRMptr;
292 
293  int sz = mgr.GetNumBlocks();
294 
295  if (sz == 0) {
296  // its a leaf nodes
297  const BlockReorderLeaf &leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
298 
299  // simply return entry in matrix
300  return blkVec->getNonconstMultiVectorBlock(leaf.GetIndex());
301  } else {
302  Array<RCP<Thyra::MultiVectorBase<double> > > multiVecs;
303  Array<RCP<const Thyra::VectorSpaceBase<double> > > vecSpaces;
304 
305  // loop over each row
306  for (int i = 0; i < sz; i++) {
307  BRMptr blkMgr = mgr.GetBlock(i);
308 
309  const RCP<Thyra::MultiVectorBase<double> > lmv = buildReorderedMultiVector(*blkMgr, blkVec);
310  const RCP<const Thyra::VectorSpaceBase<double> > lvs = lmv->range();
311 
312  multiVecs.push_back(lmv);
313  vecSpaces.push_back(lvs);
314  }
315 
316  // build a vector space
317  const RCP<const Thyra::DefaultProductVectorSpace<double> > vs =
318  Thyra::productVectorSpace<double>(vecSpaces);
319 
320  // build the vector
321  return Thyra::defaultProductMultiVector<double>(vs, multiVecs);
322  }
323 }
324 
329 Teuchos::RCP<const Thyra::MultiVectorBase<double> > buildReorderedMultiVector(
330  const BlockReorderManager &mgr,
331  const Teuchos::RCP<const Thyra::ProductMultiVectorBase<double> > &blkVec) {
332  typedef RCP<const BlockReorderManager> BRMptr;
333 
334  int sz = mgr.GetNumBlocks();
335 
336  if (sz == 0) {
337  // its a leaf nodes
338  const BlockReorderLeaf &leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
339 
340  // simply return entry in matrix
341  return blkVec->getMultiVectorBlock(leaf.GetIndex());
342  } else {
343  Array<RCP<const Thyra::MultiVectorBase<double> > > multiVecs;
344  Array<RCP<const Thyra::VectorSpaceBase<double> > > vecSpaces;
345 
346  // loop over each row
347  for (int i = 0; i < sz; i++) {
348  BRMptr blkMgr = mgr.GetBlock(i);
349 
350  const RCP<const Thyra::MultiVectorBase<double> > lmv =
351  buildReorderedMultiVector(*blkMgr, blkVec);
352  const RCP<const Thyra::VectorSpaceBase<double> > lvs = lmv->range();
353 
354  multiVecs.push_back(lmv);
355  vecSpaces.push_back(lvs);
356  }
357 
358  // build a vector space
359  const RCP<const Thyra::DefaultProductVectorSpace<double> > vs =
360  Thyra::productVectorSpace<double>(vecSpaces);
361 
362  // build the vector
363  return Thyra::defaultProductMultiVector<double>(vs, multiVecs);
364  }
365 }
366 
370 void buildNonconstFlatMultiVector(const BlockReorderManager &mgr,
371  const RCP<Thyra::MultiVectorBase<double> > &blkVec,
372  Array<RCP<Thyra::MultiVectorBase<double> > > &multivecs,
373  Array<RCP<const Thyra::VectorSpaceBase<double> > > &vecspaces) {
374  int sz = mgr.GetNumBlocks();
375 
376  if (sz == 0) {
377  // its a leaf nodes
378  const BlockReorderLeaf &leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
379  int index = leaf.GetIndex();
380 
381  // simply return entry in matrix
382  multivecs[index] = blkVec;
383  vecspaces[index] = blkVec->range();
384  } else {
385  const RCP<Thyra::ProductMultiVectorBase<double> > prodMV =
386  rcp_dynamic_cast<Thyra::ProductMultiVectorBase<double> >(blkVec);
387 
388  // get flattened elements from each child
389  for (int i = 0; i < sz; i++) {
390  const RCP<Thyra::MultiVectorBase<double> > mv = prodMV->getNonconstMultiVectorBlock(i);
391  buildNonconstFlatMultiVector(*mgr.GetBlock(i), mv, multivecs, vecspaces);
392  }
393  }
394 }
395 
399 void buildFlatMultiVector(const BlockReorderManager &mgr,
400  const RCP<const Thyra::MultiVectorBase<double> > &blkVec,
401  Array<RCP<const Thyra::MultiVectorBase<double> > > &multivecs,
402  Array<RCP<const Thyra::VectorSpaceBase<double> > > &vecspaces) {
403  int sz = mgr.GetNumBlocks();
404 
405  if (sz == 0) {
406  // its a leaf nodes
407  const BlockReorderLeaf &leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
408  int index = leaf.GetIndex();
409 
410  // simply return entry in matrix
411  multivecs[index] = blkVec;
412  vecspaces[index] = blkVec->range();
413  } else {
414  const RCP<const Thyra::ProductMultiVectorBase<double> > prodMV =
415  rcp_dynamic_cast<const Thyra::ProductMultiVectorBase<double> >(blkVec);
416 
417  // get flattened elements from each child
418  for (int i = 0; i < sz; i++) {
419  RCP<const Thyra::MultiVectorBase<double> > mv = prodMV->getMultiVectorBlock(i);
420  buildFlatMultiVector(*mgr.GetBlock(i), mv, multivecs, vecspaces);
421  }
422  }
423 }
424 
429 Teuchos::RCP<Thyra::MultiVectorBase<double> > buildFlatMultiVector(
430  const BlockReorderManager &mgr,
431  const Teuchos::RCP<Thyra::ProductMultiVectorBase<double> > &blkVec) {
432  int numBlocks = mgr.LargestIndex() + 1;
433 
434  Array<RCP<Thyra::MultiVectorBase<double> > > multivecs(numBlocks);
435  Array<RCP<const Thyra::VectorSpaceBase<double> > > vecspaces(numBlocks);
436 
437  // flatten everything into a vector first
438  buildNonconstFlatMultiVector(mgr, blkVec, multivecs, vecspaces);
439 
440  // build a vector space
441  const RCP<Thyra::DefaultProductVectorSpace<double> > vs =
442  Thyra::productVectorSpace<double>(vecspaces);
443 
444  // build the vector
445  return Thyra::defaultProductMultiVector<double>(vs, multivecs);
446 }
447 
452 Teuchos::RCP<const Thyra::MultiVectorBase<double> > buildFlatMultiVector(
453  const BlockReorderManager &mgr,
454  const Teuchos::RCP<const Thyra::ProductMultiVectorBase<double> > &blkVec) {
455  int numBlocks = mgr.LargestIndex() + 1;
456 
457  Array<RCP<const Thyra::MultiVectorBase<double> > > multivecs(numBlocks);
458  Array<RCP<const Thyra::VectorSpaceBase<double> > > vecspaces(numBlocks);
459 
460  // flatten everything into a vector first
461  buildFlatMultiVector(mgr, blkVec, multivecs, vecspaces);
462 
463  // build a vector space
464  const RCP<const Thyra::DefaultProductVectorSpace<double> > vs =
465  Thyra::productVectorSpace<double>(vecspaces);
466 
467  // build the vector
468  return Thyra::defaultProductMultiVector<double>(vs, multivecs);
469 }
470 
474 void buildFlatVectorSpace(const BlockReorderManager &mgr,
475  const RCP<const Thyra::VectorSpaceBase<double> > &blkSpc,
476  Array<RCP<const Thyra::VectorSpaceBase<double> > > &vecspaces) {
477  int sz = mgr.GetNumBlocks();
478 
479  if (sz == 0) {
480  // its a leaf nodes
481  const BlockReorderLeaf &leaf = dynamic_cast<const BlockReorderLeaf &>(mgr);
482  int index = leaf.GetIndex();
483 
484  // simply return entry in matrix
485  vecspaces[index] = blkSpc;
486  } else {
487  const RCP<const Thyra::ProductVectorSpaceBase<double> > prodSpc =
488  rcp_dynamic_cast<const Thyra::ProductVectorSpaceBase<double> >(blkSpc);
489 
490  // get flattened elements from each child
491  for (int i = 0; i < sz; i++) {
492  RCP<const Thyra::VectorSpaceBase<double> > space = prodSpc->getBlock(i);
493  buildFlatVectorSpace(*mgr.GetBlock(i), space, vecspaces);
494  }
495  }
496 }
497 
500 Teuchos::RCP<const Thyra::VectorSpaceBase<double> > buildFlatVectorSpace(
501  const BlockReorderManager &mgr,
502  const Teuchos::RCP<const Thyra::VectorSpaceBase<double> > &blkSpc) {
503  int numBlocks = mgr.LargestIndex() + 1;
504 
505  Array<RCP<const Thyra::VectorSpaceBase<double> > > vecspaces(numBlocks);
506 
507  // flatten everything into a vector first
508  buildFlatVectorSpace(mgr, blkSpc, vecspaces);
509 
510  // build a vector space
511  return Thyra::productVectorSpace<double>(vecspaces);
512 }
513 
515 // The next three functions are useful for parsing the string
516 // description of a BlockReorderManager.
518 
519 // this function tokenizes a string, breaking out whitespace but saving the
520 // brackets [,] as special tokens.
521 static void tokenize(std::string srcInput, std::string whitespace, std::string prefer,
522  std::vector<std::string> &tokens) {
523  std::string input = srcInput;
524  std::vector<std::string> wsTokens;
525  std::size_t endPos = input.length() - 1;
526  while (endPos < input.length()) {
527  std::size_t next = input.find_first_of(whitespace);
528 
529  // get the sub string
530  std::string s;
531  if (next != std::string::npos) {
532  s = input.substr(0, next);
533 
534  // break out the old substring
535  input = input.substr(next + 1, endPos);
536  } else {
537  s = input;
538  input = "";
539  }
540 
541  endPos = input.length() - 1;
542 
543  // add it to the WS tokens list
544  if (s == "") continue;
545  wsTokens.push_back(s);
546  }
547 
548  for (unsigned int i = 0; i < wsTokens.size(); i++) {
549  // get string to break up
550  input = wsTokens[i];
551 
552  endPos = input.length() - 1;
553  while (endPos < input.length()) {
554  std::size_t next = input.find_first_of(prefer);
555 
556  std::string s = input;
557  if (next > 0 && next < input.length()) {
558  // get the sub string
559  s = input.substr(0, next);
560 
561  input = input.substr(next, endPos);
562  } else if (next == 0) {
563  // get the sub string
564  s = input.substr(0, next + 1);
565 
566  input = input.substr(next + 1, endPos);
567  } else
568  input = "";
569 
570  // break out the old substring
571  endPos = input.length() - 1;
572 
573  // add it to the tokens list
574  tokens.push_back(s);
575  }
576  }
577 }
578 
579 // this function takes a set of tokens and returns the first "block", i.e. those
580 // values (including) brackets that correspond to the first block
581 static std::vector<std::string>::const_iterator buildSubBlock(
582  std::vector<std::string>::const_iterator begin, std::vector<std::string>::const_iterator end,
583  std::vector<std::string> &subBlock) {
584  std::stack<std::string> matched;
585  std::vector<std::string>::const_iterator itr;
586  for (itr = begin; itr != end; ++itr) {
587  subBlock.push_back(*itr);
588 
589  // push/pop brackets as they are discovered
590  if (*itr == "[")
591  matched.push("[");
592  else if (*itr == "]")
593  matched.pop();
594 
595  // found all matching brackets
596  if (matched.empty()) return itr;
597  }
598 
599  TEUCHOS_ASSERT(matched.empty());
600 
601  return itr - 1;
602 }
603 
604 // This function takes a tokenized vector and converts it to a block reorder manager
605 static RCP<BlockReorderManager> blockedReorderFromTokens(const std::vector<std::string> &tokens) {
606  // base case
607  if (tokens.size() == 1)
608  return rcp(new Teko::BlockReorderLeaf(Teuchos::StrUtils::atoi(tokens[0])));
609 
610  // check first and last character
611  TEUCHOS_ASSERT(*(tokens.begin()) == "[")
612  TEUCHOS_ASSERT(*(tokens.end() - 1) == "]");
613 
614  std::vector<RCP<Teko::BlockReorderManager> > vecRMgr;
615  std::vector<std::string>::const_iterator itr = tokens.begin() + 1;
616  while (itr != tokens.end() - 1) {
617  // figure out which tokens are relevant for this block
618  std::vector<std::string> subBlock;
619  itr = buildSubBlock(itr, tokens.end() - 1, subBlock);
620 
621  // build the child block reorder manager
622  vecRMgr.push_back(blockedReorderFromTokens(subBlock));
623 
624  // move the iterator one more
625  itr++;
626  }
627 
628  // build the parent reorder manager
629  RCP<Teko::BlockReorderManager> rMgr = rcp(new Teko::BlockReorderManager(vecRMgr.size()));
630  for (unsigned int i = 0; i < vecRMgr.size(); i++) rMgr->SetBlock(i, vecRMgr[i]);
631 
632  return rMgr;
633 }
634 
636 
648 Teuchos::RCP<const BlockReorderManager> blockedReorderFromString(std::string &reorder) {
649  // vector of tokens to use
650  std::vector<std::string> tokens;
651 
652  // manager to be returned
653 
654  // build tokens vector
655  tokenize(reorder, " \t\n", "[]", tokens);
656 
657  // parse recursively and build reorder manager
658  Teuchos::RCP<BlockReorderManager> mgr = blockedReorderFromTokens(tokens);
659 
660  return mgr;
661 }
662 
663 } // end namespace Teko
int GetIndex() const
Get the the index that is stored in this block.
std::vector< Teuchos::RCP< BlockReorderManager > > children_
Definitions of the subblocks.
Class that describes how a flat blocked operator should be reordered.
virtual int GetNumBlocks() const
Gets the number of subblocks.
virtual int LargestIndex() const
Largest index in this manager.
virtual const Teuchos::RCP< BlockReorderManager > GetBlock(int blockIndex)
Get a particular block. If there is no block at this index location return a new one.
Teuchos::RCP< Thyra::MultiVectorBase< double > > buildReorderedMultiVector(const BlockReorderManager &mgr, const Teuchos::RCP< Thyra::ProductMultiVectorBase< double > > &blkVec)
Convert a flat multi vector into a reordered multivector.
Teuchos::RCP< const Thyra::VectorSpaceBase< double > > buildReorderedVectorSpace(const BlockReorderManager &mgr, const Teuchos::RCP< const Thyra::ProductVectorSpaceBase< double > > &blkSpc)
Use the BlockReorderManager to change a flat vector space into a composite vector space...
virtual std::string toString() const
For sanities sake, print a readable string.
BlockReorderManager()
Basic empty constructor.
Teuchos::RCP< const BlockReorderManager > blockedReorderFromString(std::string &reorder)
Convert a string to a block reorder manager object.
virtual void SetBlock(int blockIndex, int reorder)
Sets the sublock to a specific index value.