Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CDR_Model_Tpetra_impl.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_CDR_MODEL_TPETRA_IMPL_HPP
11 #define TEMPUS_CDR_MODEL_TPETRA_IMPL_HPP
12 
13 #include "CDR_Model_Functors.hpp"
14 
15 // Thyra support
16 #include "Kokkos_Core_fwd.hpp"
17 #include "Teuchos_Assert.hpp"
18 #include "Thyra_DefaultSerialDenseLinearOpWithSolveFactory.hpp"
19 #include "Thyra_DefaultSpmdVectorSpace.hpp"
20 #include "Thyra_DetachedMultiVectorView.hpp"
21 #include "Thyra_DetachedVectorView.hpp"
22 #include "Thyra_MultiVectorStdOps.hpp"
23 #include "Thyra_PreconditionerBase.hpp"
24 #include "Thyra_VectorStdOps.hpp"
25 
26 // Tpetra support
27 #include "Thyra_TpetraLinearOp.hpp"
28 #include "Thyra_TpetraThyraWrappers.hpp"
29 #include "Tpetra_CrsGraph_def.hpp"
30 #include "Tpetra_CrsMatrix_def.hpp"
31 #include "Tpetra_Import_def.hpp"
32 #include "Tpetra_Map_def.hpp"
33 #include "Tpetra_Vector_def.hpp"
34 #include "impl/Kokkos_HostThreadTeam.hpp"
36 
37 namespace Tempus_Test {
38 
39 // Constructor
40 
41 template <typename SC, typename LO, typename GO, typename Node>
43  const Teuchos::RCP<const Teuchos::Comm<int>> &comm,
44  const GO numGlobalElements, const SC zMin, const SC zMax, const SC a,
45  const SC k)
46  : comm_(comm),
47  numGlobalElements_(numGlobalElements),
48  zMin_(zMin),
49  zMax_(zMax),
50  a_(a),
51  k_(k),
52  showGetInvalidArg_(false)
53 {
54  using Teuchos::RCP;
55  using Teuchos::rcp;
56  using ::Thyra::VectorBase;
57  using MEB = ::Thyra::ModelEvaluatorBase;
58  using ST = Teuchos::ScalarTraits<SC>;
59 
61 
62  const auto num_nodes = numGlobalElements_ + 1;
63  const auto myRank = comm_->getRank();
64 
65  // owned space
66  xOwnedMap_ = rcp(new tpetra_map(num_nodes, 0, comm_));
67  xSpace_ = ::Thyra::createVectorSpace<SC, LO, GO, Node>(xOwnedMap_);
68 
69  // ghosted space
70  if (comm_->getSize() == 1) {
72  }
73  else {
74  LO overlapNumMyElements;
75  GO overlapGetMinGLobalIndex;
76  overlapNumMyElements = xOwnedMap_->getLocalNumElements() + 2;
77  if ((myRank == 0) || (myRank == (comm_->getSize() - 1))) {
78  overlapNumMyElements--;
79  }
80 
81  if (myRank == 0) {
82  overlapGetMinGLobalIndex = xOwnedMap_->getMinGlobalIndex();
83  }
84  else {
85  overlapGetMinGLobalIndex = xOwnedMap_->getMinGlobalIndex() - 1;
86  }
87 
88  Teuchos::Array<GO> overlapMyGlobalNodes(overlapNumMyElements);
89 
90  GO getGlobalElement = overlapGetMinGLobalIndex;
91  for (auto &globalElem : overlapMyGlobalNodes) {
92  globalElem = overlapGetMinGLobalIndex;
93  ++getGlobalElement;
94  }
95 
96  const auto invalid =
98  xGhostedMap_ =
99  Teuchos::rcp(new tpetra_map(invalid, overlapMyGlobalNodes, 0, comm_));
100  }
101 
102  importer_ =
103  Teuchos::rcp(new Tpetra::Import<LO, GO, Node>(xOwnedMap_, xGhostedMap_));
104 
105  // residual space
107  fSpace_ = xSpace_;
108 
109  x0_ = ::Thyra::createMember(xSpace_);
110  V_S(x0_.ptr(), ST::zero());
111 
112  // Initialize the graph for W CrsMatrix object
113  wGraph_ = createGraph();
114 
115  // Create the nodal coordinates
117 
118  auto length = zMax_ - zMin_;
119  auto dx = length / static_cast<SC>(numGlobalElements_ - 1);
120  const auto minGI = xOwnedMap_->getMinGlobalIndex();
121  {
122  CoordFiller<tpetra_vec> coordFiller(*nodeCoordinates_, zMin_, dx, minGI);
123  Kokkos::parallel_for("coords_fill", xOwnedMap_->getLocalNumElements(),
124  coordFiller);
125 
126  Kokkos::fence();
127  }
128 
129  MEB::InArgsSetup<SC> inArgs;
130  inArgs.setModelEvalDescription(this->description());
131  inArgs.setSupports(MEB::IN_ARG_t);
132  inArgs.setSupports(MEB::IN_ARG_x);
133  inArgs.setSupports(MEB::IN_ARG_beta);
134  inArgs.setSupports(MEB::IN_ARG_x_dot);
135  inArgs.setSupports(MEB::IN_ARG_alpha);
136  prototypeInArgs_ = inArgs;
137 
138  MEB::OutArgsSetup<SC> outArgs;
139  outArgs.setModelEvalDescription(this->description());
140  outArgs.setSupports(MEB::OUT_ARG_f);
141  outArgs.setSupports(MEB::OUT_ARG_W);
142  outArgs.setSupports(MEB::OUT_ARG_W_op);
143  outArgs.setSupports(MEB::OUT_ARG_W_prec);
144 
145  prototypeOutArgs_ = outArgs;
146 
147  // Setup nominal values
148  nominalValues_ = inArgs;
150  auto x_dot_init = Thyra::createMember(this->get_x_space());
151  Thyra::put_scalar(SC(0.0), x_dot_init.ptr());
152  nominalValues_.set_x_dot(x_dot_init);
153 }
154 
155 // Initializers/Accessors
156 
157 template <typename SC, typename LO, typename GO, typename Node>
160 {
161  auto W_graph = Teuchos::rcp(new tpetra_graph(xOwnedMap_, 5));
162  W_graph->resumeFill();
163 
164  auto overlapNumMyElements =
165  static_cast<LO>(xGhostedMap_->getLocalNumElements());
166 
167  // Loop Over # of Finite Elements on Processor
168  for (LO elem = 0; elem < overlapNumMyElements - 1; elem++) {
169  // Loop over Nodes in Element
170  for (LO i = 0; i < 2; i++) {
171  auto row = xGhostedMap_->getGlobalElement(elem + i);
172 
173  // Loop over Trial Functions
174  for (LO j = 0; j < 2; j++) {
175  // If this row is owned by current processor, add the index
176  if (xOwnedMap_->isNodeGlobalElement(row)) {
177  auto colIndex = xGhostedMap_->getGlobalElement(elem + j);
178  Teuchos::ArrayView<const GO> column(&colIndex, 1);
179  W_graph->insertGlobalIndices(row, column);
180  }
181  }
182  }
183  }
184  W_graph->fillComplete();
185 
186  return W_graph;
187 }
188 
189 template <typename SC, typename LO, typename GO, typename Node>
191  const Teuchos::ArrayView<const SC> &x0_in)
192 {
193 #ifdef TEUCHOS_DEBUG
194  TEUCHOS_ASSERT_EQUALITY(xSpace_->dim(), x0_in.size());
195 #endif
197  x0.sv().values()().assign(x0_in);
198 }
199 
200 template <typename SC, typename LO, typename GO, typename Node>
202  bool showGetInvalidArg)
203 {
204  showGetInvalidArg_ = showGetInvalidArg;
205 }
206 
207 template <typename SC, typename LO, typename GO, typename Node>
209  const Teuchos::RCP<const ::Thyra::LinearOpWithSolveFactoryBase<SC>>
210  &W_factory)
211 {
212  wFactory_ = W_factory;
213 }
214 
215 // Public functions overridden from ModelEvaluator
216 
217 template <typename SC, typename LO, typename GO, typename Node>
220 {
221  return xSpace_;
222 }
223 
224 template <typename SC, typename LO, typename GO, typename Node>
227 {
228  return fSpace_;
229 }
230 
231 template <typename SC, typename LO, typename GO, typename Node>
234 {
235  return nominalValues_;
236 }
237 
238 template <typename SC, typename LO, typename GO, typename Node>
241 {
242  auto W_factory = this->get_W_factory();
243 
245  is_null(W_factory), std::runtime_error,
246  "W_factory in CDR_Model_Tpetra has a null W_factory!");
247 
248  auto matrix = this->create_W_op();
249 
250  return Thyra::linearOpWithSolve<SC>(*W_factory, matrix);
251 }
252 
253 template <typename SC, typename LO, typename GO, typename Node>
256 {
257  auto W_tpetra = Teuchos::rcp(new tpetra_matrix(wGraph_));
258 
259  return Thyra::tpetraLinearOp<SC, LO, GO, Node>(fSpace_, xSpace_, W_tpetra);
260 }
261 
262 template <typename SC, typename LO, typename GO, typename Node>
265 {
266  auto W_op = create_W_op();
268 
269  prec->initializeRight(W_op);
270 
271  return prec;
272 }
273 
274 template <typename SC, typename LO, typename GO, typename Node>
277 {
278  return wFactory_;
279 }
280 
281 template <typename SC, typename LO, typename GO, typename Node>
284 {
285  return prototypeInArgs_;
286 }
287 
288 // Private functions overridden from ModelEvaluatorDefaultBase
289 
290 template <typename SC, typename LO, typename GO, typename Node>
293 {
294  return prototypeOutArgs_;
295 }
296 
297 template <typename SC, typename LO, typename GO, typename Node>
300  const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs) const
301 {
302  using Teuchos::RCP;
303  using Teuchos::rcp;
304  using Teuchos::rcp_dynamic_cast;
305 
306  TEUCHOS_ASSERT(nonnull(inArgs.get_x()));
307  TEUCHOS_ASSERT(nonnull(inArgs.get_x_dot()));
308 
309  auto f_out = outArgs.get_f();
310  auto W_out = outArgs.get_W_op();
311  auto W_prec_out = outArgs.get_W_prec();
312 
313  if (nonnull(f_out) || nonnull(W_out) || nonnull(W_prec_out)) {
314  // ****************
315  // Get the underlying Tpetra objects
316  // ****************
317 
318  RCP<tpetra_vec> f;
319  if (nonnull(f_out)) {
320  f = tpetra_extract::getTpetraVector(outArgs.get_f());
321  }
322 
324  if (nonnull(W_out)) {
325  auto W_epetra = tpetra_extract::getTpetraOperator(W_out);
326  J = rcp_dynamic_cast<tpetra_matrix>(W_epetra);
328  }
329 
330  RCP<tpetra_matrix> M_inv;
331  if (nonnull(W_prec_out)) {
332  auto M_tpetra = tpetra_extract::getTpetraOperator(
333  W_prec_out->getNonconstRightPrecOp());
334  M_inv = rcp_dynamic_cast<tpetra_matrix>(M_tpetra);
335  TEUCHOS_ASSERT(nonnull(M_inv));
336  jDiag_ = Teuchos::rcp(new tpetra_vec(xOwnedMap_));
337  jDiag_->putScalar(0.0);
338  }
339 
340  // ****************
341  // Create ghosted objects
342  // ****************
343 
344  // Set the boundary condition directly. Works for both x and xDot solves.
345  if (comm_->getRank() == 0) {
346  auto x = Teuchos::rcp_const_cast<Thyra::VectorBase<SC>>(inArgs.get_x());
347  auto xVec = tpetra_extract::getTpetraVector(x);
348  auto xView = xVec->getLocalViewHost(Tpetra::Access::ReadWrite);
349  xView(0, 0) = 1.0;
350  }
351 
352  if (is_null(uPtr_)) {
353  uPtr_ = Teuchos::rcp(new tpetra_vec(xGhostedMap_));
354  }
355 
356  uPtr_->doImport(*(tpetra_extract::getConstTpetraVector(inArgs.get_x())),
357  *importer_, Tpetra::INSERT);
358 
359  if (is_null(uDotPtr_)) {
360  uDotPtr_ = Teuchos::rcp(new tpetra_vec(xGhostedMap_));
361  }
362 
363  uDotPtr_->doImport(
364  *(tpetra_extract::getConstTpetraVector(inArgs.get_x_dot())), *importer_,
365  Tpetra::INSERT);
366 
367  if (is_null(xPtr_)) {
368  xPtr_ = Teuchos::rcp(new tpetra_vec(xGhostedMap_));
369  xPtr_->doImport(*nodeCoordinates_, *importer_, Tpetra::INSERT);
370  }
371 
372  auto overlapNumMyElements =
373  static_cast<LO>(xGhostedMap_->getLocalNumElements());
374 
375  // Zero out the objects that will be filled
376  if (nonnull(f)) {
377  f->putScalar(0.0);
378  }
379 
380  if (nonnull(J)) {
381  J->setAllToScalar(0.0);
382  }
383 
384  if (nonnull(M_inv)) {
385  M_inv->setAllToScalar(0.0);
386  }
387 
388  if (nonnull(f)) {
389  DfDp2EvaluatorFunctor<tpetra_vec> fFunctor(*f, *xPtr_, *uPtr_, *uDotPtr_,
390  comm_->getRank(), a_, k_);
391  Kokkos::parallel_for("DfDp2EvaluatorFunctor", overlapNumMyElements - 1,
392  fFunctor);
393  Kokkos::fence();
394  }
395 
396  const auto alpha = inArgs.get_alpha();
397  const auto beta = inArgs.get_beta();
398 
399  if (nonnull(J)) {
401  *J, *xPtr_, *uPtr_, *uDotPtr_, comm_->getRank(), a_, k_, alpha, beta);
402 
403  J->resumeFill();
404  Kokkos::parallel_for("JacobianEvaluatorFunctor", overlapNumMyElements - 1,
405  jFunctor);
406  Kokkos::fence();
407  J->fillComplete();
408  }
409 
410  if (nonnull(M_inv)) {
412  *M_inv, *xPtr_, *uPtr_, *uDotPtr_, comm_->getRank(), a_, k_, alpha,
413  beta);
414 
415  M_inv->resumeFill();
416  Kokkos::parallel_for("PreconditionerEvaluatorFunctor",
417  overlapNumMyElements - 1, mFunctor);
418  Kokkos::fence();
419  M_inv->fillComplete();
420  }
421 
422  if (nonnull(M_inv)) {
423  // Invert the Jacobian diagonal for the preconditioner
424  auto &diag = *jDiag_;
425  M_inv->getLocalDiagCopy(diag);
426  diag.reciprocal(diag);
427 
428  M_inv->rightScale(diag);
429  M_inv->rightScale(diag);
430  }
431  }
432 }
433 
434 } // namespace Tempus_Test
435 
436 #endif // TEMPUS_CDR_MODEL_TPETRA_IMPL_HPP
Teuchos::RCP< const tpetra_map > xGhostedMap_
Teuchos::RCP<::Thyra::VectorBase< SC > > x0_
void evalModelImpl(const ::Thyra::ModelEvaluatorBase::InArgs< SC > &inArgs, const ::Thyra::ModelEvaluatorBase::OutArgs< SC > &outArgs) const
::Thyra::ModelEvaluatorBase::InArgs< SC > createInArgs() const
bool is_null(const boost::shared_ptr< T > &p)
::Thyra::ModelEvaluatorBase::InArgs< SC > prototypeInArgs_
RCP< const VectorBase< Scalar > > get_x_dot() const
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > xSpace_
Teuchos::RCP< const Tpetra::Import< LO, GO, Node > > importer_
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
size_type size() const
Teuchos::RCP<::Thyra::PreconditionerBase< SC > > create_W_prec() const
Evaluation< VectorBase< Scalar > > get_f() const
Tpetra::CrsGraph< LO, GO, Node > tpetra_graph
void set_x0(const Teuchos::ArrayView< const SC > &x0)
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > get_f_space() const
::Thyra::ModelEvaluatorBase::OutArgs< SC > createOutArgsImpl() const
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > get_x_space() const
void set_x(const RCP< const VectorBase< Scalar > > &x)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > fSpace_
void setShowGetInvalidArgs(bool showGetInvalidArg)
Teuchos::RCP< const tpetra_graph > wGraph_
Tpetra::Vector< SC, LO, GO, Node > tpetra_vec
Ptr< T > ptr() const
Teuchos::RCP< Thyra::LinearOpWithSolveBase< double > > create_W() const
virtual std::string description() const
Teuchos::RCP< tpetra_vec > nodeCoordinates_
void set_x_dot(const RCP< const VectorBase< Scalar > > &x_dot)
Teuchos::RCP< const ::Thyra::LinearOpWithSolveFactoryBase< SC > > get_W_factory() const
void set_W_factory(const Teuchos::RCP< const ::Thyra::LinearOpWithSolveFactoryBase< SC >> &W_factory)
Teuchos::RCP< const tpetra_map > xOwnedMap_
bool nonnull(const boost::shared_ptr< T > &p)
Tpetra::Map< LO, GO, Node > tpetra_map
Teuchos::RCP< const tpetra_map > fOwnedMap_
const Teuchos::RCP< const Teuchos::Comm< int > > comm_
RCP< PreconditionerBase< Scalar > > get_W_prec() const
#define TEUCHOS_ASSERT(assertion_test)
::Thyra::ModelEvaluatorBase::InArgs< SC > nominalValues_
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
::Thyra::ModelEvaluatorBase::OutArgs< SC > prototypeOutArgs_
Tpetra::CrsMatrix< SC, LO, GO, Node > tpetra_matrix
RCP< LinearOpBase< Scalar > > get_W_op() const
Teuchos::RCP<::Thyra::LinearOpBase< SC > > create_W_op() const
RCP< const VectorBase< Scalar > > get_x() const
virtual Teuchos::RCP< const Tpetra::CrsGraph< LO, GO, Node > > createGraph()
CDR_Model_Tpetra(const Teuchos::RCP< const Teuchos::Comm< int >> &comm, const GO numGlobalElements, const SC zMin, const SC zMax, const SC a, const SC k)
::Thyra::ModelEvaluatorBase::InArgs< SC > getNominalValues() const