Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
PreconditionerOperator_def.hpp
1#ifndef PreconditionerOperator_DEF_hpp
2#define PreconditionerOperator_DEF_hpp
3#include "PreconditionerOperator_decl.hpp"
4
5
14
15namespace FEDD {
16using namespace Thyra;
17
18// Constructors
19
20
21template<class SC, class LO, class GO, class NO>
22PreconditionerOperator<SC, LO, GO, NO>::PreconditionerOperator()
23:numRowBlocks_(0), numColBlocks_(0), blockFillIsActive_(false)
24{}
25
26
27// Overridden from PhysicallyBlockedLinearOpBase
28
29
30template<class SC, class LO, class GO, class NO>
36
37
38template<class SC, class LO, class GO, class NO>
40 const int numRowBlocks, const int numColBlocks
41 )
42{
43 assertBlockFillIsActive(false);
45 resetStorage(numRowBlocks,numColBlocks);
47
49template<class SC, class LO, class GO, class NO>
51 const RCP<const ProductVectorSpaceBase<SC> > &new_productRange
52 ,const RCP<const ProductVectorSpaceBase<SC> > &new_productDomain
53 )
54{
55 TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,"beginBlockFill is used but not implemented!");
56}
57
59template<class SC, class LO, class GO, class NO>
61{
62 return blockFillIsActive_;
63}
64
65
66template<class SC, class LO, class GO, class NO>
68 const int i, const int j
69 ) const
70{
71 assertBlockFillIsActive(true);
72 assertBlockRowCol(i,j);
73 return true;
75
77template<class SC, class LO, class GO, class NO>
79 const int i, const int j
80 ,const RCP<LinearOpBase<SC> > &block
81 )
83 setBlockImpl(i, j, block);
84}
85
86
87template<class SC, class LO, class GO, class NO>
89 const int i, const int j
90 ,const RCP<const LinearOpBase<SC> > &block
91 )
92{
93 setBlockImpl(i, j, block);
94}
95
96
97template<class SC, class LO, class GO, class NO>
99{
100
101 using Teuchos::as;
102
103 assertBlockFillIsActive(true);
104
105 // 2009/05/06: rabartl: ToDo: When doing a flexible block fill
106 // (Ops_stack_.size() > 0), we need to assert that all of the block rows and
107 // columns have been filled in. I don't think we do that here.
108
109 // Get the number of block rows and columns
110 if (nonnull(productRange_)) {
111 numRowBlocks_ = productRange_->numBlocks();
112 numColBlocks_ = productDomain_->numBlocks();
113 }
114 else {
115 numRowBlocks_ = rangeBlocks_.size();
116 numColBlocks_ = domainBlocks_.size();
117 // NOTE: Above, whether doing a flexible fill or not, all of the blocks
118 // must be set in order to have a valid filled operator so this
119 // calculation should be correct.
120 }
121
122 // Assert that all of the block rows and columns have at least one entry if
123 // the spaces were not given up front.
124//#ifdef TEUCHOS_DEBUG
125// if (is_null(productRange_)) {
126// for (int i = 0; i < numRowBlocks_; ++i) {
127// TEUCHOS_TEST_FOR_EXCEPTION(
128// !rangeBlocks_[i].get(), std::logic_error
129// ,"PreconditionerOperator<SC>::endBlockFill():"
130// " Error, no linear operator block for the i="<<i<<" block row was added"
131// " and we can not complete the block fill!"
132// );
133// }
134// for(int j = 0; j < numColBlocks_; ++j) {
135// TEUCHOS_TEST_FOR_EXCEPTION(
136// !domainBlocks_[j].get(), std::logic_error
137// ,"PreconditionerOperator<SC>::endBlockFill():"
138// " Error, no linear operator block for the j="
139// <<j<<" block column was added"
140// " and we can not complete the block fill!"
141// );
142// }
143// }
144//#endif
145
146 // Insert the block LOB objects if doing a flexible fill.
147// if (Ops_stack_.size()) {
148// Ops_.resize(numRowBlocks_*numColBlocks_);
149// for ( int k = 0; k < as<int>(Ops_stack_.size()); ++k ) {
150// const BlockEntry<SC> &block_i_j = Ops_stack_[k];
151// Ops_[numRowBlocks_*block_i_j.j + block_i_j.i] = block_i_j.block;
152// }
153// Ops_stack_.resize(0);
154// }
155
156 TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,"endBlockFill is used!");
157
158 // Set the product range and domain spaces if not already set
159// if (is_null(productRange_)) {
160// adjustBlockSpaces();
161// defaultProductRange_ = productVectorSpace<SC>(rangeBlocks_());
162// defaultProductDomain_ = productVectorSpace<SC>(domainBlocks_());
163// productRange_ = defaultProductRange_;
164// productDomain_ = defaultProductDomain_;
165// }
166//
167// rangeBlocks_.resize(0);
168// domainBlocks_.resize(0);
169
170 blockFillIsActive_ = false;
171
172}
173
174
175template<class SC, class LO, class GO, class NO>
177{
178 productRange_ = Teuchos::null;
179 productDomain_ = Teuchos::null;
180 numRowBlocks_ = 0;
181 numColBlocks_ = 0;
182 Ops_.resize(0);
183 Ops_stack_.resize(0);
184 rangeBlocks_.resize(0);
185 domainBlocks_.resize(0);
186 blockFillIsActive_ = false;
187}
188
189
190// Overridden from BlockedLinearOpBase
191
192
193template<class SC, class LO, class GO, class NO>
194Teuchos::RCP<const ProductVectorSpaceBase<SC> >
196{
197 return productRange_;
198}
199
200
201template<class SC, class LO, class GO, class NO>
202Teuchos::RCP<const ProductVectorSpaceBase<SC> >
204{
205 return productDomain_;
206}
207
208
209template<class SC, class LO, class GO, class NO>
211 const int i, const int j
212 ) const
213{
214 assertBlockFillIsActive(false);
215 assertBlockRowCol(i,j);
216 return true;
217}
218
219
220template<class SC, class LO, class GO, class NO>
222 const int i, const int j
223 ) const
224{
225#ifdef TEUCHOS_DEBUG
226 TEUCHOS_TEST_FOR_EXCEPT(!blockExists(i,j));
227#endif
228 assertBlockFillIsActive(false);
229 assertBlockRowCol(i,j);
230 return Ops_[numRowBlocks_*j+i].isConst();
231}
232
233
234template<class SC, class LO, class GO, class NO>
235Teuchos::RCP<LinearOpBase<SC> >
237{
238#ifdef TEUCHOS_DEBUG
239 TEUCHOS_TEST_FOR_EXCEPT(!blockExists(i,j));
240#endif
241 assertBlockFillIsActive(false);
242 assertBlockRowCol(i,j);
243 return Ops_[numRowBlocks_*j+i].getNonconstObj();
244}
245
246
247template<class SC, class LO, class GO, class NO>
248Teuchos::RCP<const LinearOpBase<SC> >
250{
251#ifdef TEUCHOS_DEBUG
252 TEUCHOS_TEST_FOR_EXCEPT(!blockExists(i,j));
253#endif
254 assertBlockFillIsActive(false);
255 assertBlockRowCol(i,j);
256 return Ops_[numRowBlocks_*j+i];
257}
258
259
260// Overridden from LinearOpBase
261
262
263template<class SC, class LO, class GO, class NO>
264Teuchos::RCP< const VectorSpaceBase<SC> >
265PreconditionerOperator<SC, LO, GO, NO>::range() const
266{
267 return productRange_;
268}
269
270
271template<class SC, class LO, class GO, class NO>
272Teuchos::RCP< const VectorSpaceBase<SC> >
273PreconditionerOperator<SC, LO, GO, NO>::domain() const
274{
275 return productDomain_;
276}
277
278
279template<class SC, class LO, class GO, class NO>
280Teuchos::RCP<const LinearOpBase<SC> >
281PreconditionerOperator<SC, LO, GO, NO>::clone() const
282{
283 return Teuchos::null; // ToDo: Implement this when needed!
284}
285
286
287// Overridden from Teuchos::Describable
288
289
290template<class SC, class LO, class GO, class NO>
291std::string PreconditionerOperator<SC, LO, GO, NO>::description() const
292{
293 assertBlockFillIsActive(false);
294 std::ostringstream oss;
295 oss
296 << Teuchos::Describable::description() << "{"
297 << "numRowBlocks="<<numRowBlocks_
298 << ",numColBlocks="<<numColBlocks_
299 << "}";
300 return oss.str();
301}
302
303
304template<class SC, class LO, class GO, class NO>
305void PreconditionerOperator<SC, LO, GO, NO>::describe(
306 Teuchos::FancyOStream &out_arg
307 ,const Teuchos::EVerbosityLevel verbLevel
308 ) const
309{
310 using Teuchos::rcpFromRef;
311 using Teuchos::FancyOStream;
312 using Teuchos::OSTab;
313 assertBlockFillIsActive(false);
314 RCP<FancyOStream> out = rcpFromRef(out_arg);
315 OSTab tab1(out);
316 switch(verbLevel) {
317 case Teuchos::VERB_DEFAULT:
318 case Teuchos::VERB_LOW:
319 *out << this->description() << std::endl;
320 break;
321 case Teuchos::VERB_MEDIUM:
322 case Teuchos::VERB_HIGH:
323 case Teuchos::VERB_EXTREME:
324 {
325 *out
326 << Teuchos::Describable::description() << "{"
327 << "rangeDim=" << this->range()->dim()
328 << ",domainDim=" << this->domain()->dim()
329 << ",numRowBlocks=" << numRowBlocks_
330 << ",numColBlocks=" << numColBlocks_
331 << "}\n";
332 OSTab tab2(out);
333 *out
334 << "Constituent LinearOpBase objects for M = [ Op[0,0] ..."
335 << " ; ... ; ... Op[numRowBlocks-1,numColBlocks-1] ]:\n";
336 tab2.incrTab();
337 for( int i = 0; i < numRowBlocks_; ++i ) {
338 for( int j = 0; j < numColBlocks_; ++j ) {
339 *out << "Op["<<i<<","<<j<<"] = ";
340 RCP<const LinearOpBase<SC> >
341 block_i_j = getBlock(i,j);
342 if(block_i_j.get())
343 *out << Teuchos::describe(*getBlock(i,j),verbLevel);
344 else
345 *out << "NULL\n";
346 }
347 }
348 break;
349 }
350 default:
351 TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
352 }
353}
354
355
356// protected
357
358
359// Overridden from LinearOpBase
360
361
362template<class SC, class LO, class GO, class NO>
364{
365 bool supported = true;
366 for( int i = 0; i < numRowBlocks_; ++i ) {
367 for( int j = 0; j < numColBlocks_; ++j ) {
368 RCP<const LinearOpBase<SC> >
369 block_i_j = getBlock(i,j);
370 if( block_i_j.get() && !Thyra::opSupported(*block_i_j,M_trans) )
371 supported = false;
372 }
373 }
374 return supported;
375}
376
377// private
378
379
380template<class SC, class LO, class GO, class NO>
381void PreconditionerOperator<SC, LO, GO, NO>::resetStorage(
382 const int numRowBlocks, const int numColBlocks
383 )
384{
385 numRowBlocks_ = numRowBlocks;
386 numColBlocks_ = numColBlocks;
387 Ops_.resize(numRowBlocks_*numColBlocks_);
388 if (is_null(productRange_)) {
389 rangeBlocks_.resize(numRowBlocks);
390 domainBlocks_.resize(numColBlocks);
391 }
392 blockFillIsActive_ = true;
393}
394
395
396template<class SC, class LO, class GO, class NO>
397void PreconditionerOperator<SC, LO, GO, NO>::assertBlockFillIsActive(
398 bool wantedValue
399 ) const
400{
401#ifdef TEUCHOS_DEBUG
402 TEUCHOS_TEST_FOR_EXCEPT(!(blockFillIsActive_==wantedValue));
403#else
404 (void)wantedValue;
405#endif
406}
407
408
409template<class SC, class LO, class GO, class NO>
410void PreconditionerOperator<SC, LO, GO, NO>::assertBlockRowCol(
411 const int i, const int j
412 ) const
413{
414#ifdef TEUCHOS_DEBUG
415 TEUCHOS_TEST_FOR_EXCEPTION(
416 !( 0 <= i ), std::logic_error
417 ,"Error, i="<<i<<" is invalid!"
418 );
419 TEUCHOS_TEST_FOR_EXCEPTION(
420 !( 0 <= j ), std::logic_error
421 ,"Error, j="<<j<<" is invalid!"
422 );
423 // Only validate upper range if the number of row and column blocks is
424 // fixed!
425 if(Ops_.size()) {
426 TEUCHOS_TEST_FOR_EXCEPTION(
427 !( 0 <= i && i < numRowBlocks_ ), std::logic_error
428 ,"Error, i="<<i<<" does not fall in the range [0,"<<numRowBlocks_-1<<"]!"
429 );
430 TEUCHOS_TEST_FOR_EXCEPTION(
431 !( 0 <= j && j < numColBlocks_ ), std::logic_error
432 ,"Error, j="<<j<<" does not fall in the range [0,"<<numColBlocks_-1<<"]!"
433 );
434 }
435#else
436 (void)i;
437 (void)j;
438#endif
439}
440
441
442template<class SC, class LO, class GO, class NO>
443void PreconditionerOperator<SC, LO, GO, NO>::setBlockSpaces(
444 const int i, const int j, const LinearOpBase<SC> &block
445 )
446{
447 using Teuchos::toString;
448 assertBlockFillIsActive(true);
449 assertBlockRowCol(i,j);
450
451 // Validate that if the vector space block is already set that it is
452 // compatible with the block that is being set.
453 if( i < numRowBlocks_ && j < numColBlocks_ ) {
454#ifdef TEUCHOS_DEBUG
455 RCP<const VectorSpaceBase<SC> >
456 rangeBlock = (
457 productRange_.get()
458 ? productRange_->getBlock(i)
459 : rangeBlocks_[i]
460 ),
461 domainBlock = (
462 productDomain_.get()
463 ? productDomain_->getBlock(j)
464 : domainBlocks_[j]
465 );
466// if(rangeBlock.get()) {
467// THYRA_ASSERT_VEC_SPACES_NAMES(
468// "PreconditionerOperator<SC>::setBlockSpaces(i,j,block):\n\n"
469// "Adding block: " + block.description(),
470// *rangeBlock,("(*productRange->getBlock("+toString(i)+"))"),
471// *block.range(),("(*block["+toString(i)+","+toString(j)+"].range())")
472// );
473// }
474// if(domainBlock.get()) {
475// THYRA_ASSERT_VEC_SPACES_NAMES(
476// "PreconditionerOperator<SC>::setBlockSpaces(i,j,block):\n\n"
477// "Adding block: " + block.description(),
478// *domainBlock,("(*productDomain->getBlock("+toString(j)+"))"),
479// *block.domain(),("(*block["+toString(i)+","+toString(j)+"].domain())")
480// );
481// }
482#endif // TEUCHOS_DEBUG
483 }
484
485 // Add spaces missing range and domain space blocks if we are doing a
486 // flexible fill (otherwise these loops will not be executed)
487 for( int k = numRowBlocks_; k <= i; ++k )
488 rangeBlocks_.push_back(Teuchos::null);
489 for( int k = numColBlocks_; k <= j; ++k )
490 domainBlocks_.push_back(Teuchos::null);
491
492 // Set the incoming range and domain blocks if not already set
493 if(!productRange_.get()) {
494 if(!rangeBlocks_[i].get())
495 rangeBlocks_[i] = block.range().assert_not_null();
496 if(!domainBlocks_[j].get()) {
497 domainBlocks_[j] = block.domain().assert_not_null();
498 }
499 }
500
501 // Update the current number of row and columns blocks if doing a flexible
502 // fill.
503 if(!Ops_.size()) {
504 numRowBlocks_ = rangeBlocks_.size();
505 numColBlocks_ = domainBlocks_.size();
506 }
507
508}
509
510
511template<class SC, class LO, class GO, class NO>
512template<class LinearOpType>
513void PreconditionerOperator<SC, LO, GO, NO>::setBlockImpl(
514 const int i, const int j,
515 const RCP<LinearOpType> &block
516 )
517{
518 setBlockSpaces(i, j, *block);
519 if (Ops_.size()) {
520 // We are doing a fill with a fixed number of row and column blocks so we
521 // can just set this.
522 Ops_[numRowBlocks_*j+i] = block;
523 }
524 else {
525 // We are doing a flexible fill so add the block to the stack of blocks or
526 // replace a block that already exists.
527 bool foundBlock = false;
528 for( unsigned int k = 0; k < Ops_stack_.size(); ++k ) {
529 BlockEntry<SC> &block_i_j = Ops_stack_[k];
530 if( block_i_j.i == i && block_i_j.j == j ) {
531 block_i_j.block = block;
532 foundBlock = true;
533 break;
534 }
535 }
536 if(!foundBlock)
537 Ops_stack_.push_back(BlockEntry<SC>(i,j,block));
538 }
539}
540
541
542template<class SC, class LO, class GO, class NO>
543void PreconditionerOperator<SC, LO, GO, NO>::adjustBlockSpaces()
544{
545
546#ifdef TEUCHOS_DEBUG
547 TEUCHOS_ASSERT_INEQUALITY(Ops_.size(), !=, 0);
548#endif
549
550 //
551 // Loop through the rows and columns looking for rows with mixed
552 // single-space range and/or domain spaces on operators and set the single
553 // spaces as the block space if it exists.
554 //
555 // NOTE: Once we get here, we can safely assume that all of the operators
556 // are compatible w.r.t. their spaces so if there are rows and/or columns
557 // with mixed product and single vector spaces that we can just pick the
558 // single vector space for the whole row and/or column.
559 //
560
561 // Adjust blocks in the range space
562 for (int i = 0; i < numRowBlocks_; ++i) {
563 for (int j = 0; j < numColBlocks_; ++j) {
564 const RCP<const LinearOpBase<SC> >
565 op_i_j = Ops_[numRowBlocks_*j+i];
566 if (is_null(op_i_j))
567 continue;
568 const RCP<const VectorSpaceBase<SC> > range_i_j = op_i_j->range();
569 if (is_null(productVectorSpaceBase<SC>(range_i_j, false))) {
570 rangeBlocks_[i] = range_i_j;
571 break;
572 }
573 }
574 }
575
576 // Adjust blocks in the domain space
577 for (int j = 0; j < numColBlocks_; ++j) {
578 for (int i = 0; i < numRowBlocks_; ++i) {
579 const RCP<const LinearOpBase<SC> >
580 op_i_j = Ops_[numRowBlocks_*j+i];
581 if (is_null(op_i_j))
582 continue;
583 const RCP<const VectorSpaceBase<SC> >
584 domain_i_j = op_i_j->domain();
585 if (is_null(productVectorSpaceBase<SC>(domain_i_j, false))) {
586 domainBlocks_[j] = domain_i_j;
587 break;
588 }
589 }
590 }
591
592}
593
594};
595
596
597#endif
virtual void setBlock(const int i, const int j, const Teuchos::RCP< const Thyra::LinearOpBase< SC > > &block)
Definition PreconditionerOperator_def.hpp:88
bool blockIsConst(const int i, const int j) const
Definition PreconditionerOperator_def.hpp:221
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< SC > > productDomain() const
Definition PreconditionerOperator_def.hpp:203
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< SC > > productRange() const
Definition PreconditionerOperator_def.hpp:195
virtual bool blockFillIsActive() const
Definition PreconditionerOperator_def.hpp:60
virtual void uninitialize()
Definition PreconditionerOperator_def.hpp:176
virtual void beginBlockFill()
Definition PreconditionerOperator_def.hpp:31
virtual void endBlockFill()
Definition PreconditionerOperator_def.hpp:98
Teuchos::RCP< const Thyra::LinearOpBase< SC > > getBlock(const int i, const int j) const
Definition PreconditionerOperator_def.hpp:249
bool opSupportedImpl(Thyra::EOpTransp M_trans) const
Returns true only if all constituent operators support M_trans.
Definition PreconditionerOperator_def.hpp:363
virtual void setNonconstBlock(const int i, const int j, const Teuchos::RCP< Thyra::LinearOpBase< SC > > &block)
Definition PreconditionerOperator_def.hpp:78
virtual bool acceptsBlock(const int i, const int j) const
Definition PreconditionerOperator_def.hpp:67
bool blockExists(const int i, const int j) const
Definition PreconditionerOperator_def.hpp:210
Teuchos::RCP< Thyra::LinearOpBase< SC > > getNonconstBlock(const int i, const int j)
Definition PreconditionerOperator_def.hpp:236
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement.cpp:5