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