Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
Tempus_AdjointResponseTestUtils.hpp
Go to the documentation of this file.
1//@HEADER
2// *****************************************************************************
3// Tempus: Time Integration and Sensitivity Analysis Package
4//
5// Copyright 2017 NTESS and the Tempus contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8//@HEADER
9
10#ifndef TEMPUS_ADJOINT_RESPONSE_TEST_UTILS_HPP
11#define TEMPUS_ADJOINT_RESPONSE_TEST_UTILS_HPP
12
13#include <cmath>
14#include <functional>
15#include <string>
16#include <vector>
17
18#include "Teuchos_LocalTestingHelpers.hpp"
19#include "Teuchos_ParameterList.hpp"
20#include "Teuchos_XMLParameterListHelpers.hpp"
21
22#include "Thyra_DetachedMultiVectorView.hpp"
23#include "Thyra_MultiVectorStdOps.hpp"
24#include "Thyra_VectorStdOps.hpp"
25
26#include "Tempus_IntegratorAdjointSensitivity.hpp"
27
28#include "../TestModels/SinCosModel.hpp"
30
31namespace Tempus_Test {
32
41inline Teuchos::RCP<Thyra::MultiVectorBase<double> >
43 const std::string& responseType,
44 const double t0, const double tf,
45 const std::vector<double>& responseTimes)
46{
47 const int num_param = model.get_p_space(0)->dim();
48 Teuchos::RCP<Thyra::MultiVectorBase<double> > dJdp =
49 Thyra::createMembers(model.get_x_space(), num_param);
50 Thyra::assign(dJdp.ptr(), 0.0);
51
52 std::vector<double> times, weights;
53 if (responseType == "Time Integral") {
54 const double nodes[5] = {-0.9061798459386640, -0.5384693101056831, 0.0,
55 0.5384693101056831, 0.9061798459386640};
56 const double gweights[5] = {0.2369268850561891, 0.4786286704993665,
57 0.5688888888888889, 0.4786286704993665,
58 0.2369268850561891};
59 const int numIntervals = 100;
60 const double h = (tf - t0) / numIntervals;
61 for (int k = 0; k < numIntervals; ++k) {
62 const double tm = t0 + (k + 0.5) * h;
63 for (int q = 0; q < 5; ++q) {
64 times.push_back(tm + 0.5 * h * nodes[q]);
65 weights.push_back(0.5 * h * gweights[q]);
66 }
67 }
68 }
69 else {
70 times = responseTimes;
71 weights.assign(times.size(), 1.0);
72 }
73
74 for (std::size_t k = 0; k < times.size(); ++k)
75 for (int i = 0; i < num_param; ++i)
76 Thyra::Vp_StV(dJdp->col(i).ptr(), weights[k],
77 *(model.getExactSensSolution(i, times[k]).get_x()));
78 return dJdp;
79}
80
94 const std::string& xmlFile,
95 const std::function<void(Teuchos::ParameterList&)>& configure,
96 const std::string& responseType, const std::vector<double>& responseTimes,
97 const int nTimeStepSizes, const double dt0, const bool useAdjointModel,
98 std::vector<double>& stepSizes, std::vector<double>& errors,
99 double& stepperOrder, Teuchos::FancyOStream& out, bool& success)
100{
101 using Teuchos::ParameterList;
102 using Teuchos::RCP;
103 using Teuchos::sublist;
104
105 std::ostringstream timeList;
106 timeList.precision(17);
107 for (std::size_t k = 0; k < responseTimes.size(); ++k)
108 timeList << (k > 0 ? ", " : "") << responseTimes[k];
109
110 stepSizes.clear();
111 errors.clear();
112 double dt = dt0;
113 for (int n = 0; n < nTimeStepSizes; ++n, dt /= 2) {
114 RCP<ParameterList> pList = Teuchos::getParametersFromXmlFile(xmlFile);
115 RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
116 RCP<SinCosModel<double> > model =
117 Teuchos::rcp(new SinCosModel<double>(scm_pl));
118 RCP<Thyra::ModelEvaluator<double> > adjoint_model;
119 if (useAdjointModel)
120 adjoint_model = Teuchos::rcp(new SinCosModelAdjoint<double>(scm_pl));
121
122 RCP<ParameterList> pl = sublist(pList, "Tempus", true);
123 const std::string integratorName =
124 pl->get<std::string>("Integrator Name");
125 ParameterList& tscPL =
126 pl->sublist(integratorName).sublist("Time Step Control");
127 tscPL.set("Initial Time Step", dt);
128
129 ParameterList& sens_pl = pl->sublist("Sensitivities");
130 sens_pl.set("Response Type", responseType);
131 if (!responseTimes.empty())
132 sens_pl.set("Response Time List", timeList.str());
133
134 configure(*pl);
135
136 RCP<Tempus::IntegratorAdjointSensitivity<double> > integrator =
138 adjoint_model);
139 stepperOrder = integrator->getStepper()->getOrder();
140
141 // Initial conditions and their sensitivities from the exact solution
142 const double t0 = tscPL.get<double>("Initial Time");
143 RCP<const Thyra::VectorBase<double> > x0 =
144 model->getExactSolution(t0).get_x();
145 const int num_param = model->get_p_space(0)->dim();
146 RCP<Thyra::MultiVectorBase<double> > DxDp0 =
147 Thyra::createMembers(model->get_x_space(), num_param);
148 for (int i = 0; i < num_param; ++i)
149 Thyra::assign(DxDp0->col(i).ptr(),
150 *(model->getExactSensSolution(i, t0).get_x()));
151 integrator->initializeSolutionHistory(t0, x0, Teuchos::null, Teuchos::null,
152 DxDp0, Teuchos::null, Teuchos::null);
153
154 const bool integratorStatus = integrator->advanceTime();
155 TEST_ASSERT(integratorStatus);
156 if (!integratorStatus) return;
157
158 const double tf = integrator->getTime();
159 TEST_FLOATING_EQUALITY(tf, tscPL.get<double>("Final Time"), 1.0e-12);
160
161 // The integrator returns dJ/dp in gradient form (num_param x num_g)
162 RCP<const Thyra::MultiVectorBase<double> > DgDp = integrator->getDgDp();
163 RCP<Thyra::MultiVectorBase<double> > dJdp_exact =
164 sinCosExactResponseSensitivity(*model, responseType, t0, tf,
165 responseTimes);
166 double error2 = 0.0;
167 {
168 Thyra::ConstDetachedMultiVectorView<double> dgdp_view(*DgDp);
169 Thyra::ConstDetachedMultiVectorView<double> exact_view(*dJdp_exact);
170 const int num_g = DgDp->domain()->dim();
171 for (int i = 0; i < num_g; ++i)
172 for (int j = 0; j < num_param; ++j) {
173 const double diff = dgdp_view(j, i) - exact_view(i, j);
174 error2 += diff * diff;
175 }
176 }
177 stepSizes.push_back(dt);
178 errors.push_back(std::sqrt(error2));
179 out << " dt = " << dt << " error = " << errors.back() << std::endl;
180 }
181}
182
183} // namespace Tempus_Test
184
185#endif // TEMPUS_ADJOINT_RESPONSE_TEST_UTILS_HPP
Sine-Cosine model problem from Rythmos. This is a canonical Sine-Cosine differential equation.
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getExactSensSolution(int j, double t) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int l) const
Teuchos::RCP< Thyra::MultiVectorBase< double > > sinCosExactResponseSensitivity(const SinCosModel< double > &model, const std::string &responseType, const double t0, const double tf, const std::vector< double > &responseTimes)
Exact sensitivity dJ/dp (Jacobian form, x_space x num_p) of the "Time Integral" or "Sum Over Times" r...
void computeSinCosAdjointResponseErrors(const std::string &xmlFile, const std::function< void(Teuchos::ParameterList &)> &configure, const std::string &responseType, const std::vector< double > &responseTimes, const int nTimeStepSizes, const double dt0, const bool useAdjointModel, std::vector< double > &stepSizes, std::vector< double > &errors, double &stepperOrder, Teuchos::FancyOStream &out, bool &success)
Solve the SinCos adjoint problem with the "Time Integral" or "Sum Over Times" response for a sequence...
Teuchos::RCP< IntegratorAdjointSensitivity< Scalar > > createIntegratorAdjointSensitivity()
Nonmember constructor.