void Piro::Epetra::MatrixFreeDecorator::evalModel( const InArgs& inArgs, const OutArgs& outArgs ) const { using Teuchos::RCP; using Teuchos::rcp; RCP<Epetra_Operator> W_out = outArgs.get_W(); if (W_out == Teuchos::null) { // Just pass through as is: nothing to Decorate model->evalModel(inArgs, outArgs); } else { RCP<Piro::Epetra::MatrixFreeOperator> W_mfo = Teuchos::rcp_dynamic_cast<Piro::Epetra::MatrixFreeOperator>(W_out); TEUCHOS_TEST_FOR_EXCEPTION(W_mfo==Teuchos::null, std::logic_error, "Epetra_Operator sent as W to Piro::Epetra::MatrixFreeDecorator\n" "be of type Piro::Epetra::MatrixFreeOperator"); // Do base case for MatrixFree: set f instead of W OutArgs modelOutArgs(outArgs); InArgs modelInArgs(inArgs); // Store f_out in case it was also requested RCP<Epetra_Vector> f_out = outArgs.get_f(); modelOutArgs.set_f(fBase); modelOutArgs.set_W(Teuchos::null); //Evaluate the underlying model model->evalModel(modelInArgs, modelOutArgs); // If f_out was requested, return it. if (f_out != Teuchos::null) *f_out = *fBase; // Save unperturbed solution (deep copy inArgs, shallow f) InArgs clonedInArgs = inArgs; for (int l = 0; l < inArgs.Np(); ++l) { const RCP<const Epetra_Vector> p_l = inArgs.get_p(l); if (nonnull(p_l)) clonedInArgs.set_p(l, Teuchos::rcp(new Epetra_Vector(*p_l))); } clonedInArgs.set_x(Teuchos::rcp(new Epetra_Vector(*inArgs.get_x()))); bool haveXdot = false; if (inArgs.supports(IN_ARG_x_dot)) { RCP<const Epetra_Vector> xdot = inArgs.get_x_dot(); if (nonnull(xdot)) { clonedInArgs.set_x_dot(Teuchos::rcp(new Epetra_Vector(*inArgs.get_x_dot()))); haveXdot = true; } } W_mfo->setBase(clonedInArgs, fBase, haveXdot); } }