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