Thyra  Version of the Day
Thyra_ModelEvaluatorDefaultBase.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Thyra: Interfaces and Support for Abstract Numerical Algorithms
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
43 #define THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
44 
45 #include "Thyra_VectorBase.hpp"
46 
47 #include "Thyra_ModelEvaluator.hpp"
48 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
49 
50 
51 #ifdef HAVE_THYRA_ME_POLYNOMIAL
52 
53 
54 // Define the polynomial traits class specializtaion
55 // Teuchos::PolynomialTraits<VectorBase > before there is any chance of an
56 // instantiation requiring the definition of this class. The Intel C++ 9.1
57 // compiler is having trouble compiling Thyra_EpetraModelEvaluator.cpp because
58 // Thyra_ModelEvaluatorBase_decl.hpp is only including
59 // "Teuchos_Polynomial.hpp" which does not contain the needed specialization.
60 // By including it here, all client code is likely to compile just fine. I am
61 // going through all of the in order to avoid having to put
62 // Thyra_PolynomialVectorTraits.hpp in the interfaces directory. The problem
63 // with putting Thyra_PolynomialVectorTraits.hpp the interfaces directory is
64 // that it contains calls to code in the support directory and creates an
65 // unacceptable circular dependency that will cause problems once we move to
66 // subpackages in the CMake build system.
67 #include "Thyra_PolynomialVectorTraits.hpp"
68 
69 
70 #endif // HAVE_THYRA_ME_POLYNOMIAL
71 
72 
73 namespace Thyra {
74 
75 
76 //
77 // Undocumentated (from the user's perspective) types that are used to
78 // implement ModelEvaluatorDefaultBase. These types are defined outside of
79 // the templated class since they do nt depend on the scalar type.
80 //
81 
82 
83 namespace ModelEvaluatorDefaultBaseTypes {
84 
85 
86 // Type used to determine if the ModelEvaluatorDefaultBase implementation will
87 // provide a LinearOpBase wrapper for derivative object given in
88 // MultiVectorBase form.
89 class DefaultDerivLinearOpSupport {
90 public:
91  DefaultDerivLinearOpSupport()
92  :provideDefaultLinearOp_(false),
93  mvImplOrientation_(ModelEvaluatorBase::DERIV_MV_BY_COL)
94  {}
95  DefaultDerivLinearOpSupport(
97  )
98  :provideDefaultLinearOp_(true),
99  mvImplOrientation_(mvImplOrientation_in)
100  {}
101  bool provideDefaultLinearOp() const
102  { return provideDefaultLinearOp_; }
104  { return mvImplOrientation_; }
105 private:
106  bool provideDefaultLinearOp_;
108 };
109 
110 
111 // Type used to determine if the ModelEvaluatorDefaultBase implementation will
112 // provide an explicit transpose copy of a derivative object given in
113 // MultiVectorBase form.
114 class DefaultDerivMvAdjointSupport {
115 public:
116  DefaultDerivMvAdjointSupport()
117  :provideDefaultAdjoint_(false),
118  mvAdjointCopyOrientation_(ModelEvaluatorBase::DERIV_MV_BY_COL)
119  {}
120  DefaultDerivMvAdjointSupport(
121  const ModelEvaluatorBase::EDerivativeMultiVectorOrientation mvAdjointCopyOrientation_in
122  )
123  :provideDefaultAdjoint_(true),
124  mvAdjointCopyOrientation_(mvAdjointCopyOrientation_in)
125  {}
126  bool provideDefaultAdjoint() const
127  { return provideDefaultAdjoint_; }
128  ModelEvaluatorBase::EDerivativeMultiVectorOrientation mvAdjointCopyOrientation() const
129  { return mvAdjointCopyOrientation_; }
130 private:
131  bool provideDefaultAdjoint_;
133 };
134 
135 
136 // Type used to remember a pair of transposed multi-vectors to implement a
137 // adjoint copy.
138 template<class Scalar>
139 struct MultiVectorAdjointPair {
140  MultiVectorAdjointPair()
141  {}
142  MultiVectorAdjointPair(
143  const RCP<MultiVectorBase<Scalar> > &in_mvOuter,
144  const RCP<const MultiVectorBase<Scalar> > &in_mvImplAdjoint
145  )
146  : mvOuter(in_mvOuter),
147  mvImplAdjoint(in_mvImplAdjoint)
148  {}
149  RCP<MultiVectorBase<Scalar> > mvOuter;
150  RCP<const MultiVectorBase<Scalar> > mvImplAdjoint;
151 private:
152 };
153 
154 
155 
156 
157 } // namespace ModelEvaluatorDefaultBaseTypes
158 
159 
187 template<class Scalar>
188 class ModelEvaluatorDefaultBase : virtual public ModelEvaluator<Scalar>
189 {
190 public:
191 
194 
196  int Np() const;
198  int Ng() const;
212  void evalModel(
215  ) const;
216 
218 
219 protected:
220 
223 
233 
239 
241 
242 private:
243 
246 
248  virtual RCP<LinearOpBase<Scalar> > create_DfDp_op_impl(int l) const;
249 
251  virtual RCP<LinearOpBase<Scalar> > create_DgDx_dot_op_impl(int j) const;
252 
254  virtual RCP<LinearOpBase<Scalar> > create_DgDx_op_impl(int j) const;
255 
257  virtual RCP<LinearOpBase<Scalar> > create_DgDp_op_impl(int j, int l) const;
258 
260 
263 
265  virtual ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const = 0;
266 
268  virtual void evalModelImpl(
271  ) const = 0;
272 
274 
275 protected:
276 
279 
280 private:
281 
282  // //////////////////////////////
283  // Private tpyes
284 
285  typedef ModelEvaluatorDefaultBaseTypes::DefaultDerivLinearOpSupport
286  DefaultDerivLinearOpSupport;
287 
288  typedef ModelEvaluatorDefaultBaseTypes::DefaultDerivMvAdjointSupport
289  DefaultDerivMvAdjointSupport;
290 
291  typedef ModelEvaluatorDefaultBaseTypes::MultiVectorAdjointPair<Scalar>
292  MultiVectorAdjointPair;
293 
294  // //////////////////////////////
295  // Private data members
296 
297  bool isInitialized_;
298 
299  Array<DefaultDerivLinearOpSupport> DfDp_default_op_support_;
300 
301  Array<DefaultDerivLinearOpSupport> DgDx_dot_default_op_support_;
302 
303  Array<DefaultDerivLinearOpSupport> DgDx_default_op_support_;
304 
305  Array<Array<DefaultDerivLinearOpSupport> > DgDp_default_op_support_;
306  Array<Array<DefaultDerivMvAdjointSupport> > DgDp_default_mv_support_;
307 
308  bool default_W_support_;
309 
310  ModelEvaluatorBase::OutArgs<Scalar> prototypeOutArgs_;
311 
312  // //////////////////////////////
313  // Private member functions
314 
315  void lazyInitializeDefaultBase() const;
316 
317  void assert_l(const int l) const;
318 
319  void assert_j(const int j) const;
320 
321  // //////////////////////////////
322  // Private static functions
323 
324  static DefaultDerivLinearOpSupport
325  determineDefaultDerivLinearOpSupport(
326  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl
327  );
328 
329  static RCP<LinearOpBase<Scalar> >
330  createDefaultLinearOp(
331  const DefaultDerivLinearOpSupport &defaultLinearOpSupport,
332  const RCP<const VectorSpaceBase<Scalar> > &fnc_space,
333  const RCP<const VectorSpaceBase<Scalar> > &var_space
334  );
335 
337  updateDefaultLinearOpSupport(
338  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
339  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
340  );
341 
343  getOutArgImplForDefaultLinearOpSupport(
345  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
346  );
347 
348  static DefaultDerivMvAdjointSupport
349  determineDefaultDerivMvAdjointSupport(
350  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
351  const VectorSpaceBase<Scalar> &fnc_space,
352  const VectorSpaceBase<Scalar> &var_space
353  );
354 
356  updateDefaultDerivMvAdjointSupport(
357  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
358  const DefaultDerivMvAdjointSupport &defaultMvAdjointSupport
359  );
360 
361 };
362 
363 
364 } // namespace Thyra
365 
366 
367 //
368 // Implementations
369 //
370 
371 
372 #include "Thyra_ModelEvaluatorHelpers.hpp"
373 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
374 #include "Thyra_DetachedMultiVectorView.hpp"
375 #include "Teuchos_Assert.hpp"
376 
377 
378 namespace Thyra {
379 
380 
381 // Overridden from ModelEvaluator
382 
383 
384 template<class Scalar>
386 {
387  lazyInitializeDefaultBase();
388  return prototypeOutArgs_.Np();
389 }
390 
391 
392 template<class Scalar>
394 {
395  lazyInitializeDefaultBase();
396  return prototypeOutArgs_.Ng();
397 }
398 
399 
400 template<class Scalar>
403 {
404  lazyInitializeDefaultBase();
405  if (default_W_support_)
406  return this->get_W_factory()->createOp();
407  return Teuchos::null;
408 }
409 
410 
411 template<class Scalar>
414 {
415  lazyInitializeDefaultBase();
416 #ifdef TEUCHOS_DEBUG
417  assert_l(l);
418 #endif
419  const DefaultDerivLinearOpSupport
420  defaultLinearOpSupport = DfDp_default_op_support_[l];
421  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
422  return createDefaultLinearOp(
423  defaultLinearOpSupport,
424  this->get_f_space(),
425  this->get_p_space(l)
426  );
427  }
428  return this->create_DfDp_op_impl(l);
429 }
430 
431 
432 template<class Scalar>
435 {
436  lazyInitializeDefaultBase();
437 #ifdef TEUCHOS_DEBUG
438  assert_j(j);
439 #endif
440  const DefaultDerivLinearOpSupport
441  defaultLinearOpSupport = DgDx_dot_default_op_support_[j];
442  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
443  return createDefaultLinearOp(
444  defaultLinearOpSupport,
445  this->get_g_space(j),
446  this->get_x_space()
447  );
448  }
449  return this->create_DgDx_dot_op_impl(j);
450 }
451 
452 
453 template<class Scalar>
456 {
457  lazyInitializeDefaultBase();
458 #ifdef TEUCHOS_DEBUG
459  assert_j(j);
460 #endif
461  const DefaultDerivLinearOpSupport
462  defaultLinearOpSupport = DgDx_default_op_support_[j];
463  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
464  return createDefaultLinearOp(
465  defaultLinearOpSupport,
466  this->get_g_space(j),
467  this->get_x_space()
468  );
469  }
470  return this->create_DgDx_op_impl(j);
471 }
472 
473 
474 template<class Scalar>
477 {
478  lazyInitializeDefaultBase();
479 #ifdef TEUCHOS_DEBUG
480  assert_j(j);
481  assert_l(l);
482 #endif
483  const DefaultDerivLinearOpSupport
484  defaultLinearOpSupport = DgDp_default_op_support_[j][l];
485  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
486  return createDefaultLinearOp(
487  defaultLinearOpSupport,
488  this->get_g_space(j),
489  this->get_p_space(l)
490  );
491  }
492  return this->create_DgDp_op_impl(j,l);
493 }
494 
495 
496 template<class Scalar>
499 {
500  lazyInitializeDefaultBase();
501  return prototypeOutArgs_;
502 }
503 
504 
505 template<class Scalar>
509  ) const
510 {
511 
512  using Teuchos::outArg;
513  typedef ModelEvaluatorBase MEB;
514 
515  lazyInitializeDefaultBase();
516 
517  const int l_Np = outArgs.Np();
518  const int l_Ng = outArgs.Ng();
519 
520  //
521  // A) Assert that the inArgs and outArgs object match this class!
522  //
523 
524 #ifdef TEUCHOS_DEBUG
525  assertInArgsEvalObjects(*this,inArgs);
526  assertOutArgsEvalObjects(*this,outArgs,&inArgs);
527 #endif
528 
529  //
530  // B) Setup the OutArgs object for the underlying implementation's
531  // evalModelImpl(...) function
532  //
533 
534  MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl();
535  Array<MultiVectorAdjointPair> DgDp_temp_adjoint_copies;
536 
537  {
538 
539  outArgsImpl.setArgs(outArgs,true);
540 
541  // DfDp(l)
542  if (outArgsImpl.supports(MEB::OUT_ARG_f)) {
543  for ( int l = 0; l < l_Np; ++l ) {
544  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
545  DfDp_default_op_support_[l];
546  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
547  outArgsImpl.set_DfDp( l,
548  getOutArgImplForDefaultLinearOpSupport(
549  outArgs.get_DfDp(l), defaultLinearOpSupport
550  )
551  );
552  }
553  else {
554  // DfDp(l) already set by outArgsImpl.setArgs(...)!
555  }
556  }
557  }
558 
559  // DgDx_dot(j)
560  for ( int j = 0; j < l_Ng; ++j ) {
561  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
562  DgDx_dot_default_op_support_[j];
563  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
564  outArgsImpl.set_DgDx_dot( j,
565  getOutArgImplForDefaultLinearOpSupport(
566  outArgs.get_DgDx_dot(j), defaultLinearOpSupport
567  )
568  );
569  }
570  else {
571  // DgDx_dot(j) already set by outArgsImpl.setArgs(...)!
572  }
573  }
574 
575  // DgDx(j)
576  for ( int j = 0; j < l_Ng; ++j ) {
577  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
578  DgDx_default_op_support_[j];
579  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
580  outArgsImpl.set_DgDx( j,
581  getOutArgImplForDefaultLinearOpSupport(
582  outArgs.get_DgDx(j), defaultLinearOpSupport
583  )
584  );
585  }
586  else {
587  // DgDx(j) already set by outArgsImpl.setArgs(...)!
588  }
589  }
590 
591  // DgDp(j,l)
592  for ( int j = 0; j < l_Ng; ++j ) {
593  const Array<DefaultDerivLinearOpSupport> &DgDp_default_op_support_j =
594  DgDp_default_op_support_[j];
595  const Array<DefaultDerivMvAdjointSupport> &DgDp_default_mv_support_j =
596  DgDp_default_mv_support_[j];
597  for ( int l = 0; l < l_Np; ++l ) {
598  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
599  DgDp_default_op_support_j[l];
600  const DefaultDerivMvAdjointSupport defaultMvAdjointSupport =
601  DgDp_default_mv_support_j[l];
602  MEB::Derivative<Scalar> DgDp_j_l;
603  if (!outArgs.supports(MEB::OUT_ARG_DgDp,j,l).none())
604  DgDp_j_l = outArgs.get_DgDp(j,l);
605  if (
606  defaultLinearOpSupport.provideDefaultLinearOp()
607  && !is_null(DgDp_j_l.getLinearOp())
608  )
609  {
610  outArgsImpl.set_DgDp( j, l,
611  getOutArgImplForDefaultLinearOpSupport(
612  DgDp_j_l, defaultLinearOpSupport
613  )
614  );
615  }
616  else if (
617  defaultMvAdjointSupport.provideDefaultAdjoint()
618  && !is_null(DgDp_j_l.getMultiVector())
619  )
620  {
621  const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv =
622  DgDp_j_l.getMultiVector();
623  if (
624  defaultMvAdjointSupport.mvAdjointCopyOrientation()
625  ==
626  DgDp_j_l.getMultiVectorOrientation()
627  )
628  {
629  // The orientation of the multi-vector is different so we need to
630  // create a temporary copy to pass to evalModelImpl(...) and then
631  // copy it back again!
632  const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv_adj =
633  createMembers(DgDp_j_l_mv->domain(), DgDp_j_l_mv->range()->dim());
634  outArgsImpl.set_DgDp( j, l,
635  MEB::Derivative<Scalar>(
636  DgDp_j_l_mv_adj,
637  getOtherDerivativeMultiVectorOrientation(
638  defaultMvAdjointSupport.mvAdjointCopyOrientation()
639  )
640  )
641  );
642  // Remember these multi-vectors so that we can do the transpose copy
643  // back after the evaluation!
644  DgDp_temp_adjoint_copies.push_back(
645  MultiVectorAdjointPair(DgDp_j_l_mv, DgDp_j_l_mv_adj)
646  );
647  }
648  else {
649  // The form of the multi-vector is supported by evalModelImpl(..)
650  // and is already set on the outArgsImpl object.
651  }
652  }
653  else {
654  // DgDp(j,l) already set by outArgsImpl.setArgs(...)!
655  }
656  }
657  }
658 
659  // W
660  {
662  if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) {
664  W_factory = this->get_W_factory();
665  // Extract the underlying W_op object (if it exists)
666  RCP<const LinearOpBase<Scalar> > W_op_const;
667  uninitializeOp<Scalar>(*W_factory, W.ptr(), outArg(W_op_const));
669  if (!is_null(W_op_const)) {
670  // Here we remove the const. This is perfectly safe since
671  // w.r.t. this class, we put a non-const object in there and we can
672  // expect to change that object after the fact. That is our
673  // prerogative.
674  W_op = Teuchos::rcp_const_cast<LinearOpBase<Scalar> >(W_op_const);
675  }
676  else {
677  // The W_op object has not been initialized yet so create it. The
678  // next time through, we should not have to do this!
679  W_op = this->create_W_op();
680  }
681  outArgsImpl.set_W_op(W_op);
682  }
683  }
684 
685  }
686 
687  //
688  // C) Evaluate the underlying model implementation!
689  //
690 
691  this->evalModelImpl( inArgs, outArgsImpl );
692 
693  //
694  // D) Post-process the output arguments
695  //
696 
697  // Do explicit transposes for DgDp(j,l) if needed
698  const int numMvAdjointCopies = DgDp_temp_adjoint_copies.size();
699  for ( int adj_copy_i = 0; adj_copy_i < numMvAdjointCopies; ++adj_copy_i ) {
700  const MultiVectorAdjointPair adjPair =
701  DgDp_temp_adjoint_copies[adj_copy_i];
702  doExplicitMultiVectorAdjoint( *adjPair.mvImplAdjoint, &*adjPair.mvOuter );
703  }
704 
705  // Update W given W_op and W_factory
706  {
708  if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) {
710  W_factory = this->get_W_factory();
711  W_factory->setOStream(this->getOStream());
712  W_factory->setVerbLevel(this->getVerbLevel());
713  initializeOp<Scalar>(*W_factory, outArgsImpl.get_W_op().getConst(), W.ptr());
714  }
715  }
716 
717 }
718 
719 
720 // protected
721 
722 
723 // Setup functions called by subclasses
724 
725 template<class Scalar>
727 {
728 
729  typedef ModelEvaluatorBase MEB;
730 
731  // In case we throw half way thorugh, set to uninitialized
732  isInitialized_ = false;
733  default_W_support_ = false;
734 
735  //
736  // A) Get the InArgs and OutArgs from the subclass
737  //
738 
739  const MEB::InArgs<Scalar> inArgs = this->createInArgs();
740  const MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl();
741 
742  //
743  // B) Validate the subclasses InArgs and OutArgs
744  //
745 
746 #ifdef TEUCHOS_DEBUG
747  assertInArgsOutArgsSetup( this->description(), inArgs, outArgsImpl );
748 #endif // TEUCHOS_DEBUG
749 
750  //
751  // C) Set up support for default derivative objects and prototype OutArgs
752  //
753 
754  const int l_Ng = outArgsImpl.Ng();
755  const int l_Np = outArgsImpl.Np();
756 
757  // Set support for all outputs supported in the underly implementation
758  MEB::OutArgsSetup<Scalar> outArgs;
759  outArgs.setModelEvalDescription(this->description());
760  outArgs.set_Np_Ng(l_Np,l_Ng);
761  outArgs.setSupports(outArgsImpl);
762 
763  // DfDp
764  DfDp_default_op_support_.clear();
765  if (outArgs.supports(MEB::OUT_ARG_f)) {
766  for ( int l = 0; l < l_Np; ++l ) {
767  const MEB::DerivativeSupport DfDp_l_impl_support =
768  outArgsImpl.supports(MEB::OUT_ARG_DfDp,l);
769  const DefaultDerivLinearOpSupport DfDp_l_op_support =
770  determineDefaultDerivLinearOpSupport(DfDp_l_impl_support);
771  DfDp_default_op_support_.push_back(DfDp_l_op_support);
772  outArgs.setSupports(
773  MEB::OUT_ARG_DfDp, l,
774  updateDefaultLinearOpSupport(
775  DfDp_l_impl_support, DfDp_l_op_support
776  )
777  );
778  }
779  }
780 
781  // DgDx_dot
782  DgDx_dot_default_op_support_.clear();
783  for ( int j = 0; j < l_Ng; ++j ) {
784  const MEB::DerivativeSupport DgDx_dot_j_impl_support =
785  outArgsImpl.supports(MEB::OUT_ARG_DgDx_dot,j);
786  const DefaultDerivLinearOpSupport DgDx_dot_j_op_support =
787  determineDefaultDerivLinearOpSupport(DgDx_dot_j_impl_support);
788  DgDx_dot_default_op_support_.push_back(DgDx_dot_j_op_support);
789  outArgs.setSupports(
790  MEB::OUT_ARG_DgDx_dot, j,
791  updateDefaultLinearOpSupport(
792  DgDx_dot_j_impl_support, DgDx_dot_j_op_support
793  )
794  );
795  }
796 
797  // DgDx
798  DgDx_default_op_support_.clear();
799  for ( int j = 0; j < l_Ng; ++j ) {
800  const MEB::DerivativeSupport DgDx_j_impl_support =
801  outArgsImpl.supports(MEB::OUT_ARG_DgDx,j);
802  const DefaultDerivLinearOpSupport DgDx_j_op_support =
803  determineDefaultDerivLinearOpSupport(DgDx_j_impl_support);
804  DgDx_default_op_support_.push_back(DgDx_j_op_support);
805  outArgs.setSupports(
806  MEB::OUT_ARG_DgDx, j,
807  updateDefaultLinearOpSupport(
808  DgDx_j_impl_support, DgDx_j_op_support
809  )
810  );
811  }
812 
813  // DgDp
814  DgDp_default_op_support_.clear();
815  DgDp_default_mv_support_.clear();
816  for ( int j = 0; j < l_Ng; ++j ) {
817  DgDp_default_op_support_.push_back(Array<DefaultDerivLinearOpSupport>());
818  DgDp_default_mv_support_.push_back(Array<DefaultDerivMvAdjointSupport>());
819  for ( int l = 0; l < l_Np; ++l ) {
820  const MEB::DerivativeSupport DgDp_j_l_impl_support =
821  outArgsImpl.supports(MEB::OUT_ARG_DgDp,j,l);
822  // LinearOpBase support
823  const DefaultDerivLinearOpSupport DgDp_j_l_op_support =
824  determineDefaultDerivLinearOpSupport(DgDp_j_l_impl_support);
825  DgDp_default_op_support_[j].push_back(DgDp_j_l_op_support);
826  outArgs.setSupports(
827  MEB::OUT_ARG_DgDp, j, l,
828  updateDefaultLinearOpSupport(
829  DgDp_j_l_impl_support, DgDp_j_l_op_support
830  )
831  );
832  // MultiVectorBase
833  const DefaultDerivMvAdjointSupport DgDp_j_l_mv_support =
834  determineDefaultDerivMvAdjointSupport(
835  DgDp_j_l_impl_support, *this->get_g_space(j), *this->get_p_space(l)
836  );
837  DgDp_default_mv_support_[j].push_back(DgDp_j_l_mv_support);
838  outArgs.setSupports(
839  MEB::OUT_ARG_DgDp, j, l,
840  updateDefaultDerivMvAdjointSupport(
841  outArgs.supports(MEB::OUT_ARG_DgDp, j, l),
842  DgDp_j_l_mv_support
843  )
844  );
845  }
846  }
847  // 2007/09/09: rabart: ToDo: Move the above code into a private helper
848  // function!
849 
850  // W (given W_op and W_factory)
851  default_W_support_ = false;
852  if ( outArgsImpl.supports(MEB::OUT_ARG_W_op) && !is_null(this->get_W_factory())
853  && !outArgsImpl.supports(MEB::OUT_ARG_W) )
854  {
855  default_W_support_ = true;
856  outArgs.setSupports(MEB::OUT_ARG_W);
857  outArgs.set_W_properties(outArgsImpl.get_W_properties());
858  }
859 
860  //
861  // D) All done!
862  //
863 
864  prototypeOutArgs_ = outArgs;
865  isInitialized_ = true;
866 
867 }
868 
869 template<class Scalar>
871 {
872  isInitialized_ = false;
873 }
874 
875 // Private functions with default implementaton to be overridden by subclasses
876 
877 
878 template<class Scalar>
881 {
882  typedef ModelEvaluatorBase MEB;
883  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
885  outArgs.supports(MEB::OUT_ARG_DfDp,l).supports(MEB::DERIV_LINEAR_OP),
886  std::logic_error,
887  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
888  " supports the LinearOpBase form of DfDp("<<l<<") (as determined from its"
889  " OutArgs object created by createOutArgsImpl())"
890  " but this function create_DfDp_op_impl(...) has not been overridden"
891  " to create such an object!"
892  );
893  return Teuchos::null;
894 }
895 
896 
897 template<class Scalar>
898 RCP<LinearOpBase<Scalar> >
899 ModelEvaluatorDefaultBase<Scalar>::create_DgDx_dot_op_impl(int j) const
900 {
901  typedef ModelEvaluatorBase MEB;
902  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
904  outArgs.supports(MEB::OUT_ARG_DgDx_dot,j).supports(MEB::DERIV_LINEAR_OP),
905  std::logic_error,
906  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
907  " supports the LinearOpBase form of DgDx_dot("<<j<<") (as determined from"
908  " its OutArgs object created by createOutArgsImpl())"
909  " but this function create_DgDx_dot_op_impl(...) has not been overridden"
910  " to create such an object!"
911  );
912  return Teuchos::null;
913 }
914 
915 
916 template<class Scalar>
917 RCP<LinearOpBase<Scalar> >
918 ModelEvaluatorDefaultBase<Scalar>::create_DgDx_op_impl(int j) const
919 {
920  typedef ModelEvaluatorBase MEB;
921  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
923  outArgs.supports(MEB::OUT_ARG_DgDx,j).supports(MEB::DERIV_LINEAR_OP),
924  std::logic_error,
925  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
926  " supports the LinearOpBase form of DgDx("<<j<<") (as determined from"
927  " its OutArgs object created by createOutArgsImpl())"
928  " but this function create_DgDx_op_impl(...) has not been overridden"
929  " to create such an object!"
930  );
931  return Teuchos::null;
932 }
933 
934 
935 template<class Scalar>
936 RCP<LinearOpBase<Scalar> >
937 ModelEvaluatorDefaultBase<Scalar>::create_DgDp_op_impl(int j, int l) const
938 {
939  typedef ModelEvaluatorBase MEB;
940  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
942  outArgs.supports(MEB::OUT_ARG_DgDp,j,l).supports(MEB::DERIV_LINEAR_OP),
943  std::logic_error,
944  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
945  " supports the LinearOpBase form of DgDp("<<j<<","<<l<<")"
946  " (as determined from its OutArgs object created by createOutArgsImpl())"
947  " but this function create_DgDp_op_impl(...) has not been overridden"
948  " to create such an object!"
949  );
950  return Teuchos::null;
951 }
952 
953 
954 // protected
955 
956 
957 template<class Scalar>
959  :isInitialized_(false), default_W_support_(false)
960 {}
961 
962 
963 // private
964 
965 
966 template<class Scalar>
968 {
969  if (!isInitialized_)
970  const_cast<ModelEvaluatorDefaultBase<Scalar>*>(this)->initializeDefaultBase();
971 }
972 
973 
974 template<class Scalar>
975 void ModelEvaluatorDefaultBase<Scalar>::assert_l(const int l) const
976 {
978 }
979 
980 
981 template<class Scalar>
982 void ModelEvaluatorDefaultBase<Scalar>::assert_j(const int j) const
983 {
985 }
986 
987 
988 // Private static functions
989 
990 
991 template<class Scalar>
992 ModelEvaluatorDefaultBaseTypes::DefaultDerivLinearOpSupport
993 ModelEvaluatorDefaultBase<Scalar>::determineDefaultDerivLinearOpSupport(
994  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl
995  )
996 {
997  typedef ModelEvaluatorBase MEB;
998  if (
999  (
1000  derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1001  ||
1002  derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW)
1003  )
1004  &&
1005  !derivSupportImpl.supports(MEB::DERIV_LINEAR_OP)
1006  )
1007  {
1008  return DefaultDerivLinearOpSupport(
1009  derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1010  ? MEB::DERIV_MV_BY_COL
1011  : MEB::DERIV_TRANS_MV_BY_ROW
1012  );
1013  }
1014  return DefaultDerivLinearOpSupport();
1015 }
1016 
1017 
1018 template<class Scalar>
1019 RCP<LinearOpBase<Scalar> >
1020 ModelEvaluatorDefaultBase<Scalar>::createDefaultLinearOp(
1021  const DefaultDerivLinearOpSupport &defaultLinearOpSupport,
1022  const RCP<const VectorSpaceBase<Scalar> > &fnc_space,
1023  const RCP<const VectorSpaceBase<Scalar> > &var_space
1024  )
1025 {
1026  using Teuchos::rcp_implicit_cast;
1027  typedef LinearOpBase<Scalar> LOB;
1028  typedef ModelEvaluatorBase MEB;
1029  switch(defaultLinearOpSupport.mvImplOrientation()) {
1030  case MEB::DERIV_MV_BY_COL:
1031  // The MultiVector will do just fine as the LinearOpBase
1032  return createMembers(fnc_space, var_space->dim());
1033  case MEB::DERIV_TRANS_MV_BY_ROW:
1034  // We will have to implicitly transpose the underlying MultiVector
1035  return nonconstAdjoint<Scalar>(
1036  rcp_implicit_cast<LOB>(createMembers(var_space, fnc_space->dim()))
1037  );
1038 #ifdef TEUCHOS_DEBUG
1039  default:
1041 #endif
1042  }
1043  return Teuchos::null; // Will never be called!
1044 }
1045 
1046 
1047 template<class Scalar>
1048 ModelEvaluatorBase::DerivativeSupport
1049 ModelEvaluatorDefaultBase<Scalar>::updateDefaultLinearOpSupport(
1050  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1051  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
1052  )
1053 {
1054  typedef ModelEvaluatorBase MEB;
1055  MEB::DerivativeSupport derivSupport = derivSupportImpl;
1056  if (defaultLinearOpSupport.provideDefaultLinearOp())
1057  derivSupport.plus(MEB::DERIV_LINEAR_OP);
1058  return derivSupport;
1059 }
1060 
1061 
1062 template<class Scalar>
1063 ModelEvaluatorBase::Derivative<Scalar>
1064 ModelEvaluatorDefaultBase<Scalar>::getOutArgImplForDefaultLinearOpSupport(
1065  const ModelEvaluatorBase::Derivative<Scalar> &deriv,
1066  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
1067  )
1068 {
1069 
1070  using Teuchos::rcp_dynamic_cast;
1071  typedef ModelEvaluatorBase MEB;
1072  typedef MultiVectorBase<Scalar> MVB;
1073  typedef ScaledAdjointLinearOpBase<Scalar> SALOB;
1074 
1075  // If the derivative is not a LinearOpBase then it it either empty or is a
1076  // MultiVectorBase object, and in either case we just return it since the
1077  // underlying evalModelImpl(...) functions should be able to handle it!
1078  if (is_null(deriv.getLinearOp()))
1079  return deriv;
1080 
1081  // The derivative is LinearOpBase so get out the underlying MultiVectorBase
1082  // object and return its derivative multi-vector form.
1083  switch(defaultLinearOpSupport.mvImplOrientation()) {
1084  case MEB::DERIV_MV_BY_COL: {
1085  return MEB::Derivative<Scalar>(
1086  rcp_dynamic_cast<MVB>(deriv.getLinearOp(),true),
1087  MEB::DERIV_MV_BY_COL
1088  );
1089  }
1090  case MEB::DERIV_TRANS_MV_BY_ROW: {
1091  return MEB::Derivative<Scalar>(
1092  rcp_dynamic_cast<MVB>(
1093  rcp_dynamic_cast<SALOB>(deriv.getLinearOp(),true)->getNonconstOrigOp()
1094  ),
1095  MEB::DERIV_TRANS_MV_BY_ROW
1096  );
1097  }
1098 #ifdef TEUCHOS_DEBUG
1099  default:
1101 #endif
1102  }
1103 
1104  return ModelEvaluatorBase::Derivative<Scalar>(); // Should never get here!
1105 
1106 }
1107 
1108 
1109 template<class Scalar>
1110 ModelEvaluatorDefaultBaseTypes::DefaultDerivMvAdjointSupport
1111 ModelEvaluatorDefaultBase<Scalar>::determineDefaultDerivMvAdjointSupport(
1112  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1113  const VectorSpaceBase<Scalar> &fnc_space,
1114  const VectorSpaceBase<Scalar> &var_space
1115  )
1116 {
1117  typedef ModelEvaluatorBase MEB;
1118  // Here we will support the adjoint copy for of a multi-vector if both
1119  // spaces give rise to in-core vectors.
1120  const bool implSupportsMv =
1121  ( derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1122  || derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW) );
1123  const bool implLacksMvOrientSupport =
1124  ( !derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1125  || !derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW) );
1126  const bool bothSpacesHaveInCoreViews =
1127  ( fnc_space.hasInCoreView() && var_space.hasInCoreView() );
1128  if ( implSupportsMv && implLacksMvOrientSupport && bothSpacesHaveInCoreViews ) {
1129  return DefaultDerivMvAdjointSupport(
1130  derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1131  ? MEB::DERIV_TRANS_MV_BY_ROW
1132  : MEB::DERIV_MV_BY_COL
1133  );
1134  }
1135  // We can't provide an adjoint copy or such a copy is not needed!
1136  return DefaultDerivMvAdjointSupport();
1137 }
1138 
1139 
1140 template<class Scalar>
1141 ModelEvaluatorBase::DerivativeSupport
1142 ModelEvaluatorDefaultBase<Scalar>::updateDefaultDerivMvAdjointSupport(
1143  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1144  const DefaultDerivMvAdjointSupport &defaultMvAdjointSupport
1145  )
1146 {
1147  typedef ModelEvaluatorBase MEB;
1148  MEB::DerivativeSupport derivSupport = derivSupportImpl;
1149  if (defaultMvAdjointSupport.provideDefaultAdjoint())
1150  derivSupport.plus(defaultMvAdjointSupport.mvAdjointCopyOrientation());
1151  return derivSupport;
1152 }
1153 
1154 
1155 } // namespace Thyra
1156 
1157 
1158 #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
RCP< LinearOpBase< Scalar > > create_DgDx_dot_op(int j) const
RCP< LinearOpWithSolveBase< Scalar > > create_W() 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 boost::shared_ptr< T > &p)