Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_MPModelEvaluator.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 
12 #include <algorithm>
13 #include "Teuchos_Assert.hpp"
14 #include "EpetraExt_BlockUtility.h"
15 #include "EpetraExt_BlockMultiVector.h"
20 
24  const Teuchos::RCP<const Epetra_Map>& mp_block_map_,
26  : me(me_),
27  num_mp_blocks(mp_block_map_->NumMyElements()),
28  mp_comm(mp_comm_),
29  mp_block_map(mp_block_map_),
30  params(params_),
31  supports_x(false),
32  x_map(me->get_x_map()),
33  f_map(me->get_f_map()),
34  mp_x_map(),
35  mp_f_map(),
36  num_p(0),
37  num_p_mp(0),
38  mp_p_index_map(),
39  mp_p_map(),
40  mp_p_names(),
41  num_g(0),
42  num_g_mp(0),
43  mp_g_index_map(),
44  mp_g_map(),
45  W_mp_blocks(),
46  mp_p_init(),
47  my_W(),
48  my_x()
49 {
50  if (x_map != Teuchos::null)
51  supports_x = true;
52 
53  if (supports_x) {
54 
55  // Create block MP x and f maps
56  mp_x_map =
57  Teuchos::rcp(EpetraExt::BlockUtility::GenerateBlockMap(
58  *x_map, *mp_block_map, *mp_comm));
59 
60  mp_f_map =
61  Teuchos::rcp(EpetraExt::BlockUtility::GenerateBlockMap(
62  *f_map, *mp_block_map, *mp_comm));
63 
64  // Create default mp_x_init
67  for (unsigned int i=0; i<num_mp_blocks; i++)
68  (*mp_x_init)[i] = *(me->get_x_init());
69 
72  if (me->get_x_dot_init() != Teuchos::null) {
73  for (unsigned int i=0; i<num_mp_blocks; i++)
74  (*mp_x_dot_init)[i] = *(me->get_x_dot_init());
75  }
76  // Preconditioner needs an x
78 
79  W_mp_blocks =
82  for (unsigned int i=0; i<num_mp_blocks; i++)
83  W_mp_blocks->setCoeffPtr(i, me->create_W());
84  }
85 
86  // Parameters -- The idea here is to add new parameter vectors
87  // for the stochastic Galerkin components of the parameters
88 
89  InArgs me_inargs = me->createInArgs();
90  num_p = me_inargs.Np();
91 
92  // Get the p_mp's supported and build index map
93  for (int i=0; i<num_p; i++) {
94  if (me_inargs.supports(IN_ARG_p_mp, i))
96  }
98 
99  mp_p_map.resize(num_p_mp);
100  mp_p_names.resize(num_p_mp);
101  mp_p_init.resize(num_p_mp);
102 
103  // Create parameter maps, names, and initial values
104  for (int i=0; i<num_p_mp; i++) {
105  Teuchos::RCP<const Epetra_Map> p_map = me->get_p_map(mp_p_index_map[i]);
106  mp_p_map[i] =
107  Teuchos::rcp(EpetraExt::BlockUtility::GenerateBlockMap(
108  *p_map, *mp_block_map, *mp_comm));
109 
111  me->get_p_names(mp_p_index_map[i]);
112  if (p_names != Teuchos::null) {
113  mp_p_names[i] =
115  for (int j=0; j<p_names->size(); j++) {
116  std::stringstream ss;
117  ss << (*p_names)[j] << " -- MP Coefficient " << i;
118  (*mp_p_names[i])[j] = ss.str();
119  }
120  }
121 
122  // Create default mp_p_init
123  mp_p_init[i] =
125  mp_block_map, p_map, mp_p_map[i], mp_comm));
126  mp_p_init[i]->init(0.0);
127  // for (unsigned int j=0; j<num_mp_blocks; j++)
128  // (*mp_p_init[i])[j] = *(me->get_p_init(i));
129 
130  }
131 
132  // Responses -- The idea here is to add new parameter vectors
133  // for the stochastic Galerkin components of the respones
134 
135  // Get number of MP parameters model supports derivatives w.r.t.
136  OutArgs me_outargs = me->createOutArgs();
137  num_g = me_outargs.Ng();
138 
139  // Get the g_mp's supported and build index map
140  for (int i=0; i<num_g; i++) {
141  if (me_outargs.supports(OUT_ARG_g_mp, i))
143  }
145 
146  mp_g_map.resize(num_g_mp);
147 
148  // Create response maps
149  for (int i=0; i<num_g_mp; i++) {
150  Teuchos::RCP<const Epetra_Map> g_map = me->get_g_map(mp_g_index_map[i]);
151  mp_g_map[i] =
152  Teuchos::rcp(EpetraExt::BlockUtility::GenerateBlockMap(
153  *g_map, *mp_block_map, *mp_comm));
154  }
155 }
156 
157 // Overridden from EpetraExt::ModelEvaluator
158 
161 {
162  return mp_x_map;
163 }
164 
167 {
168  return mp_f_map;
169 }
170 
173 {
174  TEUCHOS_TEST_FOR_EXCEPTION(l < 0 || l >= num_p + num_p_mp, std::logic_error,
175  "Error! Invalid p map index " << l);
176  if (l < num_p)
177  return me->get_p_map(l);
178  else
179  return mp_p_map[l-num_p];
180 
181  return Teuchos::null;
182 }
183 
186 {
187  TEUCHOS_TEST_FOR_EXCEPTION(j < 0 || j >= num_g_mp, std::logic_error,
188  "Error! Invalid g map index " << j);
189  return mp_g_map[j];
190 }
191 
194 {
195  TEUCHOS_TEST_FOR_EXCEPTION(l < 0 || l >= num_p + num_p_mp, std::logic_error,
196  "Error! Invalid p map index " << l);
197  if (l < num_p)
198  return me->get_p_names(l);
199  else
200  return mp_p_names[l-num_p];
201 
202  return Teuchos::null;
203 }
204 
207 {
208  return mp_x_init->getBlockVector();
209 }
210 
213 {
214  return mp_x_dot_init->getBlockVector();
215 }
216 
219 {
220  TEUCHOS_TEST_FOR_EXCEPTION(l < 0 || l >= num_p + num_p_mp, std::logic_error,
221  "Error! Invalid p map index " << l);
222  if (l < num_p)
223  return me->get_p_init(l);
224  else if (l < num_p + num_p_mp)
225  return mp_p_init[l-num_p]->getBlockVector();
226 
227  return Teuchos::null;
228 }
229 
232 {
233  if (supports_x) {
234  my_W =
235  Teuchos::rcp(new Stokhos::BlockDiagonalOperator(mp_comm, num_mp_blocks,
236  x_map, f_map,
237  mp_x_map, mp_f_map));
238  my_W->setupOperator(W_mp_blocks);
239 
240  return my_W;
241  }
242 
243  return Teuchos::null;
244 }
245 
248 {
249  if (supports_x) {
251  Teuchos::rcp(&(params->sublist("MP Preconditioner")), false);
252  Stokhos::MPPreconditionerFactory mp_prec_factory(mpPrecParams);
254  mp_prec_factory.build(mp_comm, num_mp_blocks, x_map, mp_x_map);
255  return Teuchos::rcp(new EpetraExt::ModelEvaluator::Preconditioner(precOp,
256  true));
257  }
258 
259  return Teuchos::null;
260 }
261 
264 {
265  TEUCHOS_TEST_FOR_EXCEPTION(j < 0 || j >= num_g_mp || !supports_x,
266  std::logic_error,
267  "Error: dg/dx index " << j << " is not supported!");
268 
269  int jj = mp_g_index_map[j];
270  Teuchos::RCP<const Epetra_Map> g_map = me->get_g_map(jj);
272  OutArgs me_outargs = me->createOutArgs();
273  DerivativeSupport ds = me_outargs.supports(OUT_ARG_DgDx_mp, jj);
274  if (ds.supports(DERIV_LINEAR_OP)) {
275  mp_blocks =
277  mp_block_map, x_map, g_map, mp_g_map[j], mp_comm));
278  for (unsigned int i=0; i<num_mp_blocks; i++)
279  mp_blocks->setCoeffPtr(i, me->create_DgDx_op(jj));
280  }
281  else if (ds.supports(DERIV_MV_BY_COL)) {
284  mp_block_map, g_map, mp_g_map[j],
285  mp_comm, x_map->NumMyElements()));
286  mp_blocks =
288  mp_mv_blocks, false));
289  }
290  else if (ds.supports(DERIV_TRANS_MV_BY_ROW)) {
293  mp_block_map, x_map, mp_x_map,
294  mp_comm, g_map->NumMyElements()));
295  mp_blocks =
297  mp_mv_blocks, true));
298  }
299  else
300  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
301  "Error! me_outargs.supports(OUT_ARG_DgDx_mp, " << j
302  << ").none() is true!");
303 
306  mp_comm, num_mp_blocks, x_map, g_map,
307  mp_x_map, mp_g_map[j]));
308  dgdx_mp->setupOperator(mp_blocks);
309  return dgdx_mp;
310 }
311 
314 {
315  TEUCHOS_TEST_FOR_EXCEPTION(j < 0 || j >= num_g_mp || !supports_x,
316  std::logic_error,
317  "Error: dg/dx_dot index " << j << " is not supported!");
318 
319  int jj = mp_g_index_map[j];
320  Teuchos::RCP<const Epetra_Map> g_map = me->get_g_map(jj);
322  OutArgs me_outargs = me->createOutArgs();
323  DerivativeSupport ds = me_outargs.supports(OUT_ARG_DgDx_dot_mp, jj);
324  if (ds.supports(DERIV_LINEAR_OP)) {
325  mp_blocks =
327  mp_block_map, x_map, g_map, mp_g_map[j],
328  mp_comm));
329  for (unsigned int i=0; i<num_mp_blocks; i++)
330  mp_blocks->setCoeffPtr(i, me->create_DgDx_dot_op(jj));
331  }
332  else if (ds.supports(DERIV_MV_BY_COL)) {
335  mp_block_map, g_map, mp_g_map[j],
336  mp_comm, x_map->NumMyElements()));
337  mp_blocks =
339  mp_mv_blocks, false));
340  }
341  else if (ds.supports(DERIV_TRANS_MV_BY_ROW)) {
344  mp_block_map, x_map, mp_x_map,
345  mp_comm, g_map->NumMyElements()));
346  mp_blocks =
348  mp_mv_blocks, true));
349  }
350  else
351  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
352  "Error! me_outargs.supports(OUT_ARG_DgDx_dot_mp, "
353  << j << ").none() is true!");
354 
357  mp_comm, num_mp_blocks, x_map, g_map,
358  mp_x_map, mp_g_map[j]));
359  dgdx_dot_mp->setupOperator(mp_blocks);
360  return dgdx_dot_mp;
361 }
362 
365 {
367  j < 0 || j >= num_g_mp || i < 0 || i >= num_p+num_p_mp,
368  std::logic_error,
369  "Error: dg/dp index " << j << "," << i << " is not supported!");
370 
371  OutArgs me_outargs = me->createOutArgs();
372  int jj = mp_g_index_map[j];
373  Teuchos::RCP<const Epetra_Map> g_map = me->get_g_map(jj);
374  if (i < num_p) {
375  if (me_outargs.supports(OUT_ARG_DgDp_mp,jj,i).supports(DERIV_LINEAR_OP)) {
378  mp_block_map, me->get_p_map(i), g_map,
379  mp_g_map[j], mp_comm));
380  for (unsigned int l=0; l<num_mp_blocks; l++)
381  mp_blocks->setCoeffPtr(l, me->create_DgDp_op(i,j));
382  return mp_blocks;
383  }
384  else
386  true, std::logic_error,
387  "Error: Underlying model evaluator must support DERIV_LINER_OP " <<
388  "to create operator for dg/dp index " << j << "," << i << "!");
389  }
390  else {
391  int ii = mp_p_index_map[i-num_p];
392  Teuchos::RCP<const Epetra_Map> p_map = me->get_p_map(ii);
394  DerivativeSupport ds = me_outargs.supports(OUT_ARG_DgDp_mp,jj,ii);
395  if (ds.supports(DERIV_LINEAR_OP)) {
396  mp_blocks =
398  mp_block_map, p_map, g_map,
399  mp_g_map[j], mp_comm));
400  for (unsigned int l=0; l<num_mp_blocks; l++)
401  mp_blocks->setCoeffPtr(l, me->create_DgDp_op(jj,ii));
402  }
403  else if (ds.supports(DERIV_MV_BY_COL)) {
406  mp_block_map, g_map, mp_g_map[j],
407  mp_comm, p_map->NumMyElements()));
408  mp_blocks =
410  mp_mv_blocks, false));
411  }
412  else if (ds.supports(DERIV_TRANS_MV_BY_ROW)) {
415  mp_block_map, p_map, mp_p_map[i-num_p],
416  mp_comm, g_map->NumMyElements()));
417  mp_blocks =
419  mp_mv_blocks, true));
420  }
421  else
422  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
423  "Error! me_outargs.supports(OUT_ARG_DgDp_mp, " << jj
424  << "," << ii << ").none() is true!");
425 
428  mp_comm, num_mp_blocks, p_map, g_map,
429  mp_p_map[i-num_p], mp_g_map[j]));
430  dgdp_mp->setupOperator(mp_blocks);
431  return dgdp_mp;
432  }
433 
434  return Teuchos::null;
435 }
436 
439 {
440  TEUCHOS_TEST_FOR_EXCEPTION(i < 0 || i >= num_p+num_p_mp,
441  std::logic_error,
442  "Error: df/dp index " << i << " is not supported!");
443 
444  OutArgs me_outargs = me->createOutArgs();
445  if (i < num_p) {
446  if (me_outargs.supports(OUT_ARG_DfDp_mp,i).supports(DERIV_LINEAR_OP)) {
449  mp_block_map, me->get_p_map(i), me->get_f_map(),
450  mp_f_map, mp_comm));
451  for (unsigned int l=0; l<num_mp_blocks; l++)
452  mp_blocks->setCoeffPtr(l, me->create_DfDp_op(i));
453  return mp_blocks;
454  }
455  else
457  true, std::logic_error,
458  "Error: Underlying model evaluator must support DERIV_LINER_OP " <<
459  "to create operator for df/dp index " << i << "!");
460  }
461  else {
462  int ii = mp_p_index_map[i-num_p];
463  Teuchos::RCP<const Epetra_Map> p_map = me->get_p_map(ii);
465  DerivativeSupport ds = me_outargs.supports(OUT_ARG_DfDp_mp,ii);
466  if (ds.supports(DERIV_LINEAR_OP)) {
467  mp_blocks =
469  mp_block_map, me->get_p_map(ii), me->get_f_map(),
470  mp_f_map, mp_comm));
471  for (unsigned int l=0; l<num_mp_blocks; l++)
472  mp_blocks->setCoeffPtr(l, me->create_DfDp_op(ii));
473  }
474  else if (ds.supports(DERIV_MV_BY_COL)) {
477  mp_block_map, f_map, mp_f_map,
478  mp_comm, p_map->NumMyElements()));
479  mp_blocks =
481  mp_mv_blocks, false));
482  }
483  else if (ds.supports(DERIV_TRANS_MV_BY_ROW)) {
486  mp_block_map, p_map, mp_p_map[i-num_p],
487  mp_comm, f_map->NumMyElements()));
488  mp_blocks =
490  mp_mv_blocks, true));
491  }
492  else
493  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
494  "Error! me_outargs.supports(OUT_ARG_DfDp_mp, " << ii
495  << ").none() is true!");
496 
497 
500  mp_comm, num_mp_blocks,
501  p_map, f_map, mp_p_map[i-num_p], mp_f_map));
502  dfdp_mp->setupOperator(mp_blocks);
503  return dfdp_mp;
504  }
505 
506  return Teuchos::null;
507 }
508 
509 EpetraExt::ModelEvaluator::InArgs
511 {
512  InArgsSetup inArgs;
513  InArgs me_inargs = me->createInArgs();
514 
515  inArgs.setModelEvalDescription(this->description());
516  inArgs.set_Np(num_p + num_p_mp);
517  inArgs.setSupports(IN_ARG_x_dot, me_inargs.supports(IN_ARG_x_dot));
518  inArgs.setSupports(IN_ARG_x, me_inargs.supports(IN_ARG_x));
519  inArgs.setSupports(IN_ARG_t, me_inargs.supports(IN_ARG_t));
520  inArgs.setSupports(IN_ARG_alpha, me_inargs.supports(IN_ARG_alpha));
521  inArgs.setSupports(IN_ARG_beta, me_inargs.supports(IN_ARG_beta));
522 
523  return inArgs;
524 }
525 
526 EpetraExt::ModelEvaluator::OutArgs
528 {
529  OutArgsSetup outArgs;
530  OutArgs me_outargs = me->createOutArgs();
531 
532  outArgs.setModelEvalDescription(this->description());
533  outArgs.set_Np_Ng(num_p + num_p_mp, num_g_mp);
534  outArgs.setSupports(OUT_ARG_f, me_outargs.supports(OUT_ARG_f));
535  outArgs.setSupports(OUT_ARG_W, me_outargs.supports(OUT_ARG_W));
536  outArgs.setSupports(OUT_ARG_WPrec, me_outargs.supports(OUT_ARG_W));
537  for (int j=0; j<num_p; j++)
538  outArgs.setSupports(OUT_ARG_DfDp, j,
539  me_outargs.supports(OUT_ARG_DfDp, j));
540  for (int j=0; j<num_p_mp; j++)
541  if (!me_outargs.supports(OUT_ARG_DfDp_mp, mp_p_index_map[j]).none())
542  outArgs.setSupports(OUT_ARG_DfDp, j+num_p, DERIV_LINEAR_OP);
543  for (int i=0; i<num_g_mp; i++) {
544  int ii = mp_g_index_map[i];
545  if (!me_outargs.supports(OUT_ARG_DgDx_dot_mp, ii).none())
546  outArgs.setSupports(OUT_ARG_DgDx_dot, i, DERIV_LINEAR_OP);
547  if (!me_outargs.supports(OUT_ARG_DgDx_mp, ii).none())
548  outArgs.setSupports(OUT_ARG_DgDx, i, DERIV_LINEAR_OP);
549  for (int j=0; j<num_p; j++)
550  outArgs.setSupports(OUT_ARG_DgDp, i, j,
551  me_outargs.supports(OUT_ARG_DgDp_mp, ii, j));
552  for (int j=0; j<num_p_mp; j++)
553  if (!me_outargs.supports(OUT_ARG_DgDp_mp, ii, mp_p_index_map[j]).none())
554  outArgs.setSupports(OUT_ARG_DgDp, i, j+num_p, DERIV_LINEAR_OP);
555  }
556 
557  return outArgs;
558 }
559 
560 void
562  const OutArgs& outArgs) const
563 {
564  // Get the input arguments
566  if (inArgs.supports(IN_ARG_x)) {
567  x = inArgs.get_x();
568  if (x != Teuchos::null)
569  *my_x = *x;
570  }
572  if (inArgs.supports(IN_ARG_x_dot))
573  x_dot = inArgs.get_x_dot();
574 
575  // Get the output arguments
576  EpetraExt::ModelEvaluator::Evaluation<Epetra_Vector> f_out;
577  if (outArgs.supports(OUT_ARG_f))
578  f_out = outArgs.get_f();
580  if (outArgs.supports(OUT_ARG_W))
581  W_out = outArgs.get_W();
583  if (outArgs.supports(OUT_ARG_WPrec))
584  WPrec_out = outArgs.get_WPrec();
585 
586  // Check if we are using the "matrix-free" method for W and we are
587  // computing a preconditioner.
588  bool eval_prec = (W_out == Teuchos::null && WPrec_out != Teuchos::null);
589 
590  // Here we are assuming a full W fill occurred previously which we can use
591  // for the preconditioner. Given the expense of computing the MP W blocks
592  // this saves significant computational cost
593  if (eval_prec) {
595  Teuchos::rcp_dynamic_cast<Stokhos::MPPreconditioner>(WPrec_out, true);
596  W_prec->setupPreconditioner(my_W, *my_x);
597 
598  // We can now quit unless a fill of f, g, or dg/dp was also requested
599  bool done = (f_out == Teuchos::null);
600  for (int i=0; i<outArgs.Ng(); i++) {
601  done = done && (outArgs.get_g(i) == Teuchos::null);
602  for (int j=0; j<outArgs.Np(); j++)
603  if (!outArgs.supports(OUT_ARG_DgDp, i, j).none())
604  done = done && (outArgs.get_DgDp(i,j).isEmpty());
605  }
606  if (done)
607  return;
608  }
609 
610  // Create underlying inargs
611  InArgs me_inargs = me->createInArgs();
612  if (x != Teuchos::null) {
614  create_x_mp(View, x.get());
615  me_inargs.set_x_mp(x_mp);
616  }
617  if (x_dot != Teuchos::null) {
619  create_x_mp(View, x_dot.get());
620  me_inargs.set_x_dot_mp(x_dot_mp);
621  }
622  if (me_inargs.supports(IN_ARG_alpha))
623  me_inargs.set_alpha(inArgs.get_alpha());
624  if (me_inargs.supports(IN_ARG_beta))
625  me_inargs.set_beta(inArgs.get_beta());
626  if (me_inargs.supports(IN_ARG_t))
627  me_inargs.set_t(inArgs.get_t());
628 
629  // Pass parameters
630  for (int i=0; i<num_p; i++)
631  me_inargs.set_p(i, inArgs.get_p(i));
632  for (int i=0; i<num_p_mp; i++) {
633  Teuchos::RCP<const Epetra_Vector> p = inArgs.get_p(i+num_p);
634 
635  // We always need to pass in the MP parameters, so just use
636  // the initial parameters if it is NULL
637  if (p == Teuchos::null)
638  p = mp_p_init[i]->getBlockVector();
639 
640  // Convert block p to MP polynomial
642  create_p_mp(mp_p_index_map[i], View, p.get());
643  me_inargs.set_p_mp(mp_p_index_map[i], p_mp);
644  }
645 
646  // Create underlying outargs
647  OutArgs me_outargs = me->createOutArgs();
648 
649  // f
650  if (f_out != Teuchos::null) {
652  create_f_mp(View, f_out.get());
653  me_outargs.set_f_mp(f_mp);
654  }
655 
656  // W
657  if (W_out != Teuchos::null && !eval_prec)
658  me_outargs.set_W_mp(W_mp_blocks);
659 
660  // df/dp -- scalar p
661  for (int i=0; i<num_p; i++) {
662  if (!outArgs.supports(OUT_ARG_DfDp, i).none()) {
663  Derivative dfdp = outArgs.get_DfDp(i);
664  if (dfdp.getMultiVector() != Teuchos::null) {
666  if (dfdp.getMultiVectorOrientation() == DERIV_MV_BY_COL)
667  dfdp_mp =
669  mp_block_map, me->get_f_map(), mp_f_map, mp_comm,
670  View, *(dfdp.getMultiVector())));
671  else if (dfdp.getMultiVectorOrientation() == DERIV_TRANS_MV_BY_ROW)
672  dfdp_mp =
674  mp_block_map, me->get_p_map(i), mp_p_map[i], mp_comm,
675  View, *(dfdp.getMultiVector())));
676  me_outargs.set_DfDp_mp(i,
677  MPDerivative(dfdp_mp,
678  dfdp.getMultiVectorOrientation()));
679  }
680  else if (dfdp.getLinearOp() != Teuchos::null) {
682  Teuchos::rcp_dynamic_cast<Stokhos::ProductEpetraOperator>(dfdp.getLinearOp(), true);
683  me_outargs.set_DfDp_mp(i, MPDerivative(dfdp_mp));
684  }
685  }
686  }
687 
688  // dfdp -- block p. Here we only support DERIV_LINEAR_OP
689  for (int i=0; i<num_p_mp; i++) {
690  if (!outArgs.supports(OUT_ARG_DfDp, i+num_p).none()) {
691  Derivative dfdp = outArgs.get_DfDp(i+num_p);
692  if (dfdp.getLinearOp() != Teuchos::null) {
694  Teuchos::rcp_dynamic_cast<Stokhos::BlockDiagonalOperator>(dfdp.getLinearOp(), true);
696  dfdp_op->getMPOps();
697  int ii = mp_p_index_map[i];
698  if (me_outargs.supports(OUT_ARG_DfDp_mp,ii).supports(DERIV_LINEAR_OP))
699  me_outargs.set_DfDp_mp(ii, MPDerivative(dfdp_op_mp));
700  else {
702  Teuchos::rcp_dynamic_cast<Stokhos::ProductEpetraMultiVectorOperator>(dfdp_op_mp, true);
704  mp_mv_op->productMultiVector();
705  if (me_outargs.supports(OUT_ARG_DfDp_mp,ii).supports(DERIV_MV_BY_COL))
706  me_outargs.set_DfDp_mp(
707  ii, MPDerivative(dfdp_mp, DERIV_MV_BY_COL));
708  else
709  me_outargs.set_DfDp_mp(
710  ii, MPDerivative(dfdp_mp, DERIV_TRANS_MV_BY_ROW));
711  }
712  }
714  dfdp.getLinearOp() == Teuchos::null && dfdp.isEmpty() == false,
715  std::logic_error,
716  "Error! Stokhos::MPModelEvaluator::evalModel: " <<
717  "Operator form of df/dp(" << i+num_p << ") is required!");
718  }
719  }
720 
721  // Responses (g, dg/dx, dg/dp, ...)
722  for (int i=0; i<num_g_mp; i++) {
723  int ii = mp_g_index_map[i];
724 
725  // g
726  Teuchos::RCP<Epetra_Vector> g = outArgs.get_g(i);
727  if (g != Teuchos::null) {
729  create_g_mp(ii, View, g.get());
730  me_outargs.set_g_mp(ii, g_mp);
731  }
732 
733  // dg/dxdot
734  if (outArgs.supports(OUT_ARG_DgDx_dot, i).supports(DERIV_LINEAR_OP)) {
735  Derivative dgdx_dot = outArgs.get_DgDx_dot(i);
736  if (dgdx_dot.getLinearOp() != Teuchos::null) {
738  Teuchos::rcp_dynamic_cast<Stokhos::BlockDiagonalOperator>(
739  dgdx_dot.getLinearOp(), true);
741  op->getMPOps();
742  if (me_outargs.supports(OUT_ARG_DgDx, ii).supports(DERIV_LINEAR_OP))
743  me_outargs.set_DgDx_dot_mp(ii, mp_blocks);
744  else {
746  Teuchos::rcp_dynamic_cast<Stokhos::ProductEpetraMultiVectorOperator>(mp_blocks, true);
748  mp_mv_op->productMultiVector();
749  if (me_outargs.supports(OUT_ARG_DgDx_dot_mp, ii).supports(DERIV_MV_BY_COL))
750  me_outargs.set_DgDx_dot_mp(ii, MPDerivative(dgdx_dot_mp,
751  DERIV_MV_BY_COL));
752  else
753  me_outargs.set_DgDx_dot_mp(ii, MPDerivative(dgdx_dot_mp,
754  DERIV_TRANS_MV_BY_ROW));
755  }
756  }
757  TEUCHOS_TEST_FOR_EXCEPTION(dgdx_dot.getLinearOp() == Teuchos::null &&
758  dgdx_dot.isEmpty() == false,
759  std::logic_error,
760  "Error! Stokhos::MPModelEvaluator::evalModel: " <<
761  "Operator form of dg/dxdot is required!");
762  }
763 
764  // dg/dx
765  if (outArgs.supports(OUT_ARG_DgDx, i).supports(DERIV_LINEAR_OP)) {
766  Derivative dgdx = outArgs.get_DgDx(i);
767  if (dgdx.getLinearOp() != Teuchos::null) {
769  Teuchos::rcp_dynamic_cast<Stokhos::BlockDiagonalOperator>(
770  dgdx.getLinearOp(), true);
772  op->getMPOps();
773  if (me_outargs.supports(OUT_ARG_DgDx, ii).supports(DERIV_LINEAR_OP))
774  me_outargs.set_DgDx_mp(ii, mp_blocks);
775  else {
777  Teuchos::rcp_dynamic_cast<Stokhos::ProductEpetraMultiVectorOperator>(mp_blocks, true);
779  mp_mv_op->productMultiVector();
780  if (me_outargs.supports(OUT_ARG_DgDx_mp, ii).supports(DERIV_MV_BY_COL))
781  me_outargs.set_DgDx_mp(ii, MPDerivative(dgdx_mp,
782  DERIV_MV_BY_COL));
783  else
784  me_outargs.set_DgDx_mp(ii, MPDerivative(dgdx_mp,
785  DERIV_TRANS_MV_BY_ROW));
786  }
787  }
788  TEUCHOS_TEST_FOR_EXCEPTION(dgdx.getLinearOp() == Teuchos::null &&
789  dgdx.isEmpty() == false,
790  std::logic_error,
791  "Error! Stokhos::MPModelEvaluator::evalModel: " <<
792  "Operator form of dg/dxdot is required!");
793  }
794 
795  // dg/dp -- scalar p
796  for (int j=0; j<num_p; j++) {
797  if (!outArgs.supports(OUT_ARG_DgDp, i, j).none()) {
798  Derivative dgdp = outArgs.get_DgDp(i,j);
799  if (dgdp.getMultiVector() != Teuchos::null) {
801  if (dgdp.getMultiVectorOrientation() == DERIV_MV_BY_COL)
802  dgdp_mp =
804  mp_block_map, me->get_g_map(ii), mp_g_map[i],
805  mp_comm, View, *(dgdp.getMultiVector())));
806  else if (dgdp.getMultiVectorOrientation() == DERIV_TRANS_MV_BY_ROW)
807  dgdp_mp =
809  mp_block_map, me->get_p_map(j), mp_p_map[j],
810  mp_comm, View, *(dgdp.getMultiVector())));
811  me_outargs.set_DgDp_mp(
812  ii, j, MPDerivative(dgdp_mp, dgdp.getMultiVectorOrientation()));
813  }
814  else if (dgdp.getLinearOp() != Teuchos::null) {
816  Teuchos::rcp_dynamic_cast<Stokhos::ProductEpetraOperator>(dgdp.getLinearOp(), true);
817  me_outargs.set_DgDp_mp(ii, j, MPDerivative(dgdp_mp));
818  }
819  }
820  }
821 
822  // dgdp -- block p. Here we only support DERIV_LINEAR_OP
823  for (int j=0; j<num_p_mp; j++) {
824  if (!outArgs.supports(OUT_ARG_DgDp, i, j+num_p).none()) {
825  Derivative dgdp = outArgs.get_DgDp(i,j+num_p);
826  if (dgdp.getLinearOp() != Teuchos::null) {
828  Teuchos::rcp_dynamic_cast<Stokhos::BlockDiagonalOperator>(dgdp.getLinearOp(), true);
830  dgdp_op->getMPOps();
831  int jj = mp_p_index_map[j];
832  if (me_outargs.supports(OUT_ARG_DgDp_mp,ii,jj).supports(DERIV_LINEAR_OP))
833  me_outargs.set_DgDp_mp(ii, jj, MPDerivative(dgdp_op_mp));
834  else {
836  Teuchos::rcp_dynamic_cast<Stokhos::ProductEpetraMultiVectorOperator>(dgdp_op_mp, true);
838  mp_mv_op->productMultiVector();
839  if (me_outargs.supports(OUT_ARG_DgDp_mp,ii,jj).supports(DERIV_MV_BY_COL))
840  me_outargs.set_DgDp_mp(
841  ii, jj, MPDerivative(dgdp_mp, DERIV_MV_BY_COL));
842  else
843  me_outargs.set_DgDp_mp(
844  ii, jj, MPDerivative(dgdp_mp, DERIV_TRANS_MV_BY_ROW));
845  }
846  }
848  dgdp.getLinearOp() == Teuchos::null && dgdp.isEmpty() == false,
849  std::logic_error,
850  "Error! Stokhos::MPModelEvaluator::evalModel: " <<
851  "Operator form of dg/dp(" << i << "," << j+num_p << ") is required!");
852  }
853  }
854 
855  }
856 
857  // Compute the functions
858  me->evalModel(me_inargs, me_outargs);
859 
860  // Copy block MP components for W
861  if (W_out != Teuchos::null && !eval_prec) {
863  if (W_out != Teuchos::null)
864  W = W_out;
865  else
866  W = my_W;
868  Teuchos::rcp_dynamic_cast<Stokhos::BlockDiagonalOperator>(W, true);
869  W_mp->setupOperator(W_mp_blocks);
870 
871  if (WPrec_out != Teuchos::null) {
873  Teuchos::rcp_dynamic_cast<Stokhos::MPPreconditioner>(WPrec_out, true);
874  W_prec->setupPreconditioner(W_mp, *my_x);
875  }
876  }
877 }
878 
879 void
881  const Stokhos::ProductEpetraVector& x_mp_in)
882 {
883  *mp_x_init = x_mp_in;
884 }
885 
886 void
888  const Stokhos::ProductEpetraVector& x_dot_mp_in)
889 {
890  *mp_x_dot_init = x_dot_mp_in;
891 }
892 
895 {
896  return mp_x_init;
897 }
898 
901 {
902  return mp_x_dot_init;
903 }
904 
905 void
907  int i, const Stokhos::ProductEpetraVector& p_mp_in)
908 {
909  Teuchos::Array<int>::iterator it = std::find(mp_p_index_map.begin(),
910  mp_p_index_map.end(),
911  i);
912  TEUCHOS_TEST_FOR_EXCEPTION(it == mp_p_index_map.end(), std::logic_error,
913  "Error! Invalid p map index " << i);
914  int ii = it - mp_p_index_map.begin();
915  *mp_p_init[ii] = p_mp_in;
916 }
917 
920 {
921  Teuchos::Array<int>::const_iterator it = std::find(mp_p_index_map.begin(),
922  mp_p_index_map.end(),
923  l);
924  TEUCHOS_TEST_FOR_EXCEPTION(it == mp_p_index_map.end(), std::logic_error,
925  "Error! Invalid p map index " << l);
926  int ll = it - mp_p_index_map.begin();
927  return mp_p_init[ll];
928 }
929 
932 {
933  return mp_p_index_map;
934 }
935 
938 {
939  return mp_g_index_map;
940 }
941 
944 {
946  for (int i=0; i<num_g; i++)
947  base_maps[i] = me->get_g_map(i);
948  return base_maps;
949  }
950 
953  const Epetra_Vector* v) const
954 {
956  if (v == NULL)
958  mp_block_map, x_map, mp_x_map, mp_comm));
959  else
961  mp_block_map, x_map, mp_x_map, mp_comm,
962  CV, *v));
963  return mp_x;
964 }
965 
968  const Epetra_MultiVector* v) const
969 {
971  if (v == NULL)
973  mp_block_map, x_map, mp_x_map, mp_comm,
974  num_vecs));
975  else
977  mp_block_map, x_map, mp_x_map, mp_comm,
978  CV, *v));
979  return mp_x;
980 }
981 
984  const Epetra_Vector* v) const
985 {
987  Teuchos::Array<int>::const_iterator it = std::find(mp_p_index_map.begin(),
988  mp_p_index_map.end(),
989  l);
990  TEUCHOS_TEST_FOR_EXCEPTION(it == mp_p_index_map.end(), std::logic_error,
991  "Error! Invalid p map index " << l);
992  int ll = it - mp_p_index_map.begin();
993  if (v == NULL)
995  mp_block_map, me->get_p_map(l),
996  mp_p_map[ll], mp_comm));
997  else
999  mp_block_map, me->get_p_map(l),
1000  mp_p_map[ll], mp_comm, CV, *v));
1001  return mp_p;
1002 }
1003 
1006  Epetra_DataAccess CV,
1007  const Epetra_MultiVector* v) const
1008 {
1010  Teuchos::Array<int>::const_iterator it = std::find(mp_p_index_map.begin(),
1011  mp_p_index_map.end(),
1012  l);
1013  TEUCHOS_TEST_FOR_EXCEPTION(it == mp_p_index_map.end(), std::logic_error,
1014  "Error! Invalid p map index " << l);
1015  int ll = it - mp_p_index_map.begin();
1016  if (v == NULL)
1018  mp_block_map, me->get_p_map(l),
1019  mp_p_map[ll], mp_comm, num_vecs));
1020  else
1022  mp_block_map, me->get_p_map(l),
1023  mp_p_map[ll], mp_comm, CV, *v));
1024  return mp_p;
1025 }
1026 
1029  const Epetra_Vector* v) const
1030 {
1032  if (v == NULL)
1034  mp_block_map, f_map, mp_f_map, mp_comm));
1035  else
1037  mp_block_map, f_map, mp_f_map, mp_comm,
1038  CV, *v));
1039  return mp_f;
1040 }
1041 
1044  int num_vecs,
1045  Epetra_DataAccess CV,
1046  const Epetra_MultiVector* v) const
1047 {
1049  if (v == NULL)
1051  mp_block_map, f_map, mp_f_map, mp_comm,
1052  num_vecs));
1053  else
1055  mp_block_map, f_map, mp_f_map, mp_comm,
1056  CV, *v));
1057  return mp_f;
1058 }
1059 
1062  const Epetra_Vector* v) const
1063 {
1065  Teuchos::Array<int>::const_iterator it = std::find(mp_g_index_map.begin(),
1066  mp_g_index_map.end(),
1067  l);
1068  TEUCHOS_TEST_FOR_EXCEPTION(it == mp_g_index_map.end(), std::logic_error,
1069  "Error! Invalid g map index " << l);
1070  int ll = it - mp_g_index_map.begin();
1071  if (v == NULL)
1073  mp_block_map,
1074  me->get_g_map(l),
1075  mp_g_map[ll], mp_comm));
1076  else
1078  mp_block_map,
1079  me->get_g_map(l),
1080  mp_g_map[ll], mp_comm, CV, *v));
1081  return mp_g;
1082 }
1083 
1086  Epetra_DataAccess CV,
1087  const Epetra_MultiVector* v) const
1088 {
1090  Teuchos::Array<int>::const_iterator it = std::find(mp_g_index_map.begin(),
1091  mp_g_index_map.end(),
1092  l);
1093  TEUCHOS_TEST_FOR_EXCEPTION(it == mp_g_index_map.end(), std::logic_error,
1094  "Error! Invalid g map index " << l);
1095  int ll = it - mp_g_index_map.begin();
1096  if (v == NULL)
1098  mp_block_map,
1099  me->get_g_map(l),
1100  mp_g_map[ll], mp_comm, num_vecs));
1101  else
1103  mp_block_map,
1104  me->get_g_map(l),
1105  mp_g_map[ll], mp_comm, CV, *v));
1106  return mp_g;
1107 }
Teuchos::RCP< const Stokhos::ProductEpetraVector > get_x_dot_mp_init() const
Factory for generating stochastic Galerkin preconditioners.
Teuchos::RCP< const Epetra_Map > mp_x_map
Block MP unknown map.
void setCoeffPtr(ordinal_type i, const Teuchos::RCP< coeff_type > &c)
Set coefficient i to c.
Teuchos::RCP< Stokhos::ProductEpetraMultiVector > create_g_mv_mp(int l, int num_vecs, Epetra_DataAccess CV=Copy, const Epetra_MultiVector *v=NULL) const
Create multi-point multi-vector using g map.
void evalModel(const InArgs &inArgs, const OutArgs &outArgs) const
Evaluate model on InArgs.
Teuchos::RCP< const Epetra_Vector > get_x_dot_init() const
Teuchos::RCP< Stokhos::ProductEpetraMultiVector > create_f_mv_mp(int num_vecs, Epetra_DataAccess CV=Copy, const Epetra_MultiVector *v=NULL) const
Create multi-point multi-vector using f map.
Teuchos::RCP< const Epetra_Map > get_f_map() const
Return residual vector map.
Teuchos::RCP< const Epetra_Map > get_g_map(int l) const
Return response map.
Teuchos::RCP< Epetra_Operator > create_DgDp_op(int j, int i) const
Create MP operator representing dg/dp.
Teuchos::RCP< Epetra_Operator > create_W() const
Create W = alpha*M + beta*J matrix.
A container class for products of Epetra_Vector&#39;s.
bool supports_x
Whether we support x (and thus f and W)
virtual Teuchos::RCP< Stokhos::MPPreconditioner > build(const Teuchos::RCP< const EpetraExt::MultiComm > &mp_comm, int num_mp_blocks, const Teuchos::RCP< const Epetra_Map > &base_map, const Teuchos::RCP< const Epetra_Map > &mp_map)
Build preconditioner operator.
Teuchos::RCP< const Stokhos::ProductEpetraVector > get_p_mp_init(int l) const
Return initial SG parameters.
void set_x_mp_init(const Stokhos::ProductEpetraVector &x_mp_in)
Set initial multi-point solution.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< Stokhos::ProductEpetraVector > create_x_mp(Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create multi-point vector using x map and owned mp map.
int num_p_mp
Number of multi-point parameter vectors.
int num_p
Number of parameter vectors of underlying model evaluator.
T * get() const
Teuchos::RCP< const Epetra_Vector > get_x_init() const
Return initial solution.
Teuchos::RCP< Stokhos::ProductEpetraMultiVector > create_x_mv_mp(int num_vecs, Epetra_DataAccess CV=Copy, const Epetra_MultiVector *v=NULL) const
Create multi-point vector using x map.
Teuchos::RCP< Stokhos::ProductEpetraVector > create_g_mp(int l, Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create multi-point vector using g map.
Teuchos::Array< Teuchos::RCP< const Epetra_Map > > mp_g_map
Block MP response map.
void set_x_dot_mp_init(const Stokhos::ProductEpetraVector &x_dot_mp_in)
Teuchos::Array< int > mp_p_index_map
Index map between block-p and p_mp maps.
Teuchos::Array< Teuchos::RCP< const Epetra_Map > > get_g_mp_base_maps() const
Get base maps of MP responses.
Teuchos::RCP< EpetraExt::ModelEvaluator::Preconditioner > create_WPrec() const
Create preconditioner operator.
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
Return array of parameter names.
virtual void setupOperator(const Teuchos::RCP< Stokhos::ProductEpetraOperator > &ops)
Setup operator.
int NumMyElements() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< Stokhos::ProductEpetraVector > create_f_mp(Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create multi-point vector using f map.
Teuchos::Array< int > get_g_mp_map_indices() const
Get indices of MP responses.
A container class for products of Epetra_Vector&#39;s.
Teuchos::RCP< EpetraExt::ModelEvaluator > me
Underlying model evaluator.
Teuchos::RCP< Stokhos::ProductEpetraOperator > W_mp_blocks
W multi-point components.
An Epetra operator representing the block stochastic Galerkin operator.
Teuchos::RCP< Stokhos::ProductEpetraVector > mp_x_dot_init
Teuchos::RCP< const Epetra_Map > f_map
Underlying residual map.
A container class for products of Epetra_Vector&#39;s.
Teuchos::RCP< Stokhos::ProductEpetraMultiVector > create_p_mv_mp(int l, int num_vecs, Epetra_DataAccess CV=Copy, const Epetra_MultiVector *v=NULL) const
Create multi-point vector using p map.
Teuchos::RCP< Epetra_Operator > create_DgDx_op(int j) const
Create MP operator representing dg/dx.
OutArgs createOutArgs() const
Create OutArgs.
Teuchos::RCP< Epetra_Operator > create_DgDx_dot_op(int j) const
Create MP operator representing dg/dxdot.
A container class storing products of Epetra_MultiVector&#39;s.
iterator end()
Teuchos::RCP< const Epetra_Map > get_p_map(int l) const
Return parameter vector map.
std::vector< T >::const_iterator const_iterator
Teuchos::RCP< const Epetra_Map > mp_block_map
Map for layout of parallel MP blocks.
MPModelEvaluator(const Teuchos::RCP< EpetraExt::ModelEvaluator > &me, const Teuchos::RCP< const EpetraExt::MultiComm > &mp_comm, const Teuchos::RCP< const Epetra_Map > &mp_block_map, const Teuchos::RCP< Teuchos::ParameterList > &params)
Teuchos::Array< Teuchos::RCP< ProductEpetraVector > > mp_p_init
MP initial p.
Teuchos::RCP< Epetra_Vector > my_x
x pointer for evaluating preconditioner
Teuchos::Array< int > mp_g_index_map
Index map between block-g and g_mp maps.
Teuchos::RCP< const Epetra_Map > mp_f_map
Block MP residual map.
Teuchos::RCP< const Stokhos::ProductEpetraVector > get_x_mp_init() const
Return initial SG x.
void push_back(const value_type &x)
Teuchos::RCP< const Epetra_Map > x_map
Underlying unknown map.
virtual Teuchos::RCP< Stokhos::ProductEpetraOperator > getMPOps()
Get multi-point ops.
Teuchos::Array< int > get_p_mp_map_indices() const
Get indices of MP parameters.
int num_g
Number of response vectors of underlying model evaluator.
int num_g_mp
Number of multi-point response vectors.
size_type size() const
virtual void setupPreconditioner(const Teuchos::RCP< Stokhos::BlockDiagonalOperator > &mp_op, const Epetra_Vector &x)=0
Setup preconditioner.
An abstract class to represent a generic stochastic Galerkin preconditioner as an Epetra_Operator...
InArgs createInArgs() const
Create InArgs.
Teuchos::RCP< const Epetra_Map > get_x_map() const
Return solution vector map.
Teuchos::RCP< ProductEpetraMultiVector > productMultiVector() const
Get product multi vector.
Epetra_DataAccess
Teuchos::RCP< const EpetraExt::MultiComm > mp_comm
Parallel MP communicator.
std::vector< T >::iterator iterator
Teuchos::Array< Teuchos::RCP< const Epetra_Map > > mp_p_map
Block MP parameter map.
unsigned int num_mp_blocks
Number of blocks.
void set_p_mp_init(int i, const Stokhos::ProductEpetraVector &p_mp_in)
Set initial multi-point parameter.
iterator begin()
Teuchos::RCP< const Epetra_Vector > get_p_init(int l) const
Return initial parameters.
Teuchos::RCP< Stokhos::ProductEpetraVector > mp_x_init
MP initial x.
ScalarType g(const Teuchos::Array< ScalarType > &x, const ScalarType &y)
Teuchos::RCP< Epetra_Operator > create_DfDp_op(int i) const
Create MP operator representing df/dp.
Teuchos::Array< Teuchos::RCP< Teuchos::Array< std::string > > > mp_p_names
MP coefficient parameter names.
Teuchos::RCP< Stokhos::ProductEpetraVector > create_p_mp(int l, Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create multi-point vector using p map.