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