9 #ifndef VERTEXCFD_CDR_MODEL_IMPL_HPP
10 #define VERTEXCFD_CDR_MODEL_IMPL_HPP
13 #include "Thyra_DefaultSerialDenseLinearOpWithSolveFactory.hpp"
14 #include "Thyra_DefaultSpmdVectorSpace.hpp"
15 #include "Thyra_DetachedMultiVectorView.hpp"
16 #include "Thyra_DetachedVectorView.hpp"
17 #include "Thyra_MultiVectorStdOps.hpp"
18 #include "Thyra_PreconditionerBase.hpp"
19 #include "Thyra_VectorStdOps.hpp"
22 #include "Epetra_Comm.h"
23 #include "Epetra_CrsGraph.h"
24 #include "Epetra_CrsMatrix.h"
25 #include "Epetra_Import.h"
26 #include "Epetra_Map.h"
27 #include "Epetra_Vector.h"
28 #include "Thyra_EpetraLinearOp.hpp"
29 #include "Thyra_EpetraThyraWrappers.hpp"
30 #include "Thyra_get_Epetra_Operator.hpp"
38 template<
class Scalar>
39 CDR_Model<Scalar>::CDR_Model(
const Teuchos::RCP<const Epetra_Comm>& comm,
40 const int num_global_elements,
46 , num_global_elements_(num_global_elements)
51 , showGetInvalidArg_(false)
55 using ::Thyra::VectorBase;
56 typedef ::Thyra::ModelEvaluatorBase MEB;
57 typedef Teuchos::ScalarTraits<Scalar> ST;
59 TEUCHOS_ASSERT(nonnull(comm_));
61 const int num_nodes = num_global_elements_ + 1;
64 x_owned_map_ = rcp(
new Epetra_Map(num_nodes, 0, *comm_));
65 x_space_ = ::Thyra::create_VectorSpace(x_owned_map_);
68 if (comm_->NumProc() == 1)
70 x_ghosted_map_ = x_owned_map_;
74 int OverlapNumMyElements;
76 OverlapNumMyElements = x_owned_map_->NumMyElements() + 2;
77 if ((comm_->MyPID() == 0) || (comm_->MyPID() == (comm_->NumProc() - 1)))
78 OverlapNumMyElements--;
80 if (comm_->MyPID() == 0)
81 OverlapMinMyGID = x_owned_map_->MinMyGID();
83 OverlapMinMyGID = x_owned_map_->MinMyGID() - 1;
85 int* OverlapMyGlobalElements =
new int[OverlapNumMyElements];
87 for (
int i = 0; i < OverlapNumMyElements; i++)
88 OverlapMyGlobalElements[i] = OverlapMinMyGID + i;
90 x_ghosted_map_ = Teuchos::rcp(
new Epetra_Map(
91 -1, OverlapNumMyElements, OverlapMyGlobalElements, 0, *comm_));
93 delete[] OverlapMyGlobalElements;
96 importer_ = Teuchos::rcp(
new Epetra_Import(*x_ghosted_map_, *x_owned_map_));
99 f_owned_map_ = x_owned_map_;
102 x0_ = ::Thyra::createMember(x_space_);
103 V_S(x0_.ptr(), ST::zero());
109 W_graph_ = createGraph();
113 node_coordinates_ = Teuchos::rcp(
new Epetra_Vector(*x_owned_map_));
114 Scalar length = z_max_ - z_min_;
115 Scalar dx = length / ((double)num_global_elements_ - 1);
116 for (
int i = 0; i < x_owned_map_->NumMyElements(); i++)
118 (*node_coordinates_)[i]
119 = z_min_ + dx * ((double)x_owned_map_->MinMyGID() + i);
123 MEB::InArgsSetup<Scalar> inArgs;
124 inArgs.setModelEvalDescription(this->description());
125 inArgs.setSupports(MEB::IN_ARG_t);
126 inArgs.setSupports(MEB::IN_ARG_x);
127 inArgs.setSupports(MEB::IN_ARG_beta);
128 inArgs.setSupports(MEB::IN_ARG_x_dot);
129 inArgs.setSupports(MEB::IN_ARG_alpha);
130 prototypeInArgs_ = inArgs;
132 MEB::OutArgsSetup<Scalar> outArgs;
133 outArgs.setModelEvalDescription(this->description());
134 outArgs.setSupports(MEB::OUT_ARG_f);
135 outArgs.setSupports(MEB::OUT_ARG_W);
136 outArgs.setSupports(MEB::OUT_ARG_W_op);
137 outArgs.setSupports(MEB::OUT_ARG_W_prec);
143 prototypeOutArgs_ = outArgs;
146 nominalValues_ = inArgs;
147 nominalValues_.set_x(x0_);
148 auto x_dot_init = Thyra::createMember(this->get_x_space());
149 Thyra::put_scalar(Scalar(0.0), x_dot_init.ptr());
150 nominalValues_.set_x_dot(x_dot_init);
155 template<
class Scalar>
156 Teuchos::RCP<Epetra_CrsGraph> CDR_Model<Scalar>::createGraph()
158 Teuchos::RCP<Epetra_CrsGraph> W_graph;
161 W_graph = Teuchos::rcp(
new Epetra_CrsGraph(Copy, *x_owned_map_, 5));
166 const int OverlapNumMyElements = x_ghosted_map_->NumMyElements();
169 for (
int ne = 0; ne < OverlapNumMyElements - 1; ne++)
172 for (
int i = 0; i < 2; i++)
174 row = x_ghosted_map_->GID(ne + i);
177 for (
int j = 0; j < 2; j++)
180 if (x_owned_map_->MyGID(row))
182 column = x_ghosted_map_->GID(ne + j);
183 W_graph->InsertGlobalIndices(row, 1, &column);
188 W_graph->FillComplete();
192 template<
class Scalar>
193 void CDR_Model<Scalar>::set_x0(
const Teuchos::ArrayView<const Scalar>& x0_in)
196 TEUCHOS_ASSERT_EQUALITY(x_space_->dim(), x0_in.size());
198 Thyra::DetachedVectorView<Scalar> x0(x0_);
199 x0.sv().values()().assign(x0_in);
202 template<
class Scalar>
203 void CDR_Model<Scalar>::setShowGetInvalidArgs(
bool showGetInvalidArg)
205 showGetInvalidArg_ = showGetInvalidArg;
208 template<
class Scalar>
209 void CDR_Model<Scalar>::set_W_factory(
210 const Teuchos::RCP<const ::Thyra::LinearOpWithSolveFactoryBase<Scalar>>&
213 W_factory_ = W_factory;
218 template<
class Scalar>
219 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar>>
220 CDR_Model<Scalar>::get_x_space()
const
225 template<
class Scalar>
226 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar>>
227 CDR_Model<Scalar>::get_f_space()
const
232 template<
class Scalar>
233 Thyra::ModelEvaluatorBase::InArgs<Scalar>
234 CDR_Model<Scalar>::getNominalValues()
const
236 return nominalValues_;
239 template<
class Scalar>
240 Teuchos::RCP<Thyra::LinearOpWithSolveBase<double>>
241 CDR_Model<Scalar>::create_W()
const
243 const Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<double>> W_factory
244 = this->get_W_factory();
246 TEUCHOS_TEST_FOR_EXCEPTION(is_null(W_factory),
248 "W_factory in CDR_Model has a null W_factory!");
250 const Teuchos::RCP<Thyra::LinearOpBase<double>> matrix
251 = this->create_W_op();
253 Teuchos::RCP<Thyra::LinearOpWithSolveBase<double>> W
254 = Thyra::linearOpWithSolve<double>(*W_factory, matrix);
259 template<
class Scalar>
260 Teuchos::RCP<Thyra::LinearOpBase<Scalar>> CDR_Model<Scalar>::create_W_op()
const
262 const Teuchos::RCP<Epetra_CrsMatrix> W_epetra
263 = Teuchos::rcp(
new Epetra_CrsMatrix(::Copy, *W_graph_));
265 return Thyra::nonconstEpetraLinearOp(W_epetra);
268 template<
class Scalar>
269 Teuchos::RCP<::Thyra::PreconditionerBase<Scalar>>
270 CDR_Model<Scalar>::create_W_prec()
const
272 const Teuchos::RCP<Epetra_CrsMatrix> W_epetra
273 = Teuchos::rcp(
new Epetra_CrsMatrix(::Copy, *W_graph_));
275 const Teuchos::RCP<Thyra::LinearOpBase<Scalar>> W_op
276 = Thyra::nonconstEpetraLinearOp(W_epetra);
278 const Teuchos::RCP<Thyra::DefaultPreconditioner<Scalar>> prec
279 = Teuchos::rcp(
new Thyra::DefaultPreconditioner<Scalar>);
281 prec->initializeRight(W_op);
286 template<
class Scalar>
287 Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar>>
288 CDR_Model<Scalar>::get_W_factory()
const
293 template<
class Scalar>
294 Thyra::ModelEvaluatorBase::InArgs<Scalar>
295 CDR_Model<Scalar>::createInArgs()
const
297 return prototypeInArgs_;
302 template<
class Scalar>
303 Thyra::ModelEvaluatorBase::OutArgs<Scalar>
304 CDR_Model<Scalar>::createOutArgsImpl()
const
306 return prototypeOutArgs_;
309 template<
class Scalar>
310 void CDR_Model<Scalar>::evalModelImpl(
311 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
312 const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs)
const
316 using Teuchos::rcp_dynamic_cast;
318 TEUCHOS_ASSERT(nonnull(inArgs.get_x()));
319 TEUCHOS_ASSERT(nonnull(inArgs.get_x_dot()));
323 const RCP<Thyra::VectorBase<Scalar>> f_out = outArgs.get_f();
324 const RCP<Thyra::LinearOpBase<Scalar>> W_out = outArgs.get_W_op();
325 const RCP<Thyra::PreconditionerBase<Scalar>> W_prec_out
326 = outArgs.get_W_prec();
328 if (nonnull(f_out) || nonnull(W_out) || nonnull(W_prec_out))
334 RCP<Epetra_Vector> f;
337 f = Thyra::get_Epetra_Vector(*f_owned_map_, outArgs.get_f());
340 RCP<Epetra_CrsMatrix> J;
343 const RCP<Epetra_Operator> W_epetra
344 = Thyra::get_Epetra_Operator(*W_out);
345 J = rcp_dynamic_cast<Epetra_CrsMatrix>(W_epetra);
346 TEUCHOS_ASSERT(nonnull(J));
349 RCP<Epetra_CrsMatrix> M_inv;
350 if (nonnull(W_prec_out))
352 const RCP<Epetra_Operator> M_epetra = Thyra::get_Epetra_Operator(
353 *(W_prec_out->getNonconstRightPrecOp()));
354 M_inv = rcp_dynamic_cast<Epetra_CrsMatrix>(M_epetra);
355 TEUCHOS_ASSERT(nonnull(M_inv));
356 J_diagonal_ = Teuchos::rcp(
new Epetra_Vector(*x_owned_map_));
365 if (comm_->MyPID() == 0)
367 const RCP<Thyra::VectorBase<Scalar>> x
368 = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar>>(
370 (*Thyra::get_Epetra_Vector(*x_owned_map_, x))[0] = 1.0;
374 u_ptr = Teuchos::rcp(
new Epetra_Vector(*x_ghosted_map_));
377 *(Thyra::get_Epetra_Vector(*x_owned_map_, inArgs.get_x())),
381 if (is_null(u_dot_ptr))
382 u_dot_ptr = Teuchos::rcp(
new Epetra_Vector(*x_ghosted_map_));
385 *(Thyra::get_Epetra_Vector(*x_owned_map_, inArgs.get_x_dot())),
391 x_ptr = Teuchos::rcp(
new Epetra_Vector(*x_ghosted_map_));
392 x_ptr->Import(*node_coordinates_, *importer_, Insert);
395 Epetra_Vector& u = *u_ptr;
396 Epetra_Vector& u_dot = *u_dot_ptr;
397 Epetra_Vector& x = *x_ptr;
400 const int OverlapNumMyElements = x_ghosted_map_->NumMyElements();
406 const auto alpha = inArgs.get_alpha();
407 const auto beta = inArgs.get_beta();
415 M_inv->PutScalar(0.0);
418 for (
int ne = 0; ne < OverlapNumMyElements - 1; ne++)
421 for (
int gp = 0; gp < 2; gp++)
428 uu_dot[0] = u_dot[ne];
429 uu_dot[1] = u_dot[ne + 1];
431 basis.computeBasis(gp, xx, uu, uu_dot);
434 for (
int i = 0; i < 2; i++)
436 const int row = x_ghosted_map_->GID(ne + i);
439 if (x_owned_map_->MyGID(row))
443 (*f)[x_owned_map_->LID(x_ghosted_map_->GID(ne + i))]
444 += +basis.wt * basis.dz
445 * (basis.uu_dot * basis.phi[i]
446 + (a_ / basis.dz * basis.duu
448 + 1.0 / (basis.dz * basis.dz))
451 + k_ * basis.uu * basis.uu
458 for (
int j = 0; j < 2; j++)
460 if (x_owned_map_->MyGID(row))
462 const int column = x_ghosted_map_->GID(ne + j);
464 = basis.wt * basis.dz
465 * (alpha * basis.phi[i]
471 + (1.0 / (basis.dz * basis.dz))
474 + 2.0 * k_ * basis.uu
478 ierr = J->SumIntoGlobalValues(
479 row, 1, &jac, &column);
485 for (
int j = 0; j < 2; j++)
487 if (x_owned_map_->MyGID(row))
489 const int column = x_ghosted_map_->GID(ne + j);
495 = basis.wt * basis.dz
496 * (alpha * basis.phi[i]
503 / (basis.dz * basis.dz))
506 + 2.0 * k_ * basis.uu
510 ierr = M_inv->SumIntoGlobalValues(
511 row, 1, &jac, &column);
522 if (comm_->MyPID() == 0)
532 ierr = J->ReplaceGlobalValues(0, 1, &jac, &column);
535 ierr = J->ReplaceGlobalValues(0, 1, &jac, &column);
541 ierr = M_inv->ReplaceGlobalValues(0, 1, &jac, &column);
544 ierr = M_inv->ReplaceGlobalValues(0, 1, &jac, &column);
554 M_inv->ExtractDiagonalCopy(*J_diagonal_);
556 for (
int i = 0; i < J_diagonal_->MyLength(); ++i)
557 (*J_diagonal_)[i] = 1.0 / ((*J_diagonal_)[i]);
559 M_inv->PutScalar(0.0);
560 M_inv->ReplaceDiagonalValues(*J_diagonal_);
561 M_inv->FillComplete();
564 TEUCHOS_ASSERT(ierr > -1);
583 dphide =
new double[2];
594 void Basis::computeBasis(
int gp,
double* z,
double* u,
double* u_dot)
599 eta = -1.0 / sqrt(3.0);
604 eta = 1.0 / sqrt(3.0);
609 phi[0] = (1.0 - eta) / 2.0;
610 phi[1] = (1.0 + eta) / 2.0;
615 dz = 0.5 * (z[1] - z[0]);
621 for (
int i = 0; i < N; i++)
625 duu += u[i] * dphide[i];
628 uu_dot += u_dot[i] * phi[i];
629 duu_dot += u_dot[i] * dphide[i];