Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_ModelEvaluatorDefaultBase.hpp
1// @HEADER
2// *****************************************************************************
3// Thyra: Interfaces and Support for Abstract Numerical Algorithms
4//
5// Copyright 2004 NTESS and the Thyra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
11#define THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
12
13#include "Thyra_VectorBase.hpp"
14
15#include "Thyra_ModelEvaluator.hpp"
16#include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
17
18
19#ifdef HAVE_THYRA_ME_POLYNOMIAL
20
21
22// Define the polynomial traits class specializtaion
23// Teuchos::PolynomialTraits<VectorBase > before there is any chance of an
24// instantiation requiring the definition of this class. The Intel C++ 9.1
25// compiler is having trouble compiling Thyra_EpetraModelEvaluator.cpp because
26// Thyra_ModelEvaluatorBase_decl.hpp is only including
27// "Teuchos_Polynomial.hpp" which does not contain the needed specialization.
28// By including it here, all client code is likely to compile just fine. I am
29// going through all of the in order to avoid having to put
30// Thyra_PolynomialVectorTraits.hpp in the interfaces directory. The problem
31// with putting Thyra_PolynomialVectorTraits.hpp the interfaces directory is
32// that it contains calls to code in the support directory and creates an
33// unacceptable circular dependency that will cause problems once we move to
34// subpackages in the CMake build system.
35#include "Thyra_PolynomialVectorTraits.hpp"
36
37
38#endif // HAVE_THYRA_ME_POLYNOMIAL
39
40
41namespace Thyra {
42
43
44//
45// Undocumentated (from the user's perspective) types that are used to
46// implement ModelEvaluatorDefaultBase. These types are defined outside of
47// the templated class since they do nt depend on the scalar type.
48//
49
50
51namespace ModelEvaluatorDefaultBaseTypes {
52
53
54// Type used to determine if the ModelEvaluatorDefaultBase implementation will
55// provide a LinearOpBase wrapper for derivative object given in
56// MultiVectorBase form.
57class DefaultDerivLinearOpSupport {
58public:
59 DefaultDerivLinearOpSupport()
60 :provideDefaultLinearOp_(false),
61 mvImplOrientation_(ModelEvaluatorBase::DERIV_MV_BY_COL)
62 {}
63 DefaultDerivLinearOpSupport(
65 )
66 :provideDefaultLinearOp_(true),
67 mvImplOrientation_(mvImplOrientation_in)
68 {}
69 bool provideDefaultLinearOp() const
70 { return provideDefaultLinearOp_; }
72 { return mvImplOrientation_; }
73private:
74 bool provideDefaultLinearOp_;
76};
77
78
79// Type used to determine if the ModelEvaluatorDefaultBase implementation will
80// provide an explicit transpose copy of a derivative object given in
81// MultiVectorBase form.
82class DefaultDerivMvAdjointSupport {
83public:
84 DefaultDerivMvAdjointSupport()
85 :provideDefaultAdjoint_(false),
86 mvAdjointCopyOrientation_(ModelEvaluatorBase::DERIV_MV_BY_COL)
87 {}
88 DefaultDerivMvAdjointSupport(
89 const ModelEvaluatorBase::EDerivativeMultiVectorOrientation mvAdjointCopyOrientation_in
90 )
91 :provideDefaultAdjoint_(true),
92 mvAdjointCopyOrientation_(mvAdjointCopyOrientation_in)
93 {}
94 bool provideDefaultAdjoint() const
95 { return provideDefaultAdjoint_; }
96 ModelEvaluatorBase::EDerivativeMultiVectorOrientation mvAdjointCopyOrientation() const
97 { return mvAdjointCopyOrientation_; }
98private:
99 bool provideDefaultAdjoint_;
101};
102
103
104// Type used to remember a pair of transposed multi-vectors to implement a
105// adjoint copy.
106template<class Scalar>
107struct MultiVectorAdjointPair {
108 MultiVectorAdjointPair()
109 {}
110 MultiVectorAdjointPair(
111 const RCP<MultiVectorBase<Scalar> > &in_mvOuter,
112 const RCP<const MultiVectorBase<Scalar> > &in_mvImplAdjoint
113 )
114 : mvOuter(in_mvOuter),
115 mvImplAdjoint(in_mvImplAdjoint)
116 {}
117 RCP<MultiVectorBase<Scalar> > mvOuter;
118 RCP<const MultiVectorBase<Scalar> > mvImplAdjoint;
119private:
120};
121
122
123
124
125} // namespace ModelEvaluatorDefaultBaseTypes
126
127
155template<class Scalar>
156class ModelEvaluatorDefaultBase : virtual public ModelEvaluator<Scalar>
157{
158public:
159
162
164 int Np() const;
166 int Ng() const;
183 ) const;
188
189#ifdef Thyra_BUILD_HESSIAN_SUPPORT
191 virtual RCP<LinearOpBase<Scalar> > create_hess_f_xx() const;
193 virtual RCP<LinearOpBase<Scalar> > create_hess_f_xp(int l) const;
195 virtual RCP<LinearOpBase<Scalar> > create_hess_f_pp( int l1, int l2 ) const;
197 virtual RCP<LinearOpBase<Scalar> > create_hess_g_xx(int j) const;
199 virtual RCP<LinearOpBase<Scalar> > create_hess_g_xp( int j, int l ) const;
201 virtual RCP<LinearOpBase<Scalar> > create_hess_g_pp( int j, int l1, int l2 ) const;
202#endif // ifdef Thyra_BUILD_HESSIAN_SUPPORT
203
205
206protected:
207
210
220
226
228
229private:
230
233
235 virtual RCP<LinearOpBase<Scalar> > create_DfDp_op_impl(int l) const;
236
238 virtual RCP<LinearOpBase<Scalar> > create_DgDx_dot_op_impl(int j) const;
239
241 virtual RCP<LinearOpBase<Scalar> > create_DgDx_op_impl(int j) const;
242
244 virtual RCP<LinearOpBase<Scalar> > create_DgDp_op_impl(int j, int l) const;
245
247
250
252 virtual ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const = 0;
253
255 virtual void evalModelImpl(
258 ) const = 0;
259
261
262protected:
263
266
267private:
268
269 // //////////////////////////////
270 // Private tpyes
271
272 typedef ModelEvaluatorDefaultBaseTypes::DefaultDerivLinearOpSupport
273 DefaultDerivLinearOpSupport;
274
275 typedef ModelEvaluatorDefaultBaseTypes::DefaultDerivMvAdjointSupport
276 DefaultDerivMvAdjointSupport;
277
278 typedef ModelEvaluatorDefaultBaseTypes::MultiVectorAdjointPair<Scalar>
279 MultiVectorAdjointPair;
280
281 // //////////////////////////////
282 // Private data members
283
284 bool isInitialized_;
285
286 Array<DefaultDerivLinearOpSupport> DfDp_default_op_support_;
287
288 Array<DefaultDerivLinearOpSupport> DgDx_dot_default_op_support_;
289
290 Array<DefaultDerivLinearOpSupport> DgDx_default_op_support_;
291
292 Array<Array<DefaultDerivLinearOpSupport> > DgDp_default_op_support_;
293 Array<Array<DefaultDerivMvAdjointSupport> > DgDp_default_mv_support_;
294
295 bool default_W_support_;
296
297 ModelEvaluatorBase::OutArgs<Scalar> prototypeOutArgs_;
298
299 // //////////////////////////////
300 // Private member functions
301
302 void lazyInitializeDefaultBase() const;
303
304 void assert_l(const int l) const;
305
306 void assert_j(const int j) const;
307
308 // //////////////////////////////
309 // Private static functions
310
311 static DefaultDerivLinearOpSupport
312 determineDefaultDerivLinearOpSupport(
313 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl
314 );
315
317 createDefaultLinearOp(
318 const DefaultDerivLinearOpSupport &defaultLinearOpSupport,
319 const RCP<const VectorSpaceBase<Scalar> > &fnc_space,
320 const RCP<const VectorSpaceBase<Scalar> > &var_space
321 );
322
324 updateDefaultLinearOpSupport(
325 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
326 const DefaultDerivLinearOpSupport &defaultLinearOpSupport
327 );
328
330 getOutArgImplForDefaultLinearOpSupport(
332 const DefaultDerivLinearOpSupport &defaultLinearOpSupport
333 );
334
335 static DefaultDerivMvAdjointSupport
336 determineDefaultDerivMvAdjointSupport(
337 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
338 const VectorSpaceBase<Scalar> &fnc_space,
339 const VectorSpaceBase<Scalar> &var_space
340 );
341
343 updateDefaultDerivMvAdjointSupport(
344 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
345 const DefaultDerivMvAdjointSupport &defaultMvAdjointSupport
346 );
347
348};
349
350
351} // namespace Thyra
352
353
354//
355// Implementations
356//
357
358
359#include "Thyra_ModelEvaluatorHelpers.hpp"
360#include "Thyra_DefaultScaledAdjointLinearOp.hpp"
361#include "Thyra_DetachedMultiVectorView.hpp"
362#include "Teuchos_Assert.hpp"
363
364
365namespace Thyra {
366
367
368// Overridden from ModelEvaluator
369
370
371template<class Scalar>
373{
374 lazyInitializeDefaultBase();
375 return prototypeOutArgs_.Np();
376}
377
378
379template<class Scalar>
381{
382 lazyInitializeDefaultBase();
383 return prototypeOutArgs_.Ng();
384}
385
386
387template<class Scalar>
390{
391 lazyInitializeDefaultBase();
392 if (default_W_support_)
393 return this->get_W_factory()->createOp();
394 return Teuchos::null;
395}
396
397
398template<class Scalar>
401{
402 lazyInitializeDefaultBase();
403#ifdef TEUCHOS_DEBUG
404 assert_l(l);
405#endif
406 const DefaultDerivLinearOpSupport
407 defaultLinearOpSupport = DfDp_default_op_support_[l];
408 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
409 return createDefaultLinearOp(
410 defaultLinearOpSupport,
411 this->get_f_space(),
412 this->get_p_space(l)
413 );
414 }
415 return this->create_DfDp_op_impl(l);
416}
417
418
419template<class Scalar>
422{
423 lazyInitializeDefaultBase();
424#ifdef TEUCHOS_DEBUG
425 assert_j(j);
426#endif
427 const DefaultDerivLinearOpSupport
428 defaultLinearOpSupport = DgDx_dot_default_op_support_[j];
429 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
430 return createDefaultLinearOp(
431 defaultLinearOpSupport,
432 this->get_g_space(j),
433 this->get_x_space()
434 );
435 }
436 return this->create_DgDx_dot_op_impl(j);
437}
438
439
440template<class Scalar>
443{
444 lazyInitializeDefaultBase();
445#ifdef TEUCHOS_DEBUG
446 assert_j(j);
447#endif
448 const DefaultDerivLinearOpSupport
449 defaultLinearOpSupport = DgDx_default_op_support_[j];
450 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
451 return createDefaultLinearOp(
452 defaultLinearOpSupport,
453 this->get_g_space(j),
454 this->get_x_space()
455 );
456 }
457 return this->create_DgDx_op_impl(j);
458}
459
460
461template<class Scalar>
464{
465 lazyInitializeDefaultBase();
466#ifdef TEUCHOS_DEBUG
467 assert_j(j);
468 assert_l(l);
469#endif
470 const DefaultDerivLinearOpSupport
471 defaultLinearOpSupport = DgDp_default_op_support_[j][l];
472 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
473 return createDefaultLinearOp(
474 defaultLinearOpSupport,
475 this->get_g_space(j),
476 this->get_p_space(l)
477 );
478 }
479 return this->create_DgDp_op_impl(j,l);
480}
481
482
483template<class Scalar>
486{
487 lazyInitializeDefaultBase();
488 return prototypeOutArgs_;
489}
490
491
492template<class Scalar>
496 ) const
497{
498
499 using Teuchos::outArg;
500 typedef ModelEvaluatorBase MEB;
501
502 lazyInitializeDefaultBase();
503
504 const int l_Np = outArgs.Np();
505 const int l_Ng = outArgs.Ng();
506
507 //
508 // A) Assert that the inArgs and outArgs object match this class!
509 //
510
511#ifdef TEUCHOS_DEBUG
512 assertInArgsEvalObjects(*this,inArgs);
513 assertOutArgsEvalObjects(*this,outArgs,&inArgs);
514#endif
515
516 //
517 // B) Setup the OutArgs object for the underlying implementation's
518 // evalModelImpl(...) function
519 //
520
521 MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl();
522 Array<MultiVectorAdjointPair> DgDp_temp_adjoint_copies;
523
524 {
525
526 outArgsImpl.setArgs(outArgs,true);
527
528 // DfDp(l)
529 if (outArgsImpl.supports(MEB::OUT_ARG_f)) {
530 for ( int l = 0; l < l_Np; ++l ) {
531 const DefaultDerivLinearOpSupport defaultLinearOpSupport =
532 DfDp_default_op_support_[l];
533 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
534 outArgsImpl.set_DfDp( l,
535 getOutArgImplForDefaultLinearOpSupport(
536 outArgs.get_DfDp(l), defaultLinearOpSupport
537 )
538 );
539 }
540 else {
541 // DfDp(l) already set by outArgsImpl.setArgs(...)!
542 }
543 }
544 }
545
546 // DgDx_dot(j)
547 for ( int j = 0; j < l_Ng; ++j ) {
548 const DefaultDerivLinearOpSupport defaultLinearOpSupport =
549 DgDx_dot_default_op_support_[j];
550 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
551 outArgsImpl.set_DgDx_dot( j,
552 getOutArgImplForDefaultLinearOpSupport(
553 outArgs.get_DgDx_dot(j), defaultLinearOpSupport
554 )
555 );
556 }
557 else {
558 // DgDx_dot(j) already set by outArgsImpl.setArgs(...)!
559 }
560 }
561
562 // DgDx(j)
563 for ( int j = 0; j < l_Ng; ++j ) {
564 const DefaultDerivLinearOpSupport defaultLinearOpSupport =
565 DgDx_default_op_support_[j];
566 if (defaultLinearOpSupport.provideDefaultLinearOp()) {
567 outArgsImpl.set_DgDx( j,
568 getOutArgImplForDefaultLinearOpSupport(
569 outArgs.get_DgDx(j), defaultLinearOpSupport
570 )
571 );
572 }
573 else {
574 // DgDx(j) already set by outArgsImpl.setArgs(...)!
575 }
576 }
577
578 // DgDp(j,l)
579 for ( int j = 0; j < l_Ng; ++j ) {
580 const Array<DefaultDerivLinearOpSupport> &DgDp_default_op_support_j =
581 DgDp_default_op_support_[j];
582 const Array<DefaultDerivMvAdjointSupport> &DgDp_default_mv_support_j =
583 DgDp_default_mv_support_[j];
584 for ( int l = 0; l < l_Np; ++l ) {
585 const DefaultDerivLinearOpSupport defaultLinearOpSupport =
586 DgDp_default_op_support_j[l];
587 const DefaultDerivMvAdjointSupport defaultMvAdjointSupport =
588 DgDp_default_mv_support_j[l];
589 MEB::Derivative<Scalar> DgDp_j_l;
590 if (!outArgs.supports(MEB::OUT_ARG_DgDp,j,l).none())
591 DgDp_j_l = outArgs.get_DgDp(j,l);
592 if (
593 defaultLinearOpSupport.provideDefaultLinearOp()
594 && !is_null(DgDp_j_l.getLinearOp())
595 )
596 {
597 outArgsImpl.set_DgDp( j, l,
598 getOutArgImplForDefaultLinearOpSupport(
599 DgDp_j_l, defaultLinearOpSupport
600 )
601 );
602 }
603 else if (
604 defaultMvAdjointSupport.provideDefaultAdjoint()
605 && !is_null(DgDp_j_l.getMultiVector())
606 )
607 {
608 const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv =
609 DgDp_j_l.getMultiVector();
610 if (
611 defaultMvAdjointSupport.mvAdjointCopyOrientation()
612 ==
613 DgDp_j_l.getMultiVectorOrientation()
614 )
615 {
616 // The orientation of the multi-vector is different so we need to
617 // create a temporary copy to pass to evalModelImpl(...) and then
618 // copy it back again!
619 const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv_adj =
620 createMembers(DgDp_j_l_mv->domain(), DgDp_j_l_mv->range()->dim());
621 outArgsImpl.set_DgDp( j, l,
622 MEB::Derivative<Scalar>(
623 DgDp_j_l_mv_adj,
624 getOtherDerivativeMultiVectorOrientation(
625 defaultMvAdjointSupport.mvAdjointCopyOrientation()
626 )
627 )
628 );
629 // Remember these multi-vectors so that we can do the transpose copy
630 // back after the evaluation!
631 DgDp_temp_adjoint_copies.push_back(
632 MultiVectorAdjointPair(DgDp_j_l_mv, DgDp_j_l_mv_adj)
633 );
634 }
635 else {
636 // The form of the multi-vector is supported by evalModelImpl(..)
637 // and is already set on the outArgsImpl object.
638 }
639 }
640 else {
641 // DgDp(j,l) already set by outArgsImpl.setArgs(...)!
642 }
643 }
644 }
645
646 // W
647 {
649 if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) {
651 W_factory = this->get_W_factory();
652 // Extract the underlying W_op object (if it exists)
654 uninitializeOp<Scalar>(*W_factory, W.ptr(), outArg(W_op_const));
656 if (!is_null(W_op_const)) {
657 // Here we remove the const. This is perfectly safe since
658 // w.r.t. this class, we put a non-const object in there and we can
659 // expect to change that object after the fact. That is our
660 // prerogative.
662 }
663 else {
664 // The W_op object has not been initialized yet so create it. The
665 // next time through, we should not have to do this!
666 W_op = this->create_W_op();
667 }
668 outArgsImpl.set_W_op(W_op);
669 }
670 }
671 }
672
673 //
674 // C) Evaluate the underlying model implementation!
675 //
676
677 this->evalModelImpl( inArgs, outArgsImpl );
678
679 //
680 // D) Post-process the output arguments
681 //
682
683 // Do explicit transposes for DgDp(j,l) if needed
684 const int numMvAdjointCopies = DgDp_temp_adjoint_copies.size();
685 for ( int adj_copy_i = 0; adj_copy_i < numMvAdjointCopies; ++adj_copy_i ) {
686 const MultiVectorAdjointPair adjPair =
687 DgDp_temp_adjoint_copies[adj_copy_i];
688 doExplicitMultiVectorAdjoint( *adjPair.mvImplAdjoint, &*adjPair.mvOuter );
689 }
690
691 // Update W given W_op and W_factory
692 {
694 if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) {
696 W_factory = this->get_W_factory();
697 W_factory->setOStream(this->getOStream());
698 W_factory->setVerbLevel(this->getVerbLevel());
699 initializeOp<Scalar>(*W_factory, outArgsImpl.get_W_op().getConst(), W.ptr());
700 }
701 }
702
703}
704
705
706// protected
707
708
709// Setup functions called by subclasses
710
711template<class Scalar>
713{
714
715 typedef ModelEvaluatorBase MEB;
716
717 // In case we throw half way thorugh, set to uninitialized
718 isInitialized_ = false;
719 default_W_support_ = false;
720
721 //
722 // A) Get the InArgs and OutArgs from the subclass
723 //
724
725 const MEB::InArgs<Scalar> inArgs = this->createInArgs();
726 const MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl();
727
728 //
729 // B) Validate the subclasses InArgs and OutArgs
730 //
731
732#ifdef TEUCHOS_DEBUG
733 assertInArgsOutArgsSetup( this->description(), inArgs, outArgsImpl );
734#endif // TEUCHOS_DEBUG
735
736 //
737 // C) Set up support for default derivative objects and prototype OutArgs
738 //
739
740 const int l_Ng = outArgsImpl.Ng();
741 const int l_Np = outArgsImpl.Np();
742
743 // Set support for all outputs supported in the underly implementation
744 MEB::OutArgsSetup<Scalar> outArgs;
745 outArgs.setModelEvalDescription(this->description());
746 outArgs.set_Np_Ng(l_Np,l_Ng);
747 outArgs.setSupports(outArgsImpl);
748
749 // DfDp
750 DfDp_default_op_support_.clear();
751 if (outArgs.supports(MEB::OUT_ARG_f)) {
752 for ( int l = 0; l < l_Np; ++l ) {
753 const MEB::DerivativeSupport DfDp_l_impl_support =
754 outArgsImpl.supports(MEB::OUT_ARG_DfDp,l);
755 const DefaultDerivLinearOpSupport DfDp_l_op_support =
756 determineDefaultDerivLinearOpSupport(DfDp_l_impl_support);
757 DfDp_default_op_support_.push_back(DfDp_l_op_support);
758 outArgs.setSupports(
759 MEB::OUT_ARG_DfDp, l,
760 updateDefaultLinearOpSupport(
761 DfDp_l_impl_support, DfDp_l_op_support
762 )
763 );
764 }
765 }
766
767 // DgDx_dot
768 DgDx_dot_default_op_support_.clear();
769 for ( int j = 0; j < l_Ng; ++j ) {
770 const MEB::DerivativeSupport DgDx_dot_j_impl_support =
771 outArgsImpl.supports(MEB::OUT_ARG_DgDx_dot,j);
772 const DefaultDerivLinearOpSupport DgDx_dot_j_op_support =
773 determineDefaultDerivLinearOpSupport(DgDx_dot_j_impl_support);
774 DgDx_dot_default_op_support_.push_back(DgDx_dot_j_op_support);
775 outArgs.setSupports(
776 MEB::OUT_ARG_DgDx_dot, j,
777 updateDefaultLinearOpSupport(
778 DgDx_dot_j_impl_support, DgDx_dot_j_op_support
779 )
780 );
781 }
782
783 // DgDx
784 DgDx_default_op_support_.clear();
785 for ( int j = 0; j < l_Ng; ++j ) {
786 const MEB::DerivativeSupport DgDx_j_impl_support =
787 outArgsImpl.supports(MEB::OUT_ARG_DgDx,j);
788 const DefaultDerivLinearOpSupport DgDx_j_op_support =
789 determineDefaultDerivLinearOpSupport(DgDx_j_impl_support);
790 DgDx_default_op_support_.push_back(DgDx_j_op_support);
791 outArgs.setSupports(
792 MEB::OUT_ARG_DgDx, j,
793 updateDefaultLinearOpSupport(
794 DgDx_j_impl_support, DgDx_j_op_support
795 )
796 );
797 }
798
799 // DgDp
800 DgDp_default_op_support_.clear();
801 DgDp_default_mv_support_.clear();
802 for ( int j = 0; j < l_Ng; ++j ) {
803 DgDp_default_op_support_.push_back(Array<DefaultDerivLinearOpSupport>());
804 DgDp_default_mv_support_.push_back(Array<DefaultDerivMvAdjointSupport>());
805 for ( int l = 0; l < l_Np; ++l ) {
806 const MEB::DerivativeSupport DgDp_j_l_impl_support =
807 outArgsImpl.supports(MEB::OUT_ARG_DgDp,j,l);
808 // LinearOpBase support
809 const DefaultDerivLinearOpSupport DgDp_j_l_op_support =
810 determineDefaultDerivLinearOpSupport(DgDp_j_l_impl_support);
811 DgDp_default_op_support_[j].push_back(DgDp_j_l_op_support);
812 outArgs.setSupports(
813 MEB::OUT_ARG_DgDp, j, l,
814 updateDefaultLinearOpSupport(
815 DgDp_j_l_impl_support, DgDp_j_l_op_support
816 )
817 );
818 // MultiVectorBase
819 const DefaultDerivMvAdjointSupport DgDp_j_l_mv_support =
820 determineDefaultDerivMvAdjointSupport(
821 DgDp_j_l_impl_support, *this->get_g_space(j), *this->get_p_space(l)
822 );
823 DgDp_default_mv_support_[j].push_back(DgDp_j_l_mv_support);
824 outArgs.setSupports(
825 MEB::OUT_ARG_DgDp, j, l,
826 updateDefaultDerivMvAdjointSupport(
827 outArgs.supports(MEB::OUT_ARG_DgDp, j, l),
828 DgDp_j_l_mv_support
829 )
830 );
831 }
832 }
833 // 2007/09/09: rabart: ToDo: Move the above code into a private helper
834 // function!
835
836 // W (given W_op and W_factory)
837 default_W_support_ = false;
838 if ( outArgsImpl.supports(MEB::OUT_ARG_W_op) && !is_null(this->get_W_factory())
839 && !outArgsImpl.supports(MEB::OUT_ARG_W) )
840 {
841 default_W_support_ = true;
842 outArgs.setSupports(MEB::OUT_ARG_W);
843 outArgs.set_W_properties(outArgsImpl.get_W_properties());
844 }
845
846 //
847 // D) All done!
848 //
849
850 prototypeOutArgs_ = outArgs;
851 isInitialized_ = true;
852
853}
854
855template<class Scalar>
857{
858 isInitialized_ = false;
859}
860
861// Private functions with default implementaton to be overridden by subclasses
862
863
864template<class Scalar>
867{
868 typedef ModelEvaluatorBase MEB;
869 MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
871 outArgs.supports(MEB::OUT_ARG_DfDp,l).supports(MEB::DERIV_LINEAR_OP),
872 std::logic_error,
873 "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
874 " supports the LinearOpBase form of DfDp("<<l<<") (as determined from its"
875 " OutArgs object created by createOutArgsImpl())"
876 " but this function create_DfDp_op_impl(...) has not been overridden"
877 " to create such an object!"
878 );
879 return Teuchos::null;
880}
881
882
883template<class Scalar>
884RCP<LinearOpBase<Scalar> >
885ModelEvaluatorDefaultBase<Scalar>::create_DgDx_dot_op_impl(int j) const
886{
887 typedef ModelEvaluatorBase MEB;
888 MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
890 outArgs.supports(MEB::OUT_ARG_DgDx_dot,j).supports(MEB::DERIV_LINEAR_OP),
891 std::logic_error,
892 "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
893 " supports the LinearOpBase form of DgDx_dot("<<j<<") (as determined from"
894 " its OutArgs object created by createOutArgsImpl())"
895 " but this function create_DgDx_dot_op_impl(...) has not been overridden"
896 " to create such an object!"
897 );
898 return Teuchos::null;
899}
900
901
902template<class Scalar>
903RCP<LinearOpBase<Scalar> >
904ModelEvaluatorDefaultBase<Scalar>::create_DgDx_op_impl(int j) const
905{
906 typedef ModelEvaluatorBase MEB;
907 MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
909 outArgs.supports(MEB::OUT_ARG_DgDx,j).supports(MEB::DERIV_LINEAR_OP),
910 std::logic_error,
911 "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
912 " supports the LinearOpBase form of DgDx("<<j<<") (as determined from"
913 " its OutArgs object created by createOutArgsImpl())"
914 " but this function create_DgDx_op_impl(...) has not been overridden"
915 " to create such an object!"
916 );
917 return Teuchos::null;
918}
919
920
921template<class Scalar>
922RCP<LinearOpBase<Scalar> >
923ModelEvaluatorDefaultBase<Scalar>::create_DgDp_op_impl(int j, int l) const
924{
925 typedef ModelEvaluatorBase MEB;
926 MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
928 outArgs.supports(MEB::OUT_ARG_DgDp,j,l).supports(MEB::DERIV_LINEAR_OP),
929 std::logic_error,
930 "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
931 " supports the LinearOpBase form of DgDp("<<j<<","<<l<<")"
932 " (as determined from its OutArgs object created by createOutArgsImpl())"
933 " but this function create_DgDp_op_impl(...) has not been overridden"
934 " to create such an object!"
935 );
936 return Teuchos::null;
937}
938
939
940template<class Scalar>
941RCP<const VectorSpaceBase<Scalar> >
943{
944 return this->get_f_space();
945}
946
947template<class Scalar>
950{
951 return this->get_g_space(j);
952}
953
954#ifdef Thyra_BUILD_HESSIAN_SUPPORT
955
956template<class Scalar>
959{
960 return Teuchos::null;
961}
962
963template<class Scalar>
964RCP<LinearOpBase<Scalar> >
965ModelEvaluatorDefaultBase<Scalar>::create_hess_f_xp(int l) const
966{
967 return Teuchos::null;
968}
969
970template<class Scalar>
971RCP<LinearOpBase<Scalar> >
972ModelEvaluatorDefaultBase<Scalar>::create_hess_f_pp( int l1, int l2 ) const
973{
974 return Teuchos::null;
975}
976
977template<class Scalar>
978RCP<LinearOpBase<Scalar> >
979ModelEvaluatorDefaultBase<Scalar>::create_hess_g_xx(int j) const
980{
981 return Teuchos::null;
982}
983
984template<class Scalar>
985RCP<LinearOpBase<Scalar> >
986ModelEvaluatorDefaultBase<Scalar>::create_hess_g_xp( int j, int l ) const
987{
988 return Teuchos::null;
989}
990
991template<class Scalar>
992RCP<LinearOpBase<Scalar> >
993ModelEvaluatorDefaultBase<Scalar>::create_hess_g_pp( int j, int l1, int l2 ) const
994{
995 return Teuchos::null;
996}
997
998#endif // ifdef Thyra_BUILD_HESSIAN_SUPPORT
999
1000// protected
1001
1002
1003template<class Scalar>
1005 :isInitialized_(false), default_W_support_(false)
1006{}
1007
1008
1009// private
1010
1011
1012template<class Scalar>
1014{
1015 if (!isInitialized_)
1016 const_cast<ModelEvaluatorDefaultBase<Scalar>*>(this)->initializeDefaultBase();
1017}
1018
1019
1020template<class Scalar>
1021void ModelEvaluatorDefaultBase<Scalar>::assert_l(const int l) const
1022{
1024}
1025
1026
1027template<class Scalar>
1028void ModelEvaluatorDefaultBase<Scalar>::assert_j(const int j) const
1029{
1031}
1032
1033
1034// Private static functions
1035
1036
1037template<class Scalar>
1038ModelEvaluatorDefaultBaseTypes::DefaultDerivLinearOpSupport
1039ModelEvaluatorDefaultBase<Scalar>::determineDefaultDerivLinearOpSupport(
1040 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl
1041 )
1042{
1043 typedef ModelEvaluatorBase MEB;
1044 if (
1045 (
1046 derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1047 ||
1048 derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW)
1049 )
1050 &&
1051 !derivSupportImpl.supports(MEB::DERIV_LINEAR_OP)
1052 )
1053 {
1054 return DefaultDerivLinearOpSupport(
1055 derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1056 ? MEB::DERIV_MV_BY_COL
1057 : MEB::DERIV_TRANS_MV_BY_ROW
1058 );
1059 }
1060 return DefaultDerivLinearOpSupport();
1061}
1062
1063
1064template<class Scalar>
1065RCP<LinearOpBase<Scalar> >
1066ModelEvaluatorDefaultBase<Scalar>::createDefaultLinearOp(
1067 const DefaultDerivLinearOpSupport &defaultLinearOpSupport,
1068 const RCP<const VectorSpaceBase<Scalar> > &fnc_space,
1069 const RCP<const VectorSpaceBase<Scalar> > &var_space
1070 )
1071{
1072 using Teuchos::rcp_implicit_cast;
1073 typedef LinearOpBase<Scalar> LOB;
1074 typedef ModelEvaluatorBase MEB;
1075 switch(defaultLinearOpSupport.mvImplOrientation()) {
1076 case MEB::DERIV_MV_BY_COL:
1077 // The MultiVector will do just fine as the LinearOpBase
1078 return createMembers(fnc_space, var_space->dim());
1079 case MEB::DERIV_TRANS_MV_BY_ROW:
1080 // We will have to implicitly transpose the underlying MultiVector
1081 return nonconstAdjoint<Scalar>(
1082 rcp_implicit_cast<LOB>(createMembers(var_space, fnc_space->dim()))
1083 );
1084#ifdef TEUCHOS_DEBUG
1085 default:
1087#endif
1088 }
1089 return Teuchos::null; // Will never be called!
1090}
1091
1092
1093template<class Scalar>
1094ModelEvaluatorBase::DerivativeSupport
1095ModelEvaluatorDefaultBase<Scalar>::updateDefaultLinearOpSupport(
1096 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1097 const DefaultDerivLinearOpSupport &defaultLinearOpSupport
1098 )
1099{
1100 typedef ModelEvaluatorBase MEB;
1101 MEB::DerivativeSupport derivSupport = derivSupportImpl;
1102 if (defaultLinearOpSupport.provideDefaultLinearOp())
1103 derivSupport.plus(MEB::DERIV_LINEAR_OP);
1104 return derivSupport;
1105}
1106
1107
1108template<class Scalar>
1109ModelEvaluatorBase::Derivative<Scalar>
1110ModelEvaluatorDefaultBase<Scalar>::getOutArgImplForDefaultLinearOpSupport(
1111 const ModelEvaluatorBase::Derivative<Scalar> &deriv,
1112 const DefaultDerivLinearOpSupport &defaultLinearOpSupport
1113 )
1114{
1115
1116 using Teuchos::rcp_dynamic_cast;
1117 typedef ModelEvaluatorBase MEB;
1118 typedef MultiVectorBase<Scalar> MVB;
1119 typedef ScaledAdjointLinearOpBase<Scalar> SALOB;
1120
1121 // If the derivative is not a LinearOpBase then it it either empty or is a
1122 // MultiVectorBase object, and in either case we just return it since the
1123 // underlying evalModelImpl(...) functions should be able to handle it!
1124 if (is_null(deriv.getLinearOp()))
1125 return deriv;
1126
1127 // The derivative is LinearOpBase so get out the underlying MultiVectorBase
1128 // object and return its derivative multi-vector form.
1129 switch(defaultLinearOpSupport.mvImplOrientation()) {
1130 case MEB::DERIV_MV_BY_COL: {
1131 return MEB::Derivative<Scalar>(
1132 rcp_dynamic_cast<MVB>(deriv.getLinearOp(),true),
1133 MEB::DERIV_MV_BY_COL
1134 );
1135 }
1136 case MEB::DERIV_TRANS_MV_BY_ROW: {
1137 return MEB::Derivative<Scalar>(
1138 rcp_dynamic_cast<MVB>(
1139 rcp_dynamic_cast<SALOB>(deriv.getLinearOp(),true)->getNonconstOrigOp()
1140 ),
1141 MEB::DERIV_TRANS_MV_BY_ROW
1142 );
1143 }
1144#ifdef TEUCHOS_DEBUG
1145 default:
1147#endif
1148 }
1149
1150 return ModelEvaluatorBase::Derivative<Scalar>(); // Should never get here!
1151
1152}
1153
1154
1155template<class Scalar>
1156ModelEvaluatorDefaultBaseTypes::DefaultDerivMvAdjointSupport
1157ModelEvaluatorDefaultBase<Scalar>::determineDefaultDerivMvAdjointSupport(
1158 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1159 const VectorSpaceBase<Scalar> &fnc_space,
1160 const VectorSpaceBase<Scalar> &var_space
1161 )
1162{
1163 typedef ModelEvaluatorBase MEB;
1164 // Here we will support the adjoint copy for of a multi-vector if both
1165 // spaces give rise to in-core vectors.
1166 const bool implSupportsMv =
1167 ( derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1168 || derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW) );
1169 const bool implLacksMvOrientSupport =
1170 ( !derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1171 || !derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW) );
1172 const bool bothSpacesHaveInCoreViews =
1173 ( fnc_space.hasInCoreView() && var_space.hasInCoreView() );
1174 if ( implSupportsMv && implLacksMvOrientSupport && bothSpacesHaveInCoreViews ) {
1175 return DefaultDerivMvAdjointSupport(
1176 derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1177 ? MEB::DERIV_TRANS_MV_BY_ROW
1178 : MEB::DERIV_MV_BY_COL
1179 );
1180 }
1181 // We can't provide an adjoint copy or such a copy is not needed!
1182 return DefaultDerivMvAdjointSupport();
1183}
1184
1185
1186template<class Scalar>
1187ModelEvaluatorBase::DerivativeSupport
1188ModelEvaluatorDefaultBase<Scalar>::updateDefaultDerivMvAdjointSupport(
1189 const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1190 const DefaultDerivMvAdjointSupport &defaultMvAdjointSupport
1191 )
1192{
1193 typedef ModelEvaluatorBase MEB;
1194 MEB::DerivativeSupport derivSupport = derivSupportImpl;
1195 if (defaultMvAdjointSupport.provideDefaultAdjoint())
1196 derivSupport.plus(defaultMvAdjointSupport.mvAdjointCopyOrientation());
1197 return derivSupport;
1198}
1199
1200
1201} // namespace Thyra
1202
1203
1204#endif // THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
size_type size() const
void push_back(const value_type &x)
RCP< const T > getConst() const
Ptr< T > ptr() const
Determines the forms of a general derivative that are supported.
Simple aggregate class that stores a derivative object as a general linear operator or as a multi-vec...
Concrete aggregate class for all input arguments computable by a ModelEvaluator subclass object.
Concrete aggregate class for all output arguments computable by a ModelEvaluator subclass object.
Derivative< Scalar > get_DfDp(int l) const
Precondition: supports(OUT_ARG_DfDp,l)==true.
RCP< LinearOpWithSolveBase< Scalar > > get_W() const
Precondition: supports(OUT_ARG_W)==true.
int Ng() const
Return the number of axillary response functions g(j)(...) supported (Ng >= 0).
Derivative< Scalar > get_DgDp(int j, int l) const
Precondition: supports(OUT_ARG_DgDp,j,l)==true.
Derivative< Scalar > get_DgDx_dot(int j) const
Precondition: supports(OUT_ARG_DgDx_dot,j)==true.
Derivative< Scalar > get_DgDx(int j) const
Precondition: supports(OUT_ARG_DgDx,j)==true.
bool supports(EOutArgsMembers arg) const
Determine if an input argument is supported or not.
int Np() const
Return the number of parameter subvectors p(l) supported (Np >= 0).
Base subclass for ModelEvaluator that defines some basic types.
Default base class for concrete model evaluators.
RCP< LinearOpBase< Scalar > > create_DgDp_op(int j, int l) const
RCP< LinearOpBase< Scalar > > create_DgDx_op(int j) const
virtual RCP< const VectorSpaceBase< Scalar > > get_g_multiplier_space(int j) const
RCP< LinearOpBase< Scalar > > create_DgDx_dot_op(int j) const
RCP< LinearOpWithSolveBase< Scalar > > create_W() const
virtual RCP< const VectorSpaceBase< Scalar > > get_f_multiplier_space() const
void evalModel(const ModelEvaluatorBase::InArgs< Scalar > &inArgs, const ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
ModelEvaluatorBase::OutArgs< Scalar > createOutArgs() const
void resetDefaultBase()
Sets the the DefaultBase to an uninitialized state, forcing lazy initialization when needed.
void initializeDefaultBase()
Function called by subclasses to fully initialize this object on any important change.
RCP< LinearOpBase< Scalar > > create_DfDp_op(int l) const
Pure abstract base interface for evaluating a stateless "model" that can be mapped into a number of d...
Abstract interface for objects that represent a space for vectors.
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
bool is_null(const std::shared_ptr< T > &p)
T_To & dyn_cast(T_From &from)