Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
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
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"
35#include <Teuchos_DefaultMpiComm.hpp>
36
37namespace Tempus_Test {
38
39// Constructor
40
41template <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
60 TEUCHOS_ASSERT(nonnull(comm_));
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 =
97 Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid();
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
108
109 x0_ = ::Thyra::createMember(xSpace_);
110 V_S(x0_.ptr(), ST::zero());
111
112 // Initialize the graph for W CrsMatrix object
114
115 // Create the nodal coordinates
116 nodeCoordinates_ = Teuchos::rcp(new tpetra_vec(xOwnedMap_));
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;
149 nominalValues_.set_x(x0_);
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
157template <typename SC, typename LO, typename GO, typename Node>
158Teuchos::RCP<const Tpetra::CrsGraph<LO, GO, 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
189template <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
196 Thyra::DetachedVectorView<SC> x0(x0_);
197 x0.sv().values()().assign(x0_in);
198}
199
200template <typename SC, typename LO, typename GO, typename Node>
202 bool showGetInvalidArg)
203{
204 showGetInvalidArg_ = showGetInvalidArg;
205}
206
207template <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
217template <typename SC, typename LO, typename GO, typename Node>
218Teuchos::RCP<const Thyra::VectorSpaceBase<SC>>
220{
221 return xSpace_;
222}
223
224template <typename SC, typename LO, typename GO, typename Node>
225Teuchos::RCP<const Thyra::VectorSpaceBase<SC>>
227{
228 return fSpace_;
229}
230
231template <typename SC, typename LO, typename GO, typename Node>
232Thyra::ModelEvaluatorBase::InArgs<SC>
234{
235 return nominalValues_;
236}
237
238template <typename SC, typename LO, typename GO, typename Node>
239Teuchos::RCP<Thyra::LinearOpWithSolveBase<double>>
241{
242 auto W_factory = this->get_W_factory();
243
244 TEUCHOS_TEST_FOR_EXCEPTION(
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
253template <typename SC, typename LO, typename GO, typename Node>
254Teuchos::RCP<Thyra::LinearOpBase<SC>>
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
262template <typename SC, typename LO, typename GO, typename Node>
263Teuchos::RCP<::Thyra::PreconditionerBase<SC>>
265{
266 auto W_op = create_W_op();
267 auto prec = Teuchos::rcp(new Thyra::DefaultPreconditioner<SC>);
268
269 prec->initializeRight(W_op);
270
271 return prec;
272}
273
274template <typename SC, typename LO, typename GO, typename Node>
275Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<SC>>
277{
278 return wFactory_;
279}
280
281template <typename SC, typename LO, typename GO, typename Node>
282Thyra::ModelEvaluatorBase::InArgs<SC>
284{
285 return prototypeInArgs_;
286}
287
288// Private functions overridden from ModelEvaluatorDefaultBase
289
290template <typename SC, typename LO, typename GO, typename Node>
291Thyra::ModelEvaluatorBase::OutArgs<SC>
293{
294 return prototypeOutArgs_;
295}
296
297template <typename SC, typename LO, typename GO, typename Node>
299 const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
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
323 RCP<tpetra_matrix> J;
324 if (nonnull(W_out)) {
325 auto W_epetra = tpetra_extract::getTpetraOperator(W_out);
326 J = rcp_dynamic_cast<tpetra_matrix>(W_epetra);
327 TEUCHOS_ASSERT(nonnull(J));
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< Thyra::LinearOpWithSolveBase< double > > create_W() const
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)
Tpetra::CrsGraph< LO, GO, Node > tpetra_graph
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > get_x_space() const
void set_x0(const Teuchos::ArrayView< const SC > &x0)
Teuchos::RCP< const tpetra_map > xGhostedMap_
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > get_f_space() const
Teuchos::RCP< const tpetra_map > fOwnedMap_
virtual Teuchos::RCP< const Tpetra::CrsGraph< LO, GO, Node > > createGraph()
Teuchos::RCP<::Thyra::VectorBase< SC > > x0_
Teuchos::RCP< const tpetra_map > xOwnedMap_
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > fSpace_
void set_W_factory(const Teuchos::RCP< const ::Thyra::LinearOpWithSolveFactoryBase< SC > > &W_factory)
Tpetra::CrsMatrix< SC, LO, GO, Node > tpetra_matrix
::Thyra::ModelEvaluatorBase::InArgs< SC > getNominalValues() const
Teuchos::RCP< const tpetra_graph > wGraph_
Teuchos::RCP<::Thyra::PreconditionerBase< SC > > create_W_prec() const
const Teuchos::RCP< const Teuchos::Comm< int > > comm_
void evalModelImpl(const ::Thyra::ModelEvaluatorBase::InArgs< SC > &inArgs, const ::Thyra::ModelEvaluatorBase::OutArgs< SC > &outArgs) const
Teuchos::RCP< tpetra_vec > nodeCoordinates_
Tpetra::Vector< SC, LO, GO, Node > tpetra_vec
void setShowGetInvalidArgs(bool showGetInvalidArg)
::Thyra::ModelEvaluatorBase::InArgs< SC > nominalValues_
Teuchos::RCP<::Thyra::LinearOpBase< SC > > create_W_op() const
::Thyra::ModelEvaluatorBase::InArgs< SC > createInArgs() const
Teuchos::RCP< const ::Thyra::VectorSpaceBase< SC > > xSpace_
::Thyra::ModelEvaluatorBase::OutArgs< SC > prototypeOutArgs_
Teuchos::RCP< const Tpetra::Import< LO, GO, Node > > importer_
Tpetra::Map< LO, GO, Node > tpetra_map
::Thyra::ModelEvaluatorBase::InArgs< SC > prototypeInArgs_
Teuchos::RCP< const ::Thyra::LinearOpWithSolveFactoryBase< SC > > get_W_factory() const
::Thyra::ModelEvaluatorBase::OutArgs< SC > createOutArgsImpl() const