72 std::vector<Scalar> times;
73 std::string::size_type lastPos = str.find_first_not_of(
", ", 0);
74 std::string::size_type pos = str.find_first_of(
",", lastPos);
75 while (lastPos != std::string::npos) {
76 std::string token = str.substr(lastPos, pos - lastPos);
77 token.erase(token.find_last_not_of(
" \t\n\r") + 1);
79 std::size_t numParsed = 0;
82 value = std::stod(token, &numParsed);
84 catch (
const std::exception&) {
87 TEUCHOS_TEST_FOR_EXCEPTION(
88 numParsed != token.size(), std::invalid_argument,
89 "Error - could not parse \"" << token <<
"\" in the time list \""
91 times.push_back(Scalar(value));
93 if (pos == std::string::npos)
break;
94 lastPos = str.find_first_not_of(
", ", pos);
95 pos = str.find_first_of(
",", lastPos);
97 std::sort(times.begin(), times.end());
112 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
114 const bool dgdx_dot_check,
const std::string& caller)
116 typedef Thyra::ModelEvaluatorBase MEB;
117 MEB::OutArgs<Scalar> outArgs = model.createOutArgs();
118 TEUCHOS_TEST_FOR_EXCEPTION(
119 !outArgs.supports(MEB::OUT_ARG_DgDx, g_index)
120 .supports(MEB::DERIV_MV_GRADIENT_FORM),
122 "Error - " << caller <<
": the model must support dg/dx in gradient "
123 <<
"(DERIV_MV_GRADIENT_FORM) form for response " << g_index
125 outArgs.set_DgDx(g_index, MEB::Derivative<Scalar>(Teuchos::rcpFromRef(dgdx),
126 MEB::DERIV_MV_GRADIENT_FORM));
128 Teuchos::RCP<Thyra::MultiVectorBase<Scalar>> dgdx_dot;
129 if (dgdx_dot_check &&
130 outArgs.supports(MEB::OUT_ARG_DgDx_dot, g_index).supports(MEB::DERIV_MV_GRADIENT_FORM)) {
131 dgdx_dot = Thyra::createMembers(model.get_x_space(), dgdx.domain()->dim());
132 outArgs.set_DgDx_dot(g_index, MEB::Derivative<Scalar>(dgdx_dot, MEB::DERIV_MV_GRADIENT_FORM));
134 model.evalModel(inArgs, outArgs);
136 if (dgdx_dot != Teuchos::null) {
137 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Mag;
138 Teuchos::Array<Mag> norms(dgdx_dot->domain()->dim());
139 Thyra::norms_inf(*dgdx_dot, norms());
140 const Mag maxNorm = *std::max_element(norms.begin(), norms.end());
141 TEUCHOS_TEST_FOR_EXCEPTION(
142 maxNorm != Teuchos::ScalarTraits<Mag>::zero(), std::logic_error,
143 "Error - " << caller <<
": response " << g_index
144 <<
" depends on x_dot (|dg/dx_dot| = " << maxNorm
145 <<
"). The \"Time Integral\" and \"Sum Over Times\" "
146 <<
"adjoint responses require g = g(x,p,t).\n");
158 const int g_index,
const int p_index,
159 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
162 typedef Thyra::ModelEvaluatorBase MEB;
163 MEB::OutArgs<Scalar> outArgs = model.createOutArgs();
164 MEB::DerivativeSupport dgdp_support =
165 outArgs.supports(MEB::OUT_ARG_DgDp, g_index, p_index);
166 if (dgdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
167 outArgs.set_DgDp(g_index, p_index,
168 MEB::Derivative<Scalar>(Teuchos::rcpFromRef(dgdp),
169 MEB::DERIV_MV_GRADIENT_FORM));
170 model.evalModel(inArgs, outArgs);
172 else if (dgdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
173 const int num_g = dgdp.domain()->dim();
174 const int num_p = dgdp.range()->dim();
175 Teuchos::RCP<Thyra::MultiVectorBase<Scalar>> dgdp_trans =
176 Thyra::createMembers(model.get_g_space(g_index), num_p);
177 outArgs.set_DgDp(g_index, p_index, MEB::Derivative<Scalar>(dgdp_trans, MEB::DERIV_MV_JACOBIAN_FORM));
178 model.evalModel(inArgs, outArgs);
179 Thyra::DetachedMultiVectorView<Scalar> dgdp_view(dgdp);
180 Thyra::ConstDetachedMultiVectorView<Scalar> dgdp_trans_view(*dgdp_trans);
181 for (
int i = 0; i < num_p; ++i)
182 for (
int j = 0; j < num_g; ++j) dgdp_view(i, j) = dgdp_trans_view(j, i);
185 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Invalid dg/dp support");
199 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
206 typedef Thyra::ModelEvaluatorBase MEB;
207 MEB::OutArgs<Scalar> outArgs = model.createOutArgs();
208 MEB::DerivativeSupport dfdp_support = outArgs.supports(MEB::OUT_ARG_DfDp, p_index);
209 Thyra::EOpTransp trans = Thyra::CONJTRANS;
210 if (dfdp_support.supports(MEB::DERIV_LINEAR_OP)) {
211 if (dfdp_op == Teuchos::null) dfdp_op = model.create_DfDp_op(p_index);
212 outArgs.set_DfDp(p_index, MEB::Derivative<Scalar>(dfdp_op));
214 else if (dfdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
215 if (dfdp_mv == Teuchos::null)
216 dfdp_mv = Thyra::createMembers(model.get_f_space(), model.get_p_space(p_index)->dim());
217 outArgs.set_DfDp(p_index, MEB::Derivative<Scalar>(dfdp_mv, MEB::DERIV_MV_JACOBIAN_FORM));
220 else if (dfdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
221 if (dfdp_mv == Teuchos::null)
222 dfdp_mv = Thyra::createMembers(model.get_p_space(p_index), model.get_f_space()->dim());
223 outArgs.set_DfDp(p_index, MEB::Derivative<Scalar>(dfdp_mv, MEB::DERIV_MV_GRADIENT_FORM));
228 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Invalid df/dp support");
229 model.evalModel(inArgs, outArgs);
230 dfdp_op->apply(trans, v, Teuchos::ptrFromRef(y), alpha, beta);
242 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
const Scalar alpha,
251 typedef Thyra::ModelEvaluatorBase MEB;
253 MEB::InArgs<Scalar> inargs = inArgs;
254 inargs.set_alpha(alpha);
255 inargs.set_beta(beta);
256 MEB::OutArgs<Scalar> adj_outargs = adjoint_model.createOutArgs();
257 RCP<LinearOpWithSolveBase<Scalar>> W;
258 if (adj_outargs.supports(MEB::OUT_ARG_W)) {
260 W = adjoint_model.create_W();
261 adj_outargs.set_W(W);
262 adjoint_model.evalModel(inargs, adj_outargs);
266 RCP<const LinearOpWithSolveFactoryBase<Scalar>> lowsfb =
267 adjoint_model.get_W_factory();
268 TEUCHOS_TEST_FOR_EXCEPTION(lowsfb == Teuchos::null, std::logic_error,
269 "Adjoint ME must support W out-arg or provide "
270 "a W_factory for non-identity mass matrix");
273 RCP<LinearOpBase<Scalar>> W_op = adjoint_model.create_W_op();
274 adj_outargs.set_W_op(W_op);
275 RCP<PreconditionerFactoryBase<Scalar>> prec_factory = lowsfb->getPreconditionerFactory();
276 RCP<PreconditionerBase<Scalar>> W_prec;
277 if (prec_factory != Teuchos::null)
278 W_prec = prec_factory->createPrec();
279 else if (adj_outargs.supports(MEB::OUT_ARG_W_prec)) {
280 W_prec = adjoint_model.create_W_prec();
281 adj_outargs.set_W_prec(W_prec);
283 adjoint_model.evalModel(inargs, adj_outargs);
286 W = lowsfb->createOp();
287 if (W_prec != Teuchos::null) {
288 if (prec_factory != Teuchos::null)
289 prec_factory->initializePrec(Thyra::defaultLinearOpSource<Scalar>(W_op), W_prec.get());
290 Thyra::initializePreconditionedOp<Scalar>(*lowsfb, W_op, W_prec, W.ptr());
293 Thyra::initializeOp<Scalar>(*lowsfb, W_op, W.ptr());
295 TEUCHOS_TEST_FOR_EXCEPTION(
296 W == Teuchos::null, std::logic_error,
297 "A null W has been encountered in "
298 "Tempus::AdjointSensitivityUtils::createAdjointLinearOpWithSolve!\n");