Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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;
206  RCP<LinearOpBase<Scalar> > create_DgDp_op(int j, int l) const;
212  void evalModel(
215  ) const;
216 
218 
219 protected:
220 
223 
232  void initializeDefaultBase();
233 
238  void resetDefaultBase();
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
RCP< const T > getConst() const
int Ng() const
Return the number of axillary response functions g(j)(...) supported (Ng &gt;= 0).
Pure abstract base interface for evaluating a stateless &quot;model&quot; that can be mapped into a number of d...
RCP< LinearOpWithSolveBase< Scalar > > create_W() const
Default base class for concrete model evaluators.
bool is_null(const boost::shared_ptr< T > &p)
RCP< LinearOpBase< Scalar > > create_DfDp_op(int l) const
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.
void evalModel(const ModelEvaluatorBase::InArgs< Scalar > &inArgs, const ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Simple aggregate class that stores a derivative object as a general linear operator or as a multi-vec...
Abstract interface for objects that represent a space for vectors.
bool supports(EOutArgsMembers arg) const
Determine if an input argument is supported or not.
Derivative< Scalar > get_DgDp(int j, int l) const
Precondition: supports(OUT_ARG_DgDp,j,l)==true.
void initializeDefaultBase()
Function called by subclasses to fully initialize this object on any important change.
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
int Np() const
Return the number of parameter subvectors p(l) supported (Np &gt;= 0).
RCP< LinearOpBase< Scalar > > create_DgDx_op(int j) const
Ptr< T > ptr() const
Base class for all linear operators.
RCP< LinearOpBase< Scalar > > create_DgDx_dot_op(int j) const
Base subclass for ModelEvaluator that defines some basic types.
void push_back(const value_type &x)
RCP< LinearOpWithSolveBase< Scalar > > get_W() const
Precondition: supports(OUT_ARG_W)==true.
void resetDefaultBase()
Sets the the DefaultBase to an uninitialized state, forcing lazy initialization when needed...
size_type size() const
Derivative< Scalar > get_DgDx_dot(int j) const
Precondition: supports(OUT_ARG_DgDx_dot,j)==true.
Determines the forms of a general derivative that are supported.
ModelEvaluatorBase::OutArgs< Scalar > createOutArgs() const
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
Derivative< Scalar > get_DgDx(int j) const
Precondition: supports(OUT_ARG_DgDx,j)==true.
RCP< LinearOpBase< Scalar > > create_DgDp_op(int j, int l) const
Concrete aggregate class for all input arguments computable by a ModelEvaluator subclass object...