Thyra  Version of the Day
Thyra_ModelEvaluatorDefaultBase.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Thyra: Interfaces and Support for Abstract Numerical Algorithms
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
43 #define THYRA_MODEL_EVALUATOR_DEFAULT_BASE_HPP
44 
45 #include "Thyra_VectorBase.hpp"
46 
47 #include "Thyra_ModelEvaluator.hpp"
48 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
49 
50 
51 #ifdef HAVE_THYRA_ME_POLYNOMIAL
52 
53 
54 // Define the polynomial traits class specializtaion
55 // Teuchos::PolynomialTraits<VectorBase > before there is any chance of an
56 // instantiation requiring the definition of this class. The Intel C++ 9.1
57 // compiler is having trouble compiling Thyra_EpetraModelEvaluator.cpp because
58 // Thyra_ModelEvaluatorBase_decl.hpp is only including
59 // "Teuchos_Polynomial.hpp" which does not contain the needed specialization.
60 // By including it here, all client code is likely to compile just fine. I am
61 // going through all of the in order to avoid having to put
62 // Thyra_PolynomialVectorTraits.hpp in the interfaces directory. The problem
63 // with putting Thyra_PolynomialVectorTraits.hpp the interfaces directory is
64 // that it contains calls to code in the support directory and creates an
65 // unacceptable circular dependency that will cause problems once we move to
66 // subpackages in the CMake build system.
67 #include "Thyra_PolynomialVectorTraits.hpp"
68 
69 
70 #endif // HAVE_THYRA_ME_POLYNOMIAL
71 
72 
73 namespace Thyra {
74 
75 
76 //
77 // Undocumentated (from the user's perspective) types that are used to
78 // implement ModelEvaluatorDefaultBase. These types are defined outside of
79 // the templated class since they do nt depend on the scalar type.
80 //
81 
82 
83 namespace ModelEvaluatorDefaultBaseTypes {
84 
85 
86 // Type used to determine if the ModelEvaluatorDefaultBase implementation will
87 // provide a LinearOpBase wrapper for derivative object given in
88 // MultiVectorBase form.
89 class DefaultDerivLinearOpSupport {
90 public:
91  DefaultDerivLinearOpSupport()
92  :provideDefaultLinearOp_(false),
93  mvImplOrientation_(ModelEvaluatorBase::DERIV_MV_BY_COL)
94  {}
95  DefaultDerivLinearOpSupport(
97  )
98  :provideDefaultLinearOp_(true),
99  mvImplOrientation_(mvImplOrientation_in)
100  {}
101  bool provideDefaultLinearOp() const
102  { return provideDefaultLinearOp_; }
104  { return mvImplOrientation_; }
105 private:
106  bool provideDefaultLinearOp_;
108 };
109 
110 
111 // Type used to determine if the ModelEvaluatorDefaultBase implementation will
112 // provide an explicit transpose copy of a derivative object given in
113 // MultiVectorBase form.
114 class DefaultDerivMvAdjointSupport {
115 public:
116  DefaultDerivMvAdjointSupport()
117  :provideDefaultAdjoint_(false),
118  mvAdjointCopyOrientation_(ModelEvaluatorBase::DERIV_MV_BY_COL)
119  {}
120  DefaultDerivMvAdjointSupport(
121  const ModelEvaluatorBase::EDerivativeMultiVectorOrientation mvAdjointCopyOrientation_in
122  )
123  :provideDefaultAdjoint_(true),
124  mvAdjointCopyOrientation_(mvAdjointCopyOrientation_in)
125  {}
126  bool provideDefaultAdjoint() const
127  { return provideDefaultAdjoint_; }
128  ModelEvaluatorBase::EDerivativeMultiVectorOrientation mvAdjointCopyOrientation() const
129  { return mvAdjointCopyOrientation_; }
130 private:
131  bool provideDefaultAdjoint_;
133 };
134 
135 
136 // Type used to remember a pair of transposed multi-vectors to implement a
137 // adjoint copy.
138 template<class Scalar>
139 struct MultiVectorAdjointPair {
140  MultiVectorAdjointPair()
141  {}
142  MultiVectorAdjointPair(
143  const RCP<MultiVectorBase<Scalar> > &in_mvOuter,
144  const RCP<const MultiVectorBase<Scalar> > &in_mvImplAdjoint
145  )
146  : mvOuter(in_mvOuter),
147  mvImplAdjoint(in_mvImplAdjoint)
148  {}
149  RCP<MultiVectorBase<Scalar> > mvOuter;
150  RCP<const MultiVectorBase<Scalar> > mvImplAdjoint;
151 private:
152 };
153 
154 
155 
156 
157 } // namespace ModelEvaluatorDefaultBaseTypes
158 
159 
187 template<class Scalar>
188 class ModelEvaluatorDefaultBase : virtual public ModelEvaluator<Scalar>
189 {
190 public:
191 
194 
196  int Np() const;
198  int Ng() const;
212  void evalModel(
215  ) const;
225  virtual RCP<LinearOpBase<Scalar> > create_hess_f_pp( int l1, int l2 ) 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 
249 
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
size_type size() const
void push_back(const value_type &x)
RCP< const T > getConst() const
Ptr< T > ptr() const
Determines the forms of a general derivative that are supported.
Simple aggregate class that stores a derivative object as a general linear operator or as a multi-vec...
Concrete aggregate class for all input arguments computable by a ModelEvaluator subclass object.
Concrete aggregate class for all output arguments computable by a ModelEvaluator subclass object.
Derivative< Scalar > get_DfDp(int l) const
Precondition: supports(OUT_ARG_DfDp,l)==true.
RCP< LinearOpWithSolveBase< Scalar > > get_W() const
Precondition: supports(OUT_ARG_W)==true.
int Ng() const
Return the number of axillary response functions g(j)(...) supported (Ng >= 0).
Derivative< Scalar > get_DgDp(int j, int l) const
Precondition: supports(OUT_ARG_DgDp,j,l)==true.
Derivative< Scalar > get_DgDx_dot(int j) const
Precondition: supports(OUT_ARG_DgDx_dot,j)==true.
Derivative< Scalar > get_DgDx(int j) const
Precondition: supports(OUT_ARG_DgDx,j)==true.
bool supports(EOutArgsMembers arg) const
Determine if an input argument is supported or not.
int Np() const
Return the number of parameter subvectors p(l) supported (Np >= 0).
Base subclass for ModelEvaluator that defines some basic types.
Default base class for concrete model evaluators.
RCP< LinearOpBase< Scalar > > create_DgDp_op(int j, int l) const
virtual RCP< LinearOpBase< Scalar > > create_hess_f_xx() const
RCP< LinearOpBase< Scalar > > create_DgDx_op(int j) const
virtual RCP< LinearOpBase< Scalar > > create_hess_f_pp(int l1, int l2) const
virtual RCP< const VectorSpaceBase< Scalar > > get_g_multiplier_space(int j) const
RCP< LinearOpBase< Scalar > > create_DgDx_dot_op(int j) const
RCP< LinearOpWithSolveBase< Scalar > > create_W() const
virtual RCP< LinearOpBase< Scalar > > create_hess_f_xp(int l) const
virtual RCP< const VectorSpaceBase< Scalar > > get_f_multiplier_space() const
void evalModel(const ModelEvaluatorBase::InArgs< Scalar > &inArgs, const ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
virtual RCP< LinearOpBase< Scalar > > create_hess_g_pp(int j, int l1, int l2) const
ModelEvaluatorBase::OutArgs< Scalar > createOutArgs() const
void resetDefaultBase()
Sets the the DefaultBase to an uninitialized state, forcing lazy initialization when needed.
void initializeDefaultBase()
Function called by subclasses to fully initialize this object on any important change.
RCP< LinearOpBase< Scalar > > create_DfDp_op(int l) const
virtual RCP< LinearOpBase< Scalar > > create_hess_g_xx(int j) const
virtual RCP< LinearOpBase< Scalar > > create_hess_g_xp(int j, int l) const
Pure abstract base interface for evaluating a stateless "model" that can be mapped into a number of d...
Abstract interface for objects that represent a space for vectors.
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
bool is_null(const boost::shared_ptr< T > &p)