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