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;
221  virtual RCP<LinearOpBase<Scalar> > create_hess_f_xx() const;
223  virtual RCP<LinearOpBase<Scalar> > create_hess_f_xp(int l) const;
225  virtual RCP<LinearOpBase<Scalar> > create_hess_f_pp( int l1, int l2 ) const;
227  virtual RCP<LinearOpBase<Scalar> > create_hess_g_xx(int j) const;
229  virtual RCP<LinearOpBase<Scalar> > create_hess_g_xp( int j, int l ) const;
231  virtual RCP<LinearOpBase<Scalar> > create_hess_g_pp( int j, int l1, int l2 ) const;
232 
234 
235 protected:
236 
239 
248  void initializeDefaultBase();
249 
254  void resetDefaultBase();
255 
257 
258 private:
259 
262 
264  virtual RCP<LinearOpBase<Scalar> > create_DfDp_op_impl(int l) const;
265 
267  virtual RCP<LinearOpBase<Scalar> > create_DgDx_dot_op_impl(int j) const;
268 
270  virtual RCP<LinearOpBase<Scalar> > create_DgDx_op_impl(int j) const;
271 
273  virtual RCP<LinearOpBase<Scalar> > create_DgDp_op_impl(int j, int l) const;
274 
276 
279 
281  virtual ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const = 0;
282 
284  virtual void evalModelImpl(
287  ) const = 0;
288 
290 
291 protected:
292 
295 
296 private:
297 
298  // //////////////////////////////
299  // Private tpyes
300 
301  typedef ModelEvaluatorDefaultBaseTypes::DefaultDerivLinearOpSupport
302  DefaultDerivLinearOpSupport;
303 
304  typedef ModelEvaluatorDefaultBaseTypes::DefaultDerivMvAdjointSupport
305  DefaultDerivMvAdjointSupport;
306 
307  typedef ModelEvaluatorDefaultBaseTypes::MultiVectorAdjointPair<Scalar>
308  MultiVectorAdjointPair;
309 
310  // //////////////////////////////
311  // Private data members
312 
313  bool isInitialized_;
314 
315  Array<DefaultDerivLinearOpSupport> DfDp_default_op_support_;
316 
317  Array<DefaultDerivLinearOpSupport> DgDx_dot_default_op_support_;
318 
319  Array<DefaultDerivLinearOpSupport> DgDx_default_op_support_;
320 
321  Array<Array<DefaultDerivLinearOpSupport> > DgDp_default_op_support_;
322  Array<Array<DefaultDerivMvAdjointSupport> > DgDp_default_mv_support_;
323 
324  bool default_W_support_;
325 
326  ModelEvaluatorBase::OutArgs<Scalar> prototypeOutArgs_;
327 
328  // //////////////////////////////
329  // Private member functions
330 
331  void lazyInitializeDefaultBase() const;
332 
333  void assert_l(const int l) const;
334 
335  void assert_j(const int j) const;
336 
337  // //////////////////////////////
338  // Private static functions
339 
340  static DefaultDerivLinearOpSupport
341  determineDefaultDerivLinearOpSupport(
342  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl
343  );
344 
345  static RCP<LinearOpBase<Scalar> >
346  createDefaultLinearOp(
347  const DefaultDerivLinearOpSupport &defaultLinearOpSupport,
348  const RCP<const VectorSpaceBase<Scalar> > &fnc_space,
349  const RCP<const VectorSpaceBase<Scalar> > &var_space
350  );
351 
353  updateDefaultLinearOpSupport(
354  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
355  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
356  );
357 
359  getOutArgImplForDefaultLinearOpSupport(
361  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
362  );
363 
364  static DefaultDerivMvAdjointSupport
365  determineDefaultDerivMvAdjointSupport(
366  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
367  const VectorSpaceBase<Scalar> &fnc_space,
368  const VectorSpaceBase<Scalar> &var_space
369  );
370 
372  updateDefaultDerivMvAdjointSupport(
373  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
374  const DefaultDerivMvAdjointSupport &defaultMvAdjointSupport
375  );
376 
377 };
378 
379 
380 } // namespace Thyra
381 
382 
383 //
384 // Implementations
385 //
386 
387 
388 #include "Thyra_ModelEvaluatorHelpers.hpp"
389 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
390 #include "Thyra_DetachedMultiVectorView.hpp"
391 #include "Teuchos_Assert.hpp"
392 
393 
394 namespace Thyra {
395 
396 
397 // Overridden from ModelEvaluator
398 
399 
400 template<class Scalar>
402 {
403  lazyInitializeDefaultBase();
404  return prototypeOutArgs_.Np();
405 }
406 
407 
408 template<class Scalar>
410 {
411  lazyInitializeDefaultBase();
412  return prototypeOutArgs_.Ng();
413 }
414 
415 
416 template<class Scalar>
419 {
420  lazyInitializeDefaultBase();
421  if (default_W_support_)
422  return this->get_W_factory()->createOp();
423  return Teuchos::null;
424 }
425 
426 
427 template<class Scalar>
430 {
431  lazyInitializeDefaultBase();
432 #ifdef TEUCHOS_DEBUG
433  assert_l(l);
434 #endif
435  const DefaultDerivLinearOpSupport
436  defaultLinearOpSupport = DfDp_default_op_support_[l];
437  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
438  return createDefaultLinearOp(
439  defaultLinearOpSupport,
440  this->get_f_space(),
441  this->get_p_space(l)
442  );
443  }
444  return this->create_DfDp_op_impl(l);
445 }
446 
447 
448 template<class Scalar>
451 {
452  lazyInitializeDefaultBase();
453 #ifdef TEUCHOS_DEBUG
454  assert_j(j);
455 #endif
456  const DefaultDerivLinearOpSupport
457  defaultLinearOpSupport = DgDx_dot_default_op_support_[j];
458  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
459  return createDefaultLinearOp(
460  defaultLinearOpSupport,
461  this->get_g_space(j),
462  this->get_x_space()
463  );
464  }
465  return this->create_DgDx_dot_op_impl(j);
466 }
467 
468 
469 template<class Scalar>
472 {
473  lazyInitializeDefaultBase();
474 #ifdef TEUCHOS_DEBUG
475  assert_j(j);
476 #endif
477  const DefaultDerivLinearOpSupport
478  defaultLinearOpSupport = DgDx_default_op_support_[j];
479  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
480  return createDefaultLinearOp(
481  defaultLinearOpSupport,
482  this->get_g_space(j),
483  this->get_x_space()
484  );
485  }
486  return this->create_DgDx_op_impl(j);
487 }
488 
489 
490 template<class Scalar>
493 {
494  lazyInitializeDefaultBase();
495 #ifdef TEUCHOS_DEBUG
496  assert_j(j);
497  assert_l(l);
498 #endif
499  const DefaultDerivLinearOpSupport
500  defaultLinearOpSupport = DgDp_default_op_support_[j][l];
501  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
502  return createDefaultLinearOp(
503  defaultLinearOpSupport,
504  this->get_g_space(j),
505  this->get_p_space(l)
506  );
507  }
508  return this->create_DgDp_op_impl(j,l);
509 }
510 
511 
512 template<class Scalar>
515 {
516  lazyInitializeDefaultBase();
517  return prototypeOutArgs_;
518 }
519 
520 
521 template<class Scalar>
525  ) const
526 {
527 
528  using Teuchos::outArg;
529  typedef ModelEvaluatorBase MEB;
530 
531  lazyInitializeDefaultBase();
532 
533  const int l_Np = outArgs.Np();
534  const int l_Ng = outArgs.Ng();
535 
536  //
537  // A) Assert that the inArgs and outArgs object match this class!
538  //
539 
540 #ifdef TEUCHOS_DEBUG
541  assertInArgsEvalObjects(*this,inArgs);
542  assertOutArgsEvalObjects(*this,outArgs,&inArgs);
543 #endif
544 
545  //
546  // B) Setup the OutArgs object for the underlying implementation's
547  // evalModelImpl(...) function
548  //
549 
550  MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl();
551  Array<MultiVectorAdjointPair> DgDp_temp_adjoint_copies;
552 
553  {
554 
555  outArgsImpl.setArgs(outArgs,true);
556 
557  // DfDp(l)
558  if (outArgsImpl.supports(MEB::OUT_ARG_f)) {
559  for ( int l = 0; l < l_Np; ++l ) {
560  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
561  DfDp_default_op_support_[l];
562  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
563  outArgsImpl.set_DfDp( l,
564  getOutArgImplForDefaultLinearOpSupport(
565  outArgs.get_DfDp(l), defaultLinearOpSupport
566  )
567  );
568  }
569  else {
570  // DfDp(l) already set by outArgsImpl.setArgs(...)!
571  }
572  }
573  }
574 
575  // DgDx_dot(j)
576  for ( int j = 0; j < l_Ng; ++j ) {
577  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
578  DgDx_dot_default_op_support_[j];
579  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
580  outArgsImpl.set_DgDx_dot( j,
581  getOutArgImplForDefaultLinearOpSupport(
582  outArgs.get_DgDx_dot(j), defaultLinearOpSupport
583  )
584  );
585  }
586  else {
587  // DgDx_dot(j) already set by outArgsImpl.setArgs(...)!
588  }
589  }
590 
591  // DgDx(j)
592  for ( int j = 0; j < l_Ng; ++j ) {
593  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
594  DgDx_default_op_support_[j];
595  if (defaultLinearOpSupport.provideDefaultLinearOp()) {
596  outArgsImpl.set_DgDx( j,
597  getOutArgImplForDefaultLinearOpSupport(
598  outArgs.get_DgDx(j), defaultLinearOpSupport
599  )
600  );
601  }
602  else {
603  // DgDx(j) already set by outArgsImpl.setArgs(...)!
604  }
605  }
606 
607  // DgDp(j,l)
608  for ( int j = 0; j < l_Ng; ++j ) {
609  const Array<DefaultDerivLinearOpSupport> &DgDp_default_op_support_j =
610  DgDp_default_op_support_[j];
611  const Array<DefaultDerivMvAdjointSupport> &DgDp_default_mv_support_j =
612  DgDp_default_mv_support_[j];
613  for ( int l = 0; l < l_Np; ++l ) {
614  const DefaultDerivLinearOpSupport defaultLinearOpSupport =
615  DgDp_default_op_support_j[l];
616  const DefaultDerivMvAdjointSupport defaultMvAdjointSupport =
617  DgDp_default_mv_support_j[l];
618  MEB::Derivative<Scalar> DgDp_j_l;
619  if (!outArgs.supports(MEB::OUT_ARG_DgDp,j,l).none())
620  DgDp_j_l = outArgs.get_DgDp(j,l);
621  if (
622  defaultLinearOpSupport.provideDefaultLinearOp()
623  && !is_null(DgDp_j_l.getLinearOp())
624  )
625  {
626  outArgsImpl.set_DgDp( j, l,
627  getOutArgImplForDefaultLinearOpSupport(
628  DgDp_j_l, defaultLinearOpSupport
629  )
630  );
631  }
632  else if (
633  defaultMvAdjointSupport.provideDefaultAdjoint()
634  && !is_null(DgDp_j_l.getMultiVector())
635  )
636  {
637  const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv =
638  DgDp_j_l.getMultiVector();
639  if (
640  defaultMvAdjointSupport.mvAdjointCopyOrientation()
641  ==
642  DgDp_j_l.getMultiVectorOrientation()
643  )
644  {
645  // The orientation of the multi-vector is different so we need to
646  // create a temporary copy to pass to evalModelImpl(...) and then
647  // copy it back again!
648  const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv_adj =
649  createMembers(DgDp_j_l_mv->domain(), DgDp_j_l_mv->range()->dim());
650  outArgsImpl.set_DgDp( j, l,
651  MEB::Derivative<Scalar>(
652  DgDp_j_l_mv_adj,
653  getOtherDerivativeMultiVectorOrientation(
654  defaultMvAdjointSupport.mvAdjointCopyOrientation()
655  )
656  )
657  );
658  // Remember these multi-vectors so that we can do the transpose copy
659  // back after the evaluation!
660  DgDp_temp_adjoint_copies.push_back(
661  MultiVectorAdjointPair(DgDp_j_l_mv, DgDp_j_l_mv_adj)
662  );
663  }
664  else {
665  // The form of the multi-vector is supported by evalModelImpl(..)
666  // and is already set on the outArgsImpl object.
667  }
668  }
669  else {
670  // DgDp(j,l) already set by outArgsImpl.setArgs(...)!
671  }
672  }
673  }
674 
675  // W
676  {
678  if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) {
680  W_factory = this->get_W_factory();
681  // Extract the underlying W_op object (if it exists)
682  RCP<const LinearOpBase<Scalar> > W_op_const;
683  uninitializeOp<Scalar>(*W_factory, W.ptr(), outArg(W_op_const));
685  if (!is_null(W_op_const)) {
686  // Here we remove the const. This is perfectly safe since
687  // w.r.t. this class, we put a non-const object in there and we can
688  // expect to change that object after the fact. That is our
689  // prerogative.
690  W_op = Teuchos::rcp_const_cast<LinearOpBase<Scalar> >(W_op_const);
691  }
692  else {
693  // The W_op object has not been initialized yet so create it. The
694  // next time through, we should not have to do this!
695  W_op = this->create_W_op();
696  }
697  outArgsImpl.set_W_op(W_op);
698  }
699  }
700  }
701 
702  //
703  // C) Evaluate the underlying model implementation!
704  //
705 
706  this->evalModelImpl( inArgs, outArgsImpl );
707 
708  //
709  // D) Post-process the output arguments
710  //
711 
712  // Do explicit transposes for DgDp(j,l) if needed
713  const int numMvAdjointCopies = DgDp_temp_adjoint_copies.size();
714  for ( int adj_copy_i = 0; adj_copy_i < numMvAdjointCopies; ++adj_copy_i ) {
715  const MultiVectorAdjointPair adjPair =
716  DgDp_temp_adjoint_copies[adj_copy_i];
717  doExplicitMultiVectorAdjoint( *adjPair.mvImplAdjoint, &*adjPair.mvOuter );
718  }
719 
720  // Update W given W_op and W_factory
721  {
723  if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) {
725  W_factory = this->get_W_factory();
726  W_factory->setOStream(this->getOStream());
727  W_factory->setVerbLevel(this->getVerbLevel());
728  initializeOp<Scalar>(*W_factory, outArgsImpl.get_W_op().getConst(), W.ptr());
729  }
730  }
731 
732 }
733 
734 
735 // protected
736 
737 
738 // Setup functions called by subclasses
739 
740 template<class Scalar>
742 {
743 
744  typedef ModelEvaluatorBase MEB;
745 
746  // In case we throw half way thorugh, set to uninitialized
747  isInitialized_ = false;
748  default_W_support_ = false;
749 
750  //
751  // A) Get the InArgs and OutArgs from the subclass
752  //
753 
754  const MEB::InArgs<Scalar> inArgs = this->createInArgs();
755  const MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl();
756 
757  //
758  // B) Validate the subclasses InArgs and OutArgs
759  //
760 
761 #ifdef TEUCHOS_DEBUG
762  assertInArgsOutArgsSetup( this->description(), inArgs, outArgsImpl );
763 #endif // TEUCHOS_DEBUG
764 
765  //
766  // C) Set up support for default derivative objects and prototype OutArgs
767  //
768 
769  const int l_Ng = outArgsImpl.Ng();
770  const int l_Np = outArgsImpl.Np();
771 
772  // Set support for all outputs supported in the underly implementation
773  MEB::OutArgsSetup<Scalar> outArgs;
774  outArgs.setModelEvalDescription(this->description());
775  outArgs.set_Np_Ng(l_Np,l_Ng);
776  outArgs.setSupports(outArgsImpl);
777 
778  // DfDp
779  DfDp_default_op_support_.clear();
780  if (outArgs.supports(MEB::OUT_ARG_f)) {
781  for ( int l = 0; l < l_Np; ++l ) {
782  const MEB::DerivativeSupport DfDp_l_impl_support =
783  outArgsImpl.supports(MEB::OUT_ARG_DfDp,l);
784  const DefaultDerivLinearOpSupport DfDp_l_op_support =
785  determineDefaultDerivLinearOpSupport(DfDp_l_impl_support);
786  DfDp_default_op_support_.push_back(DfDp_l_op_support);
787  outArgs.setSupports(
788  MEB::OUT_ARG_DfDp, l,
789  updateDefaultLinearOpSupport(
790  DfDp_l_impl_support, DfDp_l_op_support
791  )
792  );
793  }
794  }
795 
796  // DgDx_dot
797  DgDx_dot_default_op_support_.clear();
798  for ( int j = 0; j < l_Ng; ++j ) {
799  const MEB::DerivativeSupport DgDx_dot_j_impl_support =
800  outArgsImpl.supports(MEB::OUT_ARG_DgDx_dot,j);
801  const DefaultDerivLinearOpSupport DgDx_dot_j_op_support =
802  determineDefaultDerivLinearOpSupport(DgDx_dot_j_impl_support);
803  DgDx_dot_default_op_support_.push_back(DgDx_dot_j_op_support);
804  outArgs.setSupports(
805  MEB::OUT_ARG_DgDx_dot, j,
806  updateDefaultLinearOpSupport(
807  DgDx_dot_j_impl_support, DgDx_dot_j_op_support
808  )
809  );
810  }
811 
812  // DgDx
813  DgDx_default_op_support_.clear();
814  for ( int j = 0; j < l_Ng; ++j ) {
815  const MEB::DerivativeSupport DgDx_j_impl_support =
816  outArgsImpl.supports(MEB::OUT_ARG_DgDx,j);
817  const DefaultDerivLinearOpSupport DgDx_j_op_support =
818  determineDefaultDerivLinearOpSupport(DgDx_j_impl_support);
819  DgDx_default_op_support_.push_back(DgDx_j_op_support);
820  outArgs.setSupports(
821  MEB::OUT_ARG_DgDx, j,
822  updateDefaultLinearOpSupport(
823  DgDx_j_impl_support, DgDx_j_op_support
824  )
825  );
826  }
827 
828  // DgDp
829  DgDp_default_op_support_.clear();
830  DgDp_default_mv_support_.clear();
831  for ( int j = 0; j < l_Ng; ++j ) {
832  DgDp_default_op_support_.push_back(Array<DefaultDerivLinearOpSupport>());
833  DgDp_default_mv_support_.push_back(Array<DefaultDerivMvAdjointSupport>());
834  for ( int l = 0; l < l_Np; ++l ) {
835  const MEB::DerivativeSupport DgDp_j_l_impl_support =
836  outArgsImpl.supports(MEB::OUT_ARG_DgDp,j,l);
837  // LinearOpBase support
838  const DefaultDerivLinearOpSupport DgDp_j_l_op_support =
839  determineDefaultDerivLinearOpSupport(DgDp_j_l_impl_support);
840  DgDp_default_op_support_[j].push_back(DgDp_j_l_op_support);
841  outArgs.setSupports(
842  MEB::OUT_ARG_DgDp, j, l,
843  updateDefaultLinearOpSupport(
844  DgDp_j_l_impl_support, DgDp_j_l_op_support
845  )
846  );
847  // MultiVectorBase
848  const DefaultDerivMvAdjointSupport DgDp_j_l_mv_support =
849  determineDefaultDerivMvAdjointSupport(
850  DgDp_j_l_impl_support, *this->get_g_space(j), *this->get_p_space(l)
851  );
852  DgDp_default_mv_support_[j].push_back(DgDp_j_l_mv_support);
853  outArgs.setSupports(
854  MEB::OUT_ARG_DgDp, j, l,
855  updateDefaultDerivMvAdjointSupport(
856  outArgs.supports(MEB::OUT_ARG_DgDp, j, l),
857  DgDp_j_l_mv_support
858  )
859  );
860  }
861  }
862  // 2007/09/09: rabart: ToDo: Move the above code into a private helper
863  // function!
864 
865  // W (given W_op and W_factory)
866  default_W_support_ = false;
867  if ( outArgsImpl.supports(MEB::OUT_ARG_W_op) && !is_null(this->get_W_factory())
868  && !outArgsImpl.supports(MEB::OUT_ARG_W) )
869  {
870  default_W_support_ = true;
871  outArgs.setSupports(MEB::OUT_ARG_W);
872  outArgs.set_W_properties(outArgsImpl.get_W_properties());
873  }
874 
875  //
876  // D) All done!
877  //
878 
879  prototypeOutArgs_ = outArgs;
880  isInitialized_ = true;
881 
882 }
883 
884 template<class Scalar>
886 {
887  isInitialized_ = false;
888 }
889 
890 // Private functions with default implementaton to be overridden by subclasses
891 
892 
893 template<class Scalar>
896 {
897  typedef ModelEvaluatorBase MEB;
898  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
900  outArgs.supports(MEB::OUT_ARG_DfDp,l).supports(MEB::DERIV_LINEAR_OP),
901  std::logic_error,
902  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
903  " supports the LinearOpBase form of DfDp("<<l<<") (as determined from its"
904  " OutArgs object created by createOutArgsImpl())"
905  " but this function create_DfDp_op_impl(...) has not been overridden"
906  " to create such an object!"
907  );
908  return Teuchos::null;
909 }
910 
911 
912 template<class Scalar>
913 RCP<LinearOpBase<Scalar> >
914 ModelEvaluatorDefaultBase<Scalar>::create_DgDx_dot_op_impl(int j) const
915 {
916  typedef ModelEvaluatorBase MEB;
917  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
919  outArgs.supports(MEB::OUT_ARG_DgDx_dot,j).supports(MEB::DERIV_LINEAR_OP),
920  std::logic_error,
921  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
922  " supports the LinearOpBase form of DgDx_dot("<<j<<") (as determined from"
923  " its OutArgs object created by createOutArgsImpl())"
924  " but this function create_DgDx_dot_op_impl(...) has not been overridden"
925  " to create such an object!"
926  );
927  return Teuchos::null;
928 }
929 
930 
931 template<class Scalar>
932 RCP<LinearOpBase<Scalar> >
933 ModelEvaluatorDefaultBase<Scalar>::create_DgDx_op_impl(int j) const
934 {
935  typedef ModelEvaluatorBase MEB;
936  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
938  outArgs.supports(MEB::OUT_ARG_DgDx,j).supports(MEB::DERIV_LINEAR_OP),
939  std::logic_error,
940  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
941  " supports the LinearOpBase form of DgDx("<<j<<") (as determined from"
942  " its OutArgs object created by createOutArgsImpl())"
943  " but this function create_DgDx_op_impl(...) has not been overridden"
944  " to create such an object!"
945  );
946  return Teuchos::null;
947 }
948 
949 
950 template<class Scalar>
951 RCP<LinearOpBase<Scalar> >
952 ModelEvaluatorDefaultBase<Scalar>::create_DgDp_op_impl(int j, int l) const
953 {
954  typedef ModelEvaluatorBase MEB;
955  MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl();
957  outArgs.supports(MEB::OUT_ARG_DgDp,j,l).supports(MEB::DERIV_LINEAR_OP),
958  std::logic_error,
959  "Error, The ModelEvaluator subclass "<<this->description()<<" says that it"
960  " supports the LinearOpBase form of DgDp("<<j<<","<<l<<")"
961  " (as determined from its OutArgs object created by createOutArgsImpl())"
962  " but this function create_DgDp_op_impl(...) has not been overridden"
963  " to create such an object!"
964  );
965  return Teuchos::null;
966 }
967 
968 
969 template<class Scalar>
970 RCP<const VectorSpaceBase<Scalar> >
972 {
973  return this->get_f_space();
974 }
975 
976 template<class Scalar>
979 {
980  return this->get_g_space(j);
981 }
982 
983 template<class Scalar>
986 {
987  return Teuchos::null;
988 }
989 
990 template<class Scalar>
993 {
994  return Teuchos::null;
995 }
996 
997 template<class Scalar>
1000 {
1001  return Teuchos::null;
1002 }
1003 
1004 template<class Scalar>
1007 {
1008  return Teuchos::null;
1009 }
1010 
1011 template<class Scalar>
1014 {
1015  return Teuchos::null;
1016 }
1017 
1018 template<class Scalar>
1021 {
1022  return Teuchos::null;
1023 }
1024 
1025 // protected
1026 
1027 
1028 template<class Scalar>
1030  :isInitialized_(false), default_W_support_(false)
1031 {}
1032 
1033 
1034 // private
1035 
1036 
1037 template<class Scalar>
1039 {
1040  if (!isInitialized_)
1041  const_cast<ModelEvaluatorDefaultBase<Scalar>*>(this)->initializeDefaultBase();
1042 }
1043 
1044 
1045 template<class Scalar>
1046 void ModelEvaluatorDefaultBase<Scalar>::assert_l(const int l) const
1047 {
1049 }
1050 
1051 
1052 template<class Scalar>
1053 void ModelEvaluatorDefaultBase<Scalar>::assert_j(const int j) const
1054 {
1056 }
1057 
1058 
1059 // Private static functions
1060 
1061 
1062 template<class Scalar>
1063 ModelEvaluatorDefaultBaseTypes::DefaultDerivLinearOpSupport
1064 ModelEvaluatorDefaultBase<Scalar>::determineDefaultDerivLinearOpSupport(
1065  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl
1066  )
1067 {
1068  typedef ModelEvaluatorBase MEB;
1069  if (
1070  (
1071  derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1072  ||
1073  derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW)
1074  )
1075  &&
1076  !derivSupportImpl.supports(MEB::DERIV_LINEAR_OP)
1077  )
1078  {
1079  return DefaultDerivLinearOpSupport(
1080  derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1081  ? MEB::DERIV_MV_BY_COL
1082  : MEB::DERIV_TRANS_MV_BY_ROW
1083  );
1084  }
1085  return DefaultDerivLinearOpSupport();
1086 }
1087 
1088 
1089 template<class Scalar>
1090 RCP<LinearOpBase<Scalar> >
1091 ModelEvaluatorDefaultBase<Scalar>::createDefaultLinearOp(
1092  const DefaultDerivLinearOpSupport &defaultLinearOpSupport,
1093  const RCP<const VectorSpaceBase<Scalar> > &fnc_space,
1094  const RCP<const VectorSpaceBase<Scalar> > &var_space
1095  )
1096 {
1097  using Teuchos::rcp_implicit_cast;
1098  typedef LinearOpBase<Scalar> LOB;
1099  typedef ModelEvaluatorBase MEB;
1100  switch(defaultLinearOpSupport.mvImplOrientation()) {
1101  case MEB::DERIV_MV_BY_COL:
1102  // The MultiVector will do just fine as the LinearOpBase
1103  return createMembers(fnc_space, var_space->dim());
1104  case MEB::DERIV_TRANS_MV_BY_ROW:
1105  // We will have to implicitly transpose the underlying MultiVector
1106  return nonconstAdjoint<Scalar>(
1107  rcp_implicit_cast<LOB>(createMembers(var_space, fnc_space->dim()))
1108  );
1109 #ifdef TEUCHOS_DEBUG
1110  default:
1112 #endif
1113  }
1114  return Teuchos::null; // Will never be called!
1115 }
1116 
1117 
1118 template<class Scalar>
1119 ModelEvaluatorBase::DerivativeSupport
1120 ModelEvaluatorDefaultBase<Scalar>::updateDefaultLinearOpSupport(
1121  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1122  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
1123  )
1124 {
1125  typedef ModelEvaluatorBase MEB;
1126  MEB::DerivativeSupport derivSupport = derivSupportImpl;
1127  if (defaultLinearOpSupport.provideDefaultLinearOp())
1128  derivSupport.plus(MEB::DERIV_LINEAR_OP);
1129  return derivSupport;
1130 }
1131 
1132 
1133 template<class Scalar>
1134 ModelEvaluatorBase::Derivative<Scalar>
1135 ModelEvaluatorDefaultBase<Scalar>::getOutArgImplForDefaultLinearOpSupport(
1136  const ModelEvaluatorBase::Derivative<Scalar> &deriv,
1137  const DefaultDerivLinearOpSupport &defaultLinearOpSupport
1138  )
1139 {
1140 
1141  using Teuchos::rcp_dynamic_cast;
1142  typedef ModelEvaluatorBase MEB;
1143  typedef MultiVectorBase<Scalar> MVB;
1144  typedef ScaledAdjointLinearOpBase<Scalar> SALOB;
1145 
1146  // If the derivative is not a LinearOpBase then it it either empty or is a
1147  // MultiVectorBase object, and in either case we just return it since the
1148  // underlying evalModelImpl(...) functions should be able to handle it!
1149  if (is_null(deriv.getLinearOp()))
1150  return deriv;
1151 
1152  // The derivative is LinearOpBase so get out the underlying MultiVectorBase
1153  // object and return its derivative multi-vector form.
1154  switch(defaultLinearOpSupport.mvImplOrientation()) {
1155  case MEB::DERIV_MV_BY_COL: {
1156  return MEB::Derivative<Scalar>(
1157  rcp_dynamic_cast<MVB>(deriv.getLinearOp(),true),
1158  MEB::DERIV_MV_BY_COL
1159  );
1160  }
1161  case MEB::DERIV_TRANS_MV_BY_ROW: {
1162  return MEB::Derivative<Scalar>(
1163  rcp_dynamic_cast<MVB>(
1164  rcp_dynamic_cast<SALOB>(deriv.getLinearOp(),true)->getNonconstOrigOp()
1165  ),
1166  MEB::DERIV_TRANS_MV_BY_ROW
1167  );
1168  }
1169 #ifdef TEUCHOS_DEBUG
1170  default:
1172 #endif
1173  }
1174 
1175  return ModelEvaluatorBase::Derivative<Scalar>(); // Should never get here!
1176 
1177 }
1178 
1179 
1180 template<class Scalar>
1181 ModelEvaluatorDefaultBaseTypes::DefaultDerivMvAdjointSupport
1182 ModelEvaluatorDefaultBase<Scalar>::determineDefaultDerivMvAdjointSupport(
1183  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1184  const VectorSpaceBase<Scalar> &fnc_space,
1185  const VectorSpaceBase<Scalar> &var_space
1186  )
1187 {
1188  typedef ModelEvaluatorBase MEB;
1189  // Here we will support the adjoint copy for of a multi-vector if both
1190  // spaces give rise to in-core vectors.
1191  const bool implSupportsMv =
1192  ( derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1193  || derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW) );
1194  const bool implLacksMvOrientSupport =
1195  ( !derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1196  || !derivSupportImpl.supports(MEB::DERIV_TRANS_MV_BY_ROW) );
1197  const bool bothSpacesHaveInCoreViews =
1198  ( fnc_space.hasInCoreView() && var_space.hasInCoreView() );
1199  if ( implSupportsMv && implLacksMvOrientSupport && bothSpacesHaveInCoreViews ) {
1200  return DefaultDerivMvAdjointSupport(
1201  derivSupportImpl.supports(MEB::DERIV_MV_BY_COL)
1202  ? MEB::DERIV_TRANS_MV_BY_ROW
1203  : MEB::DERIV_MV_BY_COL
1204  );
1205  }
1206  // We can't provide an adjoint copy or such a copy is not needed!
1207  return DefaultDerivMvAdjointSupport();
1208 }
1209 
1210 
1211 template<class Scalar>
1212 ModelEvaluatorBase::DerivativeSupport
1213 ModelEvaluatorDefaultBase<Scalar>::updateDefaultDerivMvAdjointSupport(
1214  const ModelEvaluatorBase::DerivativeSupport &derivSupportImpl,
1215  const DefaultDerivMvAdjointSupport &defaultMvAdjointSupport
1216  )
1217 {
1218  typedef ModelEvaluatorBase MEB;
1219  MEB::DerivativeSupport derivSupport = derivSupportImpl;
1220  if (defaultMvAdjointSupport.provideDefaultAdjoint())
1221  derivSupport.plus(defaultMvAdjointSupport.mvAdjointCopyOrientation());
1222  return derivSupport;
1223 }
1224 
1225 
1226 } // namespace Thyra
1227 
1228 
1229 #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
virtual RCP< LinearOpBase< Scalar > > create_hess_g_xp(int j, int l) const
Default base class for concrete model evaluators.
virtual RCP< LinearOpBase< Scalar > > create_hess_f_xx() const
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)
virtual RCP< const VectorSpaceBase< Scalar > > get_g_multiplier_space(int j) const
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
virtual RCP< const VectorSpaceBase< Scalar > > get_f_multiplier_space() const
Ptr< T > ptr() const
virtual RCP< LinearOpBase< Scalar > > create_hess_f_pp(int l1, int l2) const
virtual RCP< LinearOpBase< Scalar > > create_hess_g_xx(int j) 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)
virtual RCP< LinearOpBase< Scalar > > create_hess_g_pp(int j, int l1, int l2) const
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...
virtual RCP< LinearOpBase< Scalar > > create_hess_f_xp(int l) const