Thyra Version of the Day
Loading...
Searching...
No Matches
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
29namespace Thyra {
30
31
230template<class Scalar>
232 : virtual public ModelEvaluatorDelegatorBase<Scalar>
233 , virtual public Teuchos::ParameterListAcceptor
234{
235public:
236
239
242
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
324private:
325
328
330 ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const;
332 void evalModelImpl(
335 ) const;
336
338
339private:
340
341 // ////////////////////////////////
342 // Private data members
343
344 mutable RCP<const Teuchos::ParameterList> validParamList_;
346
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
407template<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
427template<class Scalar>
428const std::string
430= "Observation Index";
431
432template<class Scalar>
433const int
435= -1;
436
437
438template<class Scalar>
439const std::string
441= "Parameter Subvector Ordinal";
442
443template<class Scalar>
444const int
446= 0;
447
448
449template<class Scalar>
450const std::string
452= "Observation Multiplier";
453
454template<class Scalar>
455const double
457= 1.0;
458
459
460template<class Scalar>
461const std::string
463= "Observation Target Vector";
464
465
466template<class Scalar>
467const std::string
469= "Observation Target as Parameter";
470
471template<class Scalar>
472const bool
474= false;
475
476
477template<class Scalar>
478const std::string
480= "Observation Pass Through";
481
482template<class Scalar>
483const bool
485= false;
486
487
488template<class Scalar>
489const std::string
491= "Parameter Multiplier";
492
493template<class Scalar>
494const double
496= 1e-6;
497
498
499template<class Scalar>
500const std::string
502= "Parameter Base Vector";
503
504
505// Constructors/initializers/accessors/utilities
506
507
508template<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
519template<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
532template<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
545template<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
637template<class Scalar>
643
644
645template<class Scalar>
648{
649 RCP<Teuchos::ParameterList> _paramList = paramList_;
650 paramList_ = Teuchos::null;
651 return _paramList;
652}
653
654
655template<class Scalar>
658{
659 return paramList_;
660}
661
662
663template<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
714template<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
726template<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
738template<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
751template<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
771template<class Scalar>
774{
775 if (prototypeOutArgs_.Np()==0)
776 initializeInArgsOutArgs();
777 return prototypeOutArgs_;
778}
779
780
781template<class Scalar>
782void 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)
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
1217template<class Scalar>
1218void 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
1227template<class Scalar>
1228void 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
1263template<class Scalar>
1264RCP<const VectorSpaceBase<Scalar> >
1265DefaultInverseModelEvaluator<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
T * get() const
This class wraps any ModelEvaluator object and adds a simple, but fairly general, inverse response fu...
RCP< const VectorSpaceBase< Scalar > > get_p_space(int l) const
STANDARD_CONST_COMPOSITION_MEMBERS(VectorBase< Scalar >, observationTarget)
Observation target vector ot.
STANDARD_CONST_COMPOSITION_MEMBERS(LinearOpBase< Scalar >, observationMatchWeightingOp)
Observation match weighting operator Q_o.
STANDARD_NONCONST_COMPOSITION_MEMBERS(MultiVectorFileIOBase< Scalar >, observationTargetIO)
MultiVectorFileIOBase object used to read the observation target vector ot as directed by the paramet...
void initialize(const RCP< ModelEvaluator< Scalar > > &thyraModel)
RCP< const VectorSpaceBase< Scalar > > get_g_space(int j) const
STANDARD_CONST_COMPOSITION_MEMBERS(LinearOpBase< Scalar >, parameterRegularizationWeightingOp)
Parameter regulization weighting operator Q_p.
RCP< const Teuchos::ParameterList > getParameterList() const
RCP< const Teuchos::ParameterList > getValidParameters() const
STANDARD_NONCONST_COMPOSITION_MEMBERS(MultiVectorFileIOBase< Scalar >, parameterBaseIO)
MultiVectorFileIOBase object used to read the parameter base vector pt as directed by the parameter l...
RCP< DefaultInverseModelEvaluator< Scalar > > defaultInverseModelEvaluator(const RCP< ModelEvaluator< Scalar > > &thyraModel)
Non-member constructor.
void setParameterList(RCP< Teuchos::ParameterList > const &paramList)
ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
STANDARD_CONST_COMPOSITION_MEMBERS(VectorBase< Scalar >, parameterBase)
Parameter base vector pt.
Base class for all linear operators.
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.
This is a base class that delegetes almost all function to a wrapped model evaluator object.
void initialize(const RCP< ModelEvaluator< Scalar > > &model)
Initialize given a non-const model evaluator.
Pure abstract base interface for evaluating a stateless "model" that can be mapped into a number of d...
Abstract strategy interface for reading and writing (multi)vector objects to and from files.
Concrete utility class that an ANA can use for reading in a (multi)vector as directed by a parameter ...
Abstract interface for finite-dimensional dense vectors.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
bool is_null(const std::shared_ptr< T > &p)
bool nonnull(const std::shared_ptr< T > &p)
#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.
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
@ NOTRANS
Use the non-transposed operator.
@ CONJTRANS
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types).
T_To & dyn_cast(T_From &from)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)