Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_DefaultInverseModelEvaluator.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_DEFAUL_INVERSE_MODEL_EVALUATOR_HPP
11 #define THYRA_DEFAUL_INVERSE_MODEL_EVALUATOR_HPP
12 
13 
14 #include "Thyra_ModelEvaluatorDelegatorBase.hpp"
15 #include "Thyra_ModelEvaluatorHelpers.hpp"
16 #include "Thyra_DetachedVectorView.hpp"
17 #include "Thyra_ParameterDrivenMultiVectorInput.hpp"
18 #include "Thyra_VectorSpaceFactoryBase.hpp"
19 #include "Thyra_MultiVectorStdOps.hpp"
20 #include "Thyra_AssertOp.hpp"
21 #include "Teuchos_StandardMemberCompositionMacros.hpp"
22 #include "Teuchos_StandardCompositionMacros.hpp"
23 #include "Teuchos_ParameterListAcceptor.hpp"
24 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
25 #include "Teuchos_StandardParameterEntryValidators.hpp"
26 #include "Teuchos_Time.hpp"
27 
28 
29 namespace Thyra {
30 
31 
230 template<class Scalar>
232  : virtual public ModelEvaluatorDelegatorBase<Scalar>
233  , virtual public Teuchos::ParameterListAcceptor
234 {
235 public:
236 
239 
242 
244  STANDARD_CONST_COMPOSITION_MEMBERS( LinearOpBase<Scalar>, observationMatchWeightingOp );
245 
247  STANDARD_CONST_COMPOSITION_MEMBERS( LinearOpBase<Scalar>, parameterRegularizationWeightingOp );
248 
252 
256 
259 
262 
264  void initialize(
265  const RCP<ModelEvaluator<Scalar> > &thyraModel
266  );
267 
269  void uninitialize(
270  RCP<ModelEvaluator<Scalar> > *thyraModel
271  );
272 
274 
277 
285  void setParameterList(RCP<Teuchos::ParameterList> const& paramList);
301 
303 
306 
308  std::string description() const;
309 
311 
314 
321 
323 
324 private:
325 
328 
330  ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const;
332  void evalModelImpl(
335  ) const;
336 
338 
339 private:
340 
341  // ////////////////////////////////
342  // Private data members
343 
344  mutable RCP<const Teuchos::ParameterList> validParamList_;
345  RCP<Teuchos::ParameterList> paramList_;
346 
347  RCP<const VectorSpaceBase<Scalar> > inv_g_space_;
348 
349  mutable ModelEvaluatorBase::InArgs<Scalar> prototypeInArgs_;
350  mutable ModelEvaluatorBase::OutArgs<Scalar> prototypeOutArgs_;
351  mutable bool usingObservationTargetAsParameter_;
352 
353  int obs_idx_;
354  int p_idx_;
355 
356 
357  double observationMultiplier_;
358  double parameterMultiplier_;
359 
360  bool observationTargetAsParameter_;
361 
362  bool observationPassThrough_;
363 
364  Teuchos::EVerbosityLevel localVerbLevel_;
365 
366  mutable ParameterDrivenMultiVectorInput<Scalar> observationTargetReader_;
367  mutable ParameterDrivenMultiVectorInput<Scalar> parameterBaseReader_;
368 
369  static const std::string ObservationIndex_name_;
370  static const int ObservationIndex_default_;
371 
372  static const std::string ParameterSubvectorIndex_name_;
373  static const int ParameterSubvectorIndex_default_;
374 
375  static const std::string ObservationMultiplier_name_;
376  static const double ObservationMultiplier_default_;
377 
378  static const std::string ObservationTargetVector_name_;
379 
380  static const std::string ObservationTargetAsParameter_name_;
381  static const bool ObservationTargetAsParameter_default_;
382 
383  static const std::string ObservationPassThrough_name_;
384  static const bool ObservationPassThrough_default_;
385 
386  static const std::string ParameterMultiplier_name_;
387  static const double ParameterMultiplier_default_;
388 
389  static const std::string ParameterBaseVector_name_;
390 
391  // ////////////////////////////////
392  // Private member functions
393 
394  void initializeDefaults();
395 
396  void initializeInArgsOutArgs() const;
397 
398  RCP<const VectorSpaceBase<Scalar> > get_obs_space() const;
399 
400 };
401 
402 
407 template<class Scalar>
410  const RCP<ModelEvaluator<Scalar> > &thyraModel
411  )
412 {
415  inverseModel->initialize(thyraModel);
416  return inverseModel;
417 }
418 
419 
420 // /////////////////////////////////
421 // Implementations
422 
423 
424 // Static data members
425 
426 
427 template<class Scalar>
428 const std::string
430 = "Observation Index";
431 
432 template<class Scalar>
433 const int
435 = -1;
436 
437 
438 template<class Scalar>
439 const std::string
441 = "Parameter Subvector Ordinal";
442 
443 template<class Scalar>
444 const int
446 = 0;
447 
448 
449 template<class Scalar>
450 const std::string
452 = "Observation Multiplier";
453 
454 template<class Scalar>
455 const double
457 = 1.0;
458 
459 
460 template<class Scalar>
461 const std::string
463 = "Observation Target Vector";
464 
465 
466 template<class Scalar>
467 const std::string
469 = "Observation Target as Parameter";
470 
471 template<class Scalar>
472 const bool
474 = false;
475 
476 
477 template<class Scalar>
478 const std::string
480 = "Observation Pass Through";
481 
482 template<class Scalar>
483 const bool
485 = false;
486 
487 
488 template<class Scalar>
489 const std::string
491 = "Parameter Multiplier";
492 
493 template<class Scalar>
494 const double
496 = 1e-6;
497 
498 
499 template<class Scalar>
500 const std::string
502 = "Parameter Base Vector";
503 
504 
505 // Constructors/initializers/accessors/utilities
506 
507 
508 template<class Scalar>
510  :usingObservationTargetAsParameter_(false), obs_idx_(-1),p_idx_(0),
511  observationTargetAsParameter_(false),
512  observationPassThrough_(ObservationPassThrough_default_),
513  localVerbLevel_(Teuchos::VERB_DEFAULT),
514  observationMultiplier_(0.0),
515  parameterMultiplier_(0.0)
516 {}
517 
518 
519 template<class Scalar>
521  const RCP<ModelEvaluator<Scalar> > &thyraModel
522  )
523 {
525  inv_g_space_= thyraModel->get_x_space()->smallVecSpcFcty()->createVecSpc(1);
526  // Get ready for reinitalization
527  prototypeInArgs_ = ModelEvaluatorBase::InArgs<Scalar>();
528  prototypeOutArgs_ = ModelEvaluatorBase::OutArgs<Scalar>();
529 }
530 
531 
532 template<class Scalar>
534  RCP<ModelEvaluator<Scalar> > *thyraModel
535  )
536 {
537  if(thyraModel) *thyraModel = this->getUnderlyingModel();
539 }
540 
541 
542 // Overridden from Teuchos::ParameterListAcceptor
543 
544 
545 template<class Scalar>
547  RCP<Teuchos::ParameterList> const& paramList
548  )
549 {
550 
551  using Teuchos::Array;
552  using Teuchos::getParameterPtr;
553  using Teuchos::rcp;
554  using Teuchos::sublist;
555 
556  // Validate and set the parameter list
557  TEUCHOS_TEST_FOR_EXCEPT(0==paramList.get());
558  paramList->validateParameters(*getValidParameters(),0);
559  paramList_ = paramList;
560 
561  // Parameters for observation matching term
562  obs_idx_ = paramList_->get(
563  ObservationIndex_name_,ObservationIndex_default_);
564  observationPassThrough_ = paramList_->get(
565  ObservationPassThrough_name_, ObservationPassThrough_default_ );
566 #ifdef TEUCHOS_DEBUG
568  ( obs_idx_ < 0 && observationPassThrough_ ), std::logic_error,
569  "Error, the observation function index obs_idx = " << obs_idx_ << " is not\n"
570  "allowed when the observation is simply passed through!"
571  );
572 #endif
573  observationMultiplier_ = paramList_->get(
574  ObservationMultiplier_name_,ObservationMultiplier_default_);
575  if (!ObservationPassThrough_default_) {
576  observationTargetAsParameter_ = paramList_->get(
577  ObservationTargetAsParameter_name_, ObservationTargetAsParameter_default_ );
578  if(get_observationTargetIO().get()) {
579  observationTargetReader_.set_vecSpc(get_obs_space());
581  vots_observationTargetReader(
582  rcp(&observationTargetReader_,false)
583  ,this->getOStream(),this->getVerbLevel()
584  );
585  observationTargetReader_.setParameterList(
586  sublist(paramList_,ObservationTargetVector_name_)
587  );
589  observationTarget;
590  observationTargetReader_.readVector(
591  "observation target vector",&observationTarget);
592  observationTarget_ = observationTarget;
593  }
594  }
595  else {
596  observationTargetAsParameter_ = false;
597  observationTarget_ = Teuchos::null;
598  }
599 
600  // Parameters for parameter matching term
601  p_idx_ = paramList_->get(
602  ParameterSubvectorIndex_name_,ParameterSubvectorIndex_default_);
603  parameterMultiplier_ = paramList_->get(
604  ParameterMultiplier_name_,ParameterMultiplier_default_);
605  if(get_parameterBaseIO().get()) {
606  parameterBaseReader_.set_vecSpc(this->get_p_space(p_idx_));
608  vots_parameterBaseReader(
609  rcp(&parameterBaseReader_,false)
610  ,this->getOStream(),this->getVerbLevel()
611  );
612  parameterBaseReader_.setParameterList(
613  sublist(paramList_,ParameterBaseVector_name_)
614  );
616  parameterBase;
617  parameterBaseReader_.readVector(
618  "parameter base vector",&parameterBase);
619  parameterBase_ = parameterBase;
620  }
621 
622  // Verbosity settings
623  localVerbLevel_ = this->readLocalVerbosityLevelValidatedParameter(*paramList_);
624  Teuchos::readVerboseObjectSublist(&*paramList_,this);
625 
626 #ifdef TEUCHOS_DEBUG
627  paramList_->validateParameters(*getValidParameters(),0);
628 #endif // TEUCHOS_DEBUG
629 
630  // Get ready for reinitalization
631  prototypeInArgs_ = ModelEvaluatorBase::InArgs<Scalar>();
632  prototypeOutArgs_ = ModelEvaluatorBase::OutArgs<Scalar>();
633 
634 }
635 
636 
637 template<class Scalar>
640 {
641  return paramList_;
642 }
643 
644 
645 template<class Scalar>
648 {
649  RCP<Teuchos::ParameterList> _paramList = paramList_;
650  paramList_ = Teuchos::null;
651  return _paramList;
652 }
653 
654 
655 template<class Scalar>
658 {
659  return paramList_;
660 }
661 
662 
663 template<class Scalar>
666 {
667  if(validParamList_.get()==NULL) {
670  pl->set( ObservationIndex_name_,ObservationIndex_default_,
671  "The index of the observation function, obs_idx.\n"
672  "If obs_idx < 0, then the observation will be the state vector x.\n"
673  "If obs_idx >= 0, then the observation will be the response function g(obs_idx)."
674  );
675  pl->set( ParameterSubvectorIndex_name_,ParameterSubvectorIndex_default_,
676  "The index of the parameter subvector that will be used in the\n"
677  "regularization term."
678  );
679  pl->set( ObservationMultiplier_name_,ObservationMultiplier_default_,
680  "observationMultiplier"
681  );
682  if(this->get_observationTargetIO().get())
683  observationTargetReader_.set_fileIO(this->get_observationTargetIO());
684  pl->sublist(ObservationTargetVector_name_).setParameters(
685  *observationTargetReader_.getValidParameters()
686  );
687  pl->set( ObservationPassThrough_name_, ObservationPassThrough_default_,
688  "If true, then the observation will just be used instead of the least-squares\n"
689  "function. This allows you to add a parameter regularization term to any existing\n"
690  "response function!"
691  );
692  pl->set( ObservationTargetAsParameter_name_, ObservationTargetAsParameter_default_,
693  "If true, then a parameter will be accepted for the state observation vector\n"
694  "to allow it to be set by an external client through the InArgs object."
695  );
696  pl->set( ParameterMultiplier_name_,ParameterMultiplier_default_,
697  "parameterMultiplier" );
698  if(this->get_parameterBaseIO().get())
699  parameterBaseReader_.set_fileIO(this->get_parameterBaseIO());
700  pl->sublist(ParameterBaseVector_name_).setParameters(
701  *parameterBaseReader_.getValidParameters()
702  );
703  this->setLocalVerbosityLevelValidatedParameter(&*pl);
704  Teuchos::setupVerboseObjectSublist(&*pl);
705  validParamList_ = pl;
706  }
707  return validParamList_;
708 }
709 
710 
711 // Overridden from ModelEvaulator.
712 
713 
714 template<class Scalar>
717 {
718  if (prototypeInArgs_.Np()==0)
719  initializeInArgsOutArgs();
720  if ( l == prototypeInArgs_.Np()-1 && usingObservationTargetAsParameter_ )
721  return get_obs_space();
722  return this->getUnderlyingModel()->get_p_space(l);
723 }
724 
725 
726 template<class Scalar>
729 {
730  if (prototypeOutArgs_.Np()==0)
731  initializeInArgsOutArgs();
732  if (j==prototypeOutArgs_.Ng()-1)
733  return inv_g_space_;
734  return this->getUnderlyingModel()->get_g_space(j);
735 }
736 
737 
738 template<class Scalar>
741 {
742  if (prototypeInArgs_.Np()==0)
743  initializeInArgsOutArgs();
744  return prototypeInArgs_;
745 }
746 
747 
748 // Public functions overridden from Teuchos::Describable
749 
750 
751 template<class Scalar>
753 {
755  thyraModel = this->getUnderlyingModel();
756  std::ostringstream oss;
757  oss << "Thyra::DefaultInverseModelEvaluator{";
758  oss << "thyraModel=";
759  if(thyraModel.get())
760  oss << "\'"<<thyraModel->description()<<"\'";
761  else
762  oss << "NULL";
763  oss << "}";
764  return oss.str();
765 }
766 
767 
768 // Private functions overridden from ModelEvaulatorDefaultBase
769 
770 
771 template<class Scalar>
774 {
775  if (prototypeOutArgs_.Np()==0)
776  initializeInArgsOutArgs();
777  return prototypeOutArgs_;
778 }
779 
780 
781 template<class Scalar>
782 void DefaultInverseModelEvaluator<Scalar>::evalModelImpl(
783  const ModelEvaluatorBase::InArgs<Scalar> &inArgs,
784  const ModelEvaluatorBase::OutArgs<Scalar> &outArgs
785  ) const
786 {
787 
788  using std::endl;
789  using Teuchos::rcp;
790  using Teuchos::rcp_const_cast;
791  using Teuchos::rcp_dynamic_cast;
792  using Teuchos::OSTab;
794  typedef typename ST::magnitudeType ScalarMag;
795  typedef ModelEvaluatorBase MEB;
796 
797  THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_LOCALVERBLEVEL_BEGIN(
798  "Thyra::DefaultInverseModelEvaluator",inArgs,outArgs,localVerbLevel_
799  );
800 
801  const bool trace = out.get() && includesVerbLevel(localVerbLevel,Teuchos::VERB_LOW);
802  const bool print_p = out.get() && includesVerbLevel(localVerbLevel,Teuchos::VERB_MEDIUM);
803  const bool print_x = out.get() && includesVerbLevel(localVerbLevel,Teuchos::VERB_EXTREME);
804  const bool print_o = print_x;
805 
806  //
807  // A) See what needs to be computed
808  //
809 
810  const RCP<VectorBase<Scalar> >
811  g_inv_out = outArgs.get_g(outArgs.Ng()-1);
812  const RCP<MultiVectorBase<Scalar> >
813  DgDx_inv_trans_out = get_mv(
814  outArgs.get_DgDx(outArgs.Ng()-1), "DgDx", MEB::DERIV_TRANS_MV_BY_ROW
815  );
816  const RCP<MultiVectorBase<Scalar> >
817  DgDp_inv_trans_out = get_mv(
818  outArgs.get_DgDp(outArgs.Ng()-1,p_idx_), "DgDp", MEB::DERIV_TRANS_MV_BY_ROW
819  );
820  const bool computeInverseFunction = ( nonnull(g_inv_out)
821  || nonnull(DgDx_inv_trans_out) || nonnull(DgDp_inv_trans_out) );
822 
823  //
824  // B) Compute all of the needed functions from the base model
825  //
826 
827  if(trace)
828  *out << "\nComputing the base point and the observation(s) ...\n";
829 
830  MEB::InArgs<Scalar> wrappedInArgs = thyraModel->createInArgs();
831  wrappedInArgs.setArgs(inArgs,true);
832  MEB::OutArgs<Scalar> wrappedOutArgs = thyraModel->createOutArgs();
833  wrappedOutArgs.setArgs(outArgs,true);
834  RCP<VectorBase<Scalar> > wrapped_o;
835  MEB::Derivative<Scalar> wrapped_DoDx;
836  MEB::Derivative<Scalar> wrapped_DoDp_trans;
837  if( obs_idx_ >= 0 && computeInverseFunction )
838  {
839  wrapped_o = createMember(thyraModel->get_g_space(obs_idx_));
840  wrappedOutArgs.set_g(obs_idx_,wrapped_o);
841  if (nonnull(DgDx_inv_trans_out)) {
842  if (!observationPassThrough_)
843  wrapped_DoDx = thyraModel->create_DgDx_op(obs_idx_);
844  else
845  wrapped_DoDx = Thyra::create_DgDx_mv(
846  *thyraModel, obs_idx_, MEB::DERIV_TRANS_MV_BY_ROW );
847  wrappedOutArgs.set_DgDx(obs_idx_,wrapped_DoDx);
848  }
849  if (nonnull(DgDp_inv_trans_out)) {
850  wrapped_DoDp_trans = create_DgDp_mv(
851  *thyraModel, obs_idx_, p_idx_, MEB::DERIV_TRANS_MV_BY_ROW
852  );
853  wrappedOutArgs.set_DgDp(obs_idx_,p_idx_,wrapped_DoDp_trans);
854  }
855  // 2007/07/28: rabartl: Above, we really should check if these output
856  // arguments have already been set by the client. If they are, then we
857  // need to make sure that they are of the correct form or we need to throw
858  // an exception!
859  }
860 
861  if (!wrappedOutArgs.isEmpty()) {
862  thyraModel->evalModel(wrappedInArgs,wrappedOutArgs);
863  }
864  else {
865  if(trace)
866  *out << "\nSkipping the evaluation of the underlying model since "
867  << "there is nothing to compute ...\n";
868  }
869 
870  bool failed = wrappedOutArgs.isFailed();
871 
872  //
873  // C) Assemble the final observation and paramter terms
874  //
875 
876  if ( !failed && computeInverseFunction ) {
877 
878  //
879  // Compute the inverse response function and its derivatives
880  //
881 
882  RCP<const VectorBase<Scalar> >
883  x_in = inArgs.get_x(),
884  p_in = inArgs.get_p(p_idx_);
885 
886  const MEB::InArgs<Scalar> nominalValues = this->getNominalValues();
887  RCP<const VectorBase<Scalar> >
888  x = ( !is_null(x_in) ? x_in : nominalValues.get_x().assert_not_null() ),
889  p = ( !is_null(p_in) ? p_in : nominalValues.get_p(p_idx_).assert_not_null() );
890 
891  const RCP<const VectorSpaceBase<Scalar> >
892  o_space = get_obs_space(),
893  p_space = this->get_p_space(p_idx_);
894 
895  const Ordinal
896  no = o_space->dim(),
897  np = p_space->dim();
898 
899  if (trace)
900  *out << "\nno = " << no
901  << "\nnp = " << np
902  << endl;
903 
904 #ifdef TEUCHOS_DEBUG
906  observationPassThrough_ && no != 1, std::logic_error,
907  "Error, the observation function dimension no="<<no<<" > 1 is not allowed"
908  " when the observation is passed through as the observation matching term!"
909  );
910 #endif
911 
912  // Compute diff_o if needed
913  RCP<const VectorBase<Scalar> > o;
914  RCP<VectorBase<Scalar> > diff_o;
915  if( !observationPassThrough_ && ( nonnull(g_inv_out) || nonnull(DgDx_inv_trans_out) ) )
916  {
917  if (obs_idx_ < 0 ) o = x; else o = wrapped_o; // can't use ( test ? x : wrapped_o )!
918  if(trace) *out << "\n||o||inf = " << norm_inf(*o) << endl;
919  if (print_o) *out << "\no = " << *o;
920  diff_o = createMember(o_space);
921  RCP<const VectorBase<Scalar> >
922  observationTarget
923  = ( observationTargetAsParameter_
924  ? inArgs.get_p(inArgs.Np()-1)
925  : Teuchos::null
926  );
927  if (is_null(observationTarget) ) {
928  observationTarget = observationTarget_;
929  if (trace)
930  *out << "\n||ot||inf = " << norm_inf(*observationTarget) << endl;
931  if (print_o)
932  *out << "\not = " << *observationTarget;
933  }
934  if (!is_null(observationTarget)) {
935  V_VmV( diff_o.ptr(), *o, *observationTarget );
936  }
937  else {
938  assign( diff_o.ptr(), *o );
939  }
940  if(trace) {
941  *out << "\n||diff_o||inf = " << norm_inf(*diff_o) << endl;
942  }
943  if (print_o) {
944  *out << "\ndiff_o = " << *diff_o;
945  }
946  }
947 
948  // Compute diff_p if needed
949  RCP<VectorBase<Scalar> > diff_p;
950  if ( nonnull(g_inv_out) || nonnull(DgDp_inv_trans_out)) {
951  if(trace) *out << "\n||p||inf = " << norm_inf(*p) << endl;
952  if(print_p) *out << "\np = " << Teuchos::describe(*p,Teuchos::VERB_EXTREME);
953  diff_p = createMember(p_space);
954  if (!is_null(parameterBase_) ) {
955  if(trace) *out << "\n||pt||inf = " << norm_inf(*parameterBase_) << endl;
956  if(print_p) {
957  *out << "\npt = "
958  << Teuchos::describe(*parameterBase_,Teuchos::VERB_EXTREME);
959  }
960  V_VmV( diff_p.ptr(), *p, *parameterBase_ );
961  }
962  else {
963  assign( diff_p.ptr(), *p );
964  }
965  if(trace) {*out << "\n||diff_p|| = " << norm(*diff_p) << endl;}
966  if(print_p) {
967  *out << "\ndiff_p = "
968  << Teuchos::describe(*diff_p, Teuchos::VERB_EXTREME);
969  }
970  }
971 
972 
973  // Get and check Q_o and Q_p
974 
975  RCP<const LinearOpBase<Scalar> >
976  Q_o = this->get_observationMatchWeightingOp(),
977  Q_p = this->get_parameterRegularizationWeightingOp();
978 
979 #ifdef TEUCHOS_DEBUG
980  if (!is_null(Q_o)) {
982  "Thyra::DefaultInverseModelEvaluator::evalModel(...)",
983  *Q_o->range(), *o_space
984  );
986  "Thyra::DefaultInverseModelEvaluator::evalModel(...)",
987  *Q_o->domain(), *o_space
988  );
989  }
990  if (!is_null(Q_p)) {
992  "Thyra::DefaultInverseModelEvaluator::evalModel(...)",
993  *Q_p->range(), *p_space
994  );
996  "Thyra::DefaultInverseModelEvaluator::evalModel(...)",
997  *Q_p->domain(), *p_space
998  );
999  }
1000  // Note, we have not proved that Q_o and Q_p are s.p.d. but at least we
1001  // have established that that have the right range and domain spaces!
1002 #endif
1003 
1004  // Compute Q_o * diff_o
1005  RCP<VectorBase<Scalar> > Q_o_diff_o;
1006  if ( !is_null(Q_o) && !is_null(diff_o) ) {
1007  Q_o_diff_o = createMember(Q_o->range()); // Should be same as domain!
1008  apply( *Q_o, NOTRANS, *diff_o, Q_o_diff_o.ptr() );
1009  }
1010 
1011  // Compute Q_p * diff_p
1012  RCP<VectorBase<Scalar> > Q_p_diff_p;
1013  if ( !is_null(Q_p) && !is_null(diff_p) ) {
1014  Q_p_diff_p = createMember(Q_p->range()); // Should be same as domain!
1015  apply( *Q_p, NOTRANS, *diff_p, Q_p_diff_p.ptr() );
1016  }
1017 
1018  // Compute g_inv(x,p)
1019  if (nonnull(g_inv_out)) {
1020  if(trace)
1021  *out << "\nComputing inverse response function ginv = g(Np-1) ...\n";
1022  const Scalar observationTerm
1023  = ( observationPassThrough_
1024  ? get_ele(*wrapped_o,0) // ToDo; Verify that this is already a scalar
1025  : ( observationMultiplier_ != ST::zero()
1026  ? ( !is_null(Q_o)
1027  ? observationMultiplier_*0.5*dot(*diff_o,*Q_o_diff_o)
1028  : observationMultiplier_*(0.5/no)*dot(*diff_o,*diff_o)
1029  )
1030  : ST::zero()
1031  )
1032  );
1033  const Scalar parameterTerm
1034  = ( parameterMultiplier_ != ST::zero()
1035  ? ( !is_null(Q_p)
1036  ? parameterMultiplier_*0.5*dot(*diff_p,*Q_p_diff_p)
1037  : parameterMultiplier_*(0.5/np)*dot(*diff_p,*diff_p)
1038  )
1039  : ST::zero()
1040  );
1041  const Scalar g_inv_val = observationTerm+parameterTerm;
1042  if(trace)
1043  *out
1044  << "\nObservation matching term of ginv = g(Np-1):"
1045  << "\n observationMultiplier = " << observationMultiplier_
1046  << "\n observationMultiplier*observationMatch(x,p) = " << observationTerm
1047  << "\nParameter regularization term of ginv = g(Np-1):"
1048  << "\n parameterMultiplier = " << parameterMultiplier_
1049  << "\n parameterMultiplier*parameterRegularization(p) = " << parameterTerm
1050  << "\nginv = " << g_inv_val
1051  << "\n";
1052  set_ele(0, observationTerm+parameterTerm, g_inv_out.ptr());
1053  }
1054 
1055  // Compute d(g_inv)/d(x)^T
1056  if (nonnull(DgDx_inv_trans_out)) {
1057  if(trace)
1058  *out << "\nComputing inverse response function derivative DginvDx^T:\n";
1059  if (!observationPassThrough_) {
1060  if( obs_idx_ < 0 ) {
1061  if (!is_null(Q_o)) {
1062  if (trace)
1063  *out << "\nDginvDx^T = observationMultiplier * Q_o * diff_o ...\n";
1064  V_StV(
1065  DgDx_inv_trans_out->col(0).ptr(),
1066  observationMultiplier_,
1067  *Q_o_diff_o
1068  );
1069  }
1070  else {
1071  if (trace)
1072  *out << "\nDginvDx^T = observationMultiplier * (1/no) * diff_o ...\n";
1073  V_StV(
1074  DgDx_inv_trans_out->col(0).ptr(),
1075  Scalar(observationMultiplier_*(1.0/no)),
1076  *diff_o
1077  );
1078  }
1079  }
1080  else {
1081  //if (trace)
1082  // *out << "\n||DoDx^T||inf = " << norms_inf(*wrapped_DoDx.getMultiVector()) << endl;
1083  if (print_o && print_x)
1084  *out << "\nDoDx = " << *wrapped_DoDx.getLinearOp();
1085  if (!is_null(Q_o)) {
1086  if (trace)
1087  *out << "\nDginvDx^T = observationMultiplier * DoDx^T * Q_o * diff_o ...\n";
1088  apply(
1089  *wrapped_DoDx.getLinearOp(), CONJTRANS,
1090  *Q_o_diff_o,
1091  DgDx_inv_trans_out->col(0).ptr(),
1092  observationMultiplier_
1093  );
1094  }
1095  else {
1096  if (trace)
1097  *out << "\nDginvDx^T = (observationMultiplier*(1/no)) * DoDx^T * diff_o ...\n";
1098  apply(
1099  *wrapped_DoDx.getLinearOp(), CONJTRANS,
1100  *diff_o,
1101  DgDx_inv_trans_out->col(0).ptr(),
1102  Scalar(observationMultiplier_*(1.0/no))
1103  );
1104  }
1105  }
1106  }
1107  else {
1108  if (trace)
1109  *out << "\nDginvDx^T = observationMultiplier * DoDx^T ...\n";
1110  V_StV(
1111  DgDx_inv_trans_out->col(0).ptr(), observationMultiplier_,
1112  *wrapped_DoDx.getMultiVector()->col(0)
1113  );
1114  }
1115  if(trace)
1116  *out << "\n||DginvDx^T||inf = " << norms_inf(*DgDx_inv_trans_out) << "\n";
1117  if (print_x)
1118  *out << "\nDginvDx^T = " << *DgDx_inv_trans_out;
1119  }
1120 
1121  // Compute d(g_inv)/d(p)^T
1122  if (nonnull(DgDp_inv_trans_out)) {
1123  if(trace)
1124  *out << "\nComputing inverse response function derivative DginvDp^T ...\n";
1125  if (obs_idx_ >= 0) {
1126  if (trace)
1127  *out << "\n||DoDp^T|| = " << norms_inf(*wrapped_DoDp_trans.getMultiVector()) << endl;
1128  if (print_p)
1129  *out << "\nDoDp^T = " << Teuchos::describe(*wrapped_DoDp_trans.getMultiVector(),Teuchos::VERB_EXTREME);
1130  }
1131  if(trace)
1132  *out << "\nDginvDp^T = 0 ...\n";
1133  assign( DgDp_inv_trans_out->col(0).ptr(), ST::zero() );
1134  // DgDp^T += observationMultiplier * d(observationMatch)/d(p)^T
1135  if (!observationPassThrough_) {
1136  if ( obs_idx_ >= 0 ) {
1137  if ( !is_null(Q_o) ) {
1138  if(trace)
1139  *out << "\nDginvDp^T += observationMultiplier* * (DoDp^T) * Q_o * diff_o ...\n";
1140  apply(
1141  *wrapped_DoDp_trans.getMultiVector(), NOTRANS,
1142  *Q_o_diff_o,
1143  DgDp_inv_trans_out->col(0).ptr(),
1144  Scalar(observationMultiplier_*(1.0/no)),
1145  ST::one()
1146  );
1147  }
1148  else {
1149  if(trace)
1150  *out << "\nDgDp^T += observationMultiplier* * (DoDp^T) * Q_o * diff_o ...\n";
1151  apply(
1152  *wrapped_DoDp_trans.getMultiVector(), NOTRANS,
1153  *diff_o,
1154  DgDp_inv_trans_out->col(0).ptr(),
1155  Scalar(observationMultiplier_*(1.0/no)),
1156  ST::one()
1157  );
1158  }
1159  if(trace)
1160  *out << "\n||DginvDp^T||inf = " << norms_inf(*DgDp_inv_trans_out) << "\n";
1161  if (print_p)
1162  *out << "\nDginvDp^T = " << *DgDp_inv_trans_out;
1163  }
1164  else {
1165  // d(observationMatch)/d(p)^T = 0, nothing to do!
1166  }
1167  }
1168  else {
1169  if(trace)
1170  *out << "\nDginvDp^T += (observationMultiplier*(1/no)) * (DoDp^T) * diff_o ...\n";
1171  Vp_StV(
1172  DgDp_inv_trans_out->col(0).ptr(), observationMultiplier_,
1173  *wrapped_DoDp_trans.getMultiVector()->col(0)
1174  );
1175 
1176  }
1177  // DgDp^T += parameterMultiplier * d(parameterRegularization)/d(p)^T
1178  if( parameterMultiplier_ != ST::zero() ) {
1179  if ( !is_null(Q_p) ) {
1180  if(trace)
1181  *out << "\nDginvDp^T += parameterMultiplier * Q_p * diff_p ...\n";
1182  Vp_StV(
1183  DgDp_inv_trans_out->col(0).ptr(),
1184  parameterMultiplier_,
1185  *Q_p_diff_p
1186  );
1187  }
1188  else {
1189  if(trace)
1190  *out << "\nDginvDp^T += (parameterMultiplier*(1.0/np)) * diff_p ...\n";
1191  Vp_StV(
1192  DgDp_inv_trans_out->col(0).ptr(),
1193  Scalar(parameterMultiplier_*(1.0/np)),
1194  *diff_p
1195  );
1196  }
1197  if(trace)
1198  *out << "\n||DginvDp^T||inf = " << norms_inf(*DgDp_inv_trans_out) << "\n";
1199  if (print_p)
1200  *out << "\nDginvDp^T = " << *DgDp_inv_trans_out;
1201  }
1202  else {
1203  // This term is zero so there is nothing to do!
1204  }
1205  }
1206 
1207  }
1208 
1209  THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END();
1210 
1211 }
1212 
1213 
1214 // private
1215 
1216 
1217 template<class Scalar>
1218 void DefaultInverseModelEvaluator<Scalar>::initializeDefaults()
1219 {
1220  obs_idx_ = ObservationIndex_default_;
1221  p_idx_ = ParameterSubvectorIndex_default_;
1222  observationMultiplier_ = ObservationMultiplier_default_;
1223  parameterMultiplier_ = ParameterMultiplier_default_;
1224 }
1225 
1226 
1227 template<class Scalar>
1228 void DefaultInverseModelEvaluator<Scalar>::initializeInArgsOutArgs() const
1229 {
1230 
1231  typedef ModelEvaluatorBase MEB;
1232 
1233  const RCP<const ModelEvaluator<Scalar> >
1234  thyraModel = this->getUnderlyingModel();
1235 
1236  const MEB::InArgs<Scalar> wrappedInArgs = thyraModel->createInArgs();
1237  const int wrapped_Np = wrappedInArgs.Np();
1238 
1239  MEB::InArgsSetup<Scalar> inArgs;
1240  inArgs.setModelEvalDescription(this->description());
1241  const bool supports_x = wrappedInArgs.supports(MEB::IN_ARG_x);
1242  usingObservationTargetAsParameter_ = ( supports_x && observationTargetAsParameter_ );
1243  inArgs.setSupports(
1244  wrappedInArgs,
1245  wrapped_Np + ( usingObservationTargetAsParameter_ ? 1 : 0 )
1246  );
1247  prototypeInArgs_ = inArgs;
1248 
1249  const MEB::OutArgs<Scalar> wrappedOutArgs = thyraModel->createOutArgs();
1250  const int wrapped_Ng = wrappedOutArgs.Ng();
1251 
1252  MEB::OutArgsSetup<Scalar> outArgs;
1253  outArgs.setModelEvalDescription(inArgs.modelEvalDescription());
1254  outArgs.set_Np_Ng( prototypeInArgs_.Np(), wrapped_Ng+1 );
1255  outArgs.setSupports(wrappedOutArgs);
1256  outArgs.setSupports(MEB::OUT_ARG_DgDx,wrapped_Ng,MEB::DERIV_TRANS_MV_BY_ROW);
1257  outArgs.setSupports(MEB::OUT_ARG_DgDp,wrapped_Ng,p_idx_,MEB::DERIV_TRANS_MV_BY_ROW);
1258  prototypeOutArgs_ = outArgs;
1259 
1260 }
1261 
1262 
1263 template<class Scalar>
1264 RCP<const VectorSpaceBase<Scalar> >
1265 DefaultInverseModelEvaluator<Scalar>::get_obs_space() const
1266 {
1267  return ( obs_idx_ < 0 ? this->get_x_space() : this->get_g_space(obs_idx_) );
1268 }
1269 
1270 
1271 } // namespace Thyra
1272 
1273 
1274 #endif // THYRA_DEFAUL_INVERSE_MODEL_EVALUATOR_HPP
Pure abstract base interface for evaluating a stateless &quot;model&quot; that can be mapped into a number of d...
#define THYRA_ASSERT_VEC_SPACES(FUNC_NAME, VS1, VS2)
This is a very useful macro that should be used to validate that two vector spaces are compatible...
bool is_null(const boost::shared_ptr< T > &p)
basic_OSTab< char > OSTab
Concrete aggregate class for all output arguments computable by a ModelEvaluator subclass object...
T & get(const std::string &name, T def_value)
This is a base class that delegetes almost all function to a wrapped model evaluator object...
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Use the non-transposed operator.
ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
void initialize(const RCP< ModelEvaluator< Scalar > > &model)
Initialize given a non-const model evaluator.
void initialize(const RCP< ModelEvaluator< Scalar > > &thyraModel)
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types)...
T * get() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
RCP< const Teuchos::ParameterList > getParameterList() const
Concrete utility class that an ANA can use for reading in a (multi)vector as directed by a parameter ...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
RCP< const VectorSpaceBase< Scalar > > get_g_space(int j) const
Abstract strategy interface for reading and writing (multi)vector objects to and from files...
Abstract interface for finite-dimensional dense vectors.
RCP< DefaultInverseModelEvaluator< Scalar > > defaultInverseModelEvaluator(const RCP< ModelEvaluator< Scalar > > &thyraModel)
Non-member constructor.
Base class for all linear operators.
STANDARD_CONST_COMPOSITION_MEMBERS(VectorBase< Scalar >, observationTarget)
Observation target vector ot.
TEUCHOSCORE_LIB_DLL_EXPORT bool includesVerbLevel(const EVerbosityLevel verbLevel, const EVerbosityLevel requestedVerbLevel, const bool isDefaultLevel=false)
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
ParameterList & setParameters(const ParameterList &source)
bool nonnull(const boost::shared_ptr< T > &p)
This class wraps any ModelEvaluator object and adds a simple, but fairly general, inverse response fu...
void setParameterList(RCP< Teuchos::ParameterList > const &paramList)
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
RCP< const VectorSpaceBase< Scalar > > get_p_space(int l) const
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
RCP< const Teuchos::ParameterList > getValidParameters() const
STANDARD_NONCONST_COMPOSITION_MEMBERS(MultiVectorFileIOBase< Scalar >, observationTargetIO)
MultiVectorFileIOBase object used to read the observation target vector ot as directed by the paramet...
Concrete aggregate class for all input arguments computable by a ModelEvaluator subclass object...