1 #ifndef VERTEXCFD_TEMPUSOBSERVER_WRITEMATRIX_IMPL_HPP
2 #define VERTEXCFD_TEMPUSOBSERVER_WRITEMATRIX_IMPL_HPP
7 #include <EpetraExt_MultiVectorOut.h>
8 #include <EpetraExt_RowMatrixOut.h>
9 #include <Epetra_CrsMatrix.h>
10 #include <MatrixMarket_Tpetra.hpp>
11 #include <NOX_Abstract_Group.H>
12 #include <NOX_Solver_Generic.H>
13 #include <NOX_Thyra_Vector.H>
14 #include <Panzer_NodeType.hpp>
15 #include <Thyra_Amesos2LinearOpWithSolve_decl.hpp>
16 #include <Thyra_AmesosLinearOpWithSolve.hpp>
17 #include <Thyra_AztecOOLinearOpWithSolve.hpp>
18 #include <Thyra_BelosLinearOpWithSolve.hpp>
19 #include <Thyra_DefaultSpmdVector.hpp>
20 #include <Thyra_EpetraLinearOp.hpp>
21 #include <Thyra_EpetraThyraWrappers.hpp>
22 #include <Thyra_NonlinearSolver_NOX.hpp>
23 #include <Thyra_TpetraLinearOp.hpp>
24 #include <Thyra_TpetraThyraWrappers.hpp>
25 #include <Tpetra_CrsMatrix.hpp>
29 namespace TempusObserver
32 template<
class Scalar>
33 WriteMatrix<Scalar>::WriteMatrix(
const Teuchos::ParameterList& write_params)
36 if (write_params.isType<Teuchos::Array<int>>(
"Write Steps"))
39 = write_params.template get<Teuchos::Array<int>>(
"Write Steps");
43 throw std::runtime_error(
44 "Requested matrix output but 'Write Steps' was not provided'");
48 _write_residual =
false;
49 if (write_params.isType<
bool>(
"Write Residual"))
51 _write_residual = write_params.template get<bool>(
"Write Residual");
56 if (write_params.isType<std::string>(
"Matrix File Prefix"))
59 = write_params.template get<std::string>(
"Matrix File Prefix");
60 _jacobian_prefix = base_prefix +
"-jacobian";
61 _residual_prefix = base_prefix +
"-residual";
65 _jacobian_prefix =
"jacobian";
66 _residual_prefix =
"residual";
71 template<
class Scalar>
73 const Tempus::Integrator<Scalar>&)
78 template<
class Scalar>
84 template<
class Scalar>
90 template<
class Scalar>
96 template<
class Scalar>
102 template<
class Scalar>
104 const Tempus::Integrator<Scalar>&)
109 template<
class Scalar>
111 const Tempus::Integrator<Scalar>& integrator)
113 auto step_index = integrator.getIndex();
116 if (std::find(_write_steps.begin(), _write_steps.end(), step_index)
117 != _write_steps.end())
120 std::string filename = _jacobian_prefix +
"-"
121 + std::to_string(step_index) +
".mtx";
124 std::string descr =
"VertexCFD Jacobian matrix at time step "
125 + std::to_string(step_index);
128 auto stepper = integrator.getStepper();
129 auto nonlinear_solver = stepper->getSolver();
130 if (!nonlinear_solver)
132 throw std::runtime_error(
"Nonlinear solver not available");
136 auto linear_solver = nonlinear_solver->get_W();
139 throw std::runtime_error(
"Linear solver is not available");
143 auto jacobian_op = this->extractLinearOp(linear_solver);
146 this->write_jacobian(jacobian_op, filename, descr);
150 filename = _residual_prefix +
"-" + std::to_string(step_index)
152 descr =
"Residual vector at time step "
153 + std::to_string(step_index);
157 = Teuchos::rcp_dynamic_cast<const Thyra::NOXNonlinearSolver>(
159 auto nox_solver = thyranox_solver->getNOXSolver();
165 const auto& group = nox_solver->getPreviousSolutionGroup();
166 const auto& nox_resid = group.getF();
167 const NOX::Thyra::Vector& noxthyra_resid
168 =
dynamic_cast<const NOX::Thyra::Vector&
>(nox_resid);
169 auto thyra_resid = noxthyra_resid.getThyraRCPVector();
172 this->write_residual(thyra_resid, filename, descr);
178 template<
class Scalar>
184 template<
class Scalar>
185 Teuchos::RCP<const Thyra::LinearOpBase<Scalar>>
187 const Teuchos::RCP<
const Thyra::LinearOpWithSolveBase<Scalar>>&
190 Teuchos::RCP<const Thyra::LinearOpBase<Scalar>> jacobian_op;
197 = this->tryExtractForwardOp<Thyra::BelosLinearOpWithSolve<double>>(
202 jacobian_op = this->tryExtractForwardOp<Thyra::AztecOOLinearOpWithSolve>(
207 jacobian_op = this->tryExtractForwardOp<Thyra::AmesosLinearOpWithSolve>(
213 = this->tryExtractForwardOp<Thyra::Amesos2LinearOpWithSolve<double>>(
218 throw std::runtime_error(
219 "Unrecognized linear solver type in matrix output");
227 template<
class Scalar>
228 template<
class SolverType>
229 Teuchos::RCP<const Thyra::LinearOpBase<Scalar>>
230 WriteMatrix<Scalar>::tryExtractForwardOp(
231 const Teuchos::RCP<
const Thyra::LinearOpWithSolveBase<Scalar>>&
234 Teuchos::RCP<const Thyra::LinearOpBase<Scalar>> jacobian_op;
237 = Teuchos::rcp_dynamic_cast<const SolverType>(linear_solver);
242 auto nonconst_derived_solver
243 = Teuchos::rcp_const_cast<SolverType>(derived_solver);
244 auto fwd_opsrc = nonconst_derived_solver->extract_fwdOpSrc();
245 jacobian_op = fwd_opsrc->getOp();
252 template<
class Scalar>
253 void WriteMatrix<Scalar>::write_jacobian(
254 const Teuchos::RCP<
const Thyra::LinearOpBase<Scalar>>& jacobian_op,
255 const std::string& filename,
256 const std::string& description)
const
260 = Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(jacobian_op);
263 auto epetra_op = jacobian_epetra->epetra_op();
265 = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(epetra_op);
268 throw std::runtime_error(
"Epetra operator is not a RowMatrix");
271 EpetraExt::RowMatrixToMatrixMarketFile(
272 filename.c_str(), *epetra_mat, description.c_str());
277 auto jacobian_tpetra = Teuchos::rcp_dynamic_cast<
278 const Thyra::TpetraLinearOp<Scalar,
280 panzer::GlobalOrdinal,
281 panzer::TpetraNodeType>>(jacobian_op);
282 if (!jacobian_tpetra)
284 throw std::runtime_error(
"Unexpected matrix type");
289 using TpetraMatrix = Tpetra::
290 CrsMatrix<Scalar, int, panzer::GlobalOrdinal, panzer::TpetraNodeType>;
291 auto tpetra_op = jacobian_tpetra->getConstTpetraOperator();
293 = Teuchos::rcp_dynamic_cast<const TpetraMatrix>(tpetra_op);
296 throw std::runtime_error(
"Tpetra operator is not a CrsMatrix");
299 Tpetra::MatrixMarket::Writer<TpetraMatrix>::writeSparseFile(
300 filename, *tpetra_mat,
"", description);
305 template<
class Scalar>
306 void WriteMatrix<Scalar>::write_residual(
307 const Teuchos::RCP<
const Thyra::VectorBase<Scalar>>& vec,
308 const std::string& filename,
309 const std::string& description)
const
313 = Teuchos::rcp_dynamic_cast<const Thyra::DefaultSpmdVector<double>>(
317 auto space = vec->space();
318 auto epetra_map = Thyra::get_Epetra_Map(space);
319 auto epetra_vec = Thyra::get_Epetra_Vector(vec, epetra_map);
321 EpetraExt::MultiVectorToMatrixMarketFile(
322 filename.c_str(), *epetra_vec,
"", description.c_str());
325 auto thyratpetra_vec = Teuchos::rcp_dynamic_cast<
327 TpetraVector<double, int, panzer::GlobalOrdinal, panzer::TpetraNodeType>>(
331 auto tpetra_vec = thyratpetra_vec->getConstTpetraVector();
333 using TpetraMatrix = Tpetra::
334 CrsMatrix<Scalar, int, panzer::GlobalOrdinal, panzer::TpetraNodeType>;
335 Tpetra::MatrixMarket::Writer<TpetraMatrix>::writeDenseFile(
336 filename, *tpetra_vec,
"", description);
345 #endif // end VERTEXCFD_TEMPUSOBSERVER_WRITEMATRIX_IMPL_HPP