//----------------------------------------------------------------------------------------------- // Calculates the derivatives of the objective //----------------------------------------------------------------------------------------------- bool BonminInterfaceGradients::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) { // running model if needed update(n, x); // ---- copying the gradients from the case to grad_f ---- // checking that gradients for all variables are available Derivative *df = p_case_last->objectiveDerivative(); if(df->numberOfPartials() == n) { for(int i = 0; i < n; ++i) { grad_f[i] = df->value(i); } } else { cout << endl << "### BONMIN Error! ###" << endl << "Number of df/dx in case does not match problem size..." << endl; exit(1); } return true; }
void QRSDetection::transform_enter (ssi_stream_t &stream_in, ssi_stream_t &stream_out, ssi_size_t xtra_stream_in_num, ssi_stream_t xtra_stream_in[]) { //bandpass Butfilt *bandpass = ssi_pcast (Butfilt, Factory::Create (Butfilt::GetCreateName (), 0, false)); bandpass->getOptions()->type = Butfilt::BAND; bandpass->getOptions()->norm = false; bandpass->getOptions()->high = 15; bandpass->getOptions()->low = 5; bandpass->getOptions()->order = 13; _bandpass = bandpass; ssi_stream_init (_bandpass_stream, 0, _bandpass->getSampleDimensionOut (stream_in.dim), _bandpass->getSampleBytesOut (stream_in.byte), _bandpass->getSampleTypeOut (stream_in.type), stream_in.sr); _bandpass->transform_enter (stream_in, _bandpass_stream); //diff Derivative *diff = ssi_pcast(Derivative, Factory::Create (Derivative::GetCreateName (), 0, false)); ssi_strcpy (diff->getOptions()->names, "1st"); _diff = diff; ssi_stream_init (_diff_stream, 0, _diff->getSampleDimensionOut (_bandpass_stream.dim), _diff->getSampleBytesOut (_bandpass_stream.byte), _diff->getSampleTypeOut (_bandpass_stream.type), _bandpass_stream.sr); _diff->transform_enter (_bandpass_stream, _diff_stream); //qrs-pre-process QRSPreProcess *pre = ssi_pcast(QRSPreProcess, Factory::Create (QRSPreProcess::GetCreateName (), 0, false)); _pre = pre; ssi_stream_init (_pre_stream, 0, _pre->getSampleDimensionOut (_diff_stream.dim), _pre->getSampleBytesOut (_diff_stream.byte), _pre->getSampleTypeOut (_diff_stream.type), _diff_stream.sr); _pre->transform_enter(_diff_stream, _pre_stream); Butfilt *pre_low = ssi_create (Butfilt, 0, false); pre_low->getOptions()->zero = true; pre_low->getOptions()->norm = false; pre_low->getOptions ()->low = 6.4; pre_low->getOptions ()->order = 3; pre_low->getOptions ()->type = Butfilt::LOW; _pre_low = pre_low; ssi_stream_init (_pre_low_stream, 0, _pre_low->getSampleDimensionOut (_pre_stream.dim), _pre_low->getSampleBytesOut (_pre_stream.byte), _pre_low->getSampleTypeOut (_pre_stream.type), _pre_stream.sr); _pre_low->transform_enter(_pre_stream, _pre_low_stream); //qrs-detect ssi_size_t sample_dimension = _pre_low_stream.dim; _pulsed = false; _n_R = 0; _samples_since_last_R = 0; _sum_RR = 0; _average_RR = 0.0f; _history_RR = new ssi_size_t[_options.depthRR]; _last_R = 0; for (ssi_size_t k = 0; k < _options.depthRR; k++) { _history_RR[k] = 0; } _first_call = true; }
void StrPrinter::bvisit(const Derivative &x) { std::ostringstream o; o << "Derivative(" << this->apply(x.get_arg()); multiset_basic m1 = x.get_symbols(); std::multiset<RCP<const Basic>, RCPBasicKeyLessCmp> m2(m1.begin(), m1.end()); for (auto p = m2.begin(); p != m2.end(); p++) { o << ", " << this->apply(*p); } o << ")"; str_ = o.str(); }
//----------------------------------------------------------------------------------------------- // Passes the Jacobian to Bonmin //----------------------------------------------------------------------------------------------- bool BonminInterfaceGradients::eval_jac_g(Index n, const Number* x, bool new_x, Index m, Index nele_jac, Index* iRow, Index *jCol, Number* values) { // checking if the structure of the jacobian has been set if (values == NULL) { cout << "Giving bonmin the structure of the jacobian..." << endl; int entry = 0; for(int row = 0; row < m; ++row) { for(int col = 0; col < n; ++col) { iRow[entry] = row; jCol[entry] = col; ++entry; } } } else // the structure is already set, getting the values { // running model if needed update(n, x); // copying gradients to Bonmin int entry = 0; for(int i = 0; i < p_case_last->numberOfConstraintDerivatives(); ++i) { Derivative *dc = p_case_last->constraintDerivative(i); for(int j = 0; j < dc->numberOfPartials(); ++j) { values[entry] = dc->value(j); ++entry; } } } return true; }
void StrPrinter::bvisit(const Derivative &x) { std::ostringstream o; o << "Derivative("; vec_basic vec = x.get_args(); o << this->apply(vec) << ")"; str_ = o.str(); }
static RCP<const Basic> diff(const Derivative &self, const RCP<const Symbol> &x) { RCP<const Basic> ret = self.get_arg()->diff(x); if (eq(*ret, *zero)) return zero; multiset_basic t = self.get_symbols(); for (auto &p: t) { // If x is already there in symbols multi-set add x to the symbols multi-set if (eq(*p, *x)) { t.insert(x); return Derivative::create(self.get_arg(), t); } } // Avoid cycles if (is_a<Derivative>(*ret) && eq(*static_cast<const Derivative &>(*ret).get_arg(), *self.get_arg())) { t.insert(x); return Derivative::create(self.get_arg(), t); } for (auto &p: t) { ret = ret->diff(rcp_static_cast<const Symbol>(p)); } return ret; }
void Piro::Epetra::NOXSolver::evalModel(const InArgs& inArgs, const OutArgs& outArgs ) const { // Parse input parameters for (int i=0; i<num_p; i++) { Teuchos::RCP<const Epetra_Vector> p_in = inArgs.get_p(i); if (p_in != Teuchos::null) interface->inargs_set_p(p_in, i); // Pass "p_in" through to inargs } // Reset initial guess, if the user requests if(piroParams->sublist("NOX").get("Reset Initial Guess",false)==true) *currentSolution=*model->get_x_init(); // Solve solver->reset(*currentSolution); NOX::StatusTest::StatusType status = solver->solve(); // Print status if (status == NOX::StatusTest::Converged) //utils.out() << "Step Converged" << std::endl; ; else { utils.out() << "Nonlinear solver failed to converge!" << std::endl; outArgs.setFailed(); } // Get the NOX and Epetra_Vector with the final solution from the solver (*currentSolution)=grp->getX(); Teuchos::RCP<const Epetra_Vector> finalSolution = Teuchos::rcp(&(currentSolution->getEpetraVector()), false); // Print solution if (utils.isPrintType(NOX::Utils::Details)) { utils.out() << std::endl << "Final Solution" << std::endl << "****************" << std::endl; finalSolution->Print(utils.pout()); } // Output the parameter list if (utils.isPrintType(NOX::Utils::Parameters)) { utils.out() << std::endl << "Final Parameters" << std::endl << "****************" << std::endl; piroParams->print(utils.out()); utils.out() << std::endl; } // Print stats bool print_stats = piroParams->get("Print Convergence Stats", true); if (print_stats) { static int totalNewtonIters=0; static int totalKrylovIters=0; static int stepNum=0; int NewtonIters = piroParams->sublist("NOX"). sublist("Output").get("Nonlinear Iterations", -1000); int KrylovIters = linsys->getLinearItersTotal() - totalKrylovIters; int lastSolveKrylovIters = linsys->getLinearItersLastSolve(); totalNewtonIters += NewtonIters; totalKrylovIters += KrylovIters; stepNum++; utils.out() << "Convergence Stats: for step #" << stepNum << " : Newton, Krylov, Kr/Ne; LastKrylov, LastTol: " << NewtonIters << " " << KrylovIters << " " << (double) KrylovIters / (double) NewtonIters << " " << lastSolveKrylovIters << " " << linsys->getAchievedTol() << std::endl; if (stepNum > 1) utils.out() << "Convergence Stats: running total: Newton, Krylov, Kr/Ne, Kr/Step: " << totalNewtonIters << " " << totalKrylovIters << " " << (double) totalKrylovIters / (double) totalNewtonIters << " " << (double) totalKrylovIters / (double) stepNum << std::endl; } // // Do Sensitivity Calc, if requested. See 3 main steps // // Set inargs and outargs EpetraExt::ModelEvaluator::InArgs model_inargs = model->createInArgs(); EpetraExt::ModelEvaluator::OutArgs model_outargs = model->createOutArgs(); model_inargs.set_x(finalSolution); // We make different choices for layouts of df/dp, dg/dx depending on // whether we are doing forward or adjoint sensitivities std::string sensitivity_method = piroParams->get("Sensitivity Method", "Forward"); bool do_sens = false; for (int i=0; i<num_p; i++) { // p model_inargs.set_p(i, inArgs.get_p(i)); // df/dp do_sens = false; for (int j=0; j<num_g; j++) { if (!outArgs.supports(OUT_ARG_DgDp, j, i).none() && !outArgs.get_DgDp(j,i).isEmpty()) { do_sens = true; // This code does not work with non-empty p_indexes. The reason is // each p_indexes could theoretically be different for each g. // We would then need to make one df/dp for all the chosen p's // and then index into them properly below. Note that the number of // columns in df/dp should be the number of chosen p's, not the total // number of p's. if (outArgs.get_DgDp(j,i).getMultiVector() != Teuchos::null) { Teuchos::Array<int> p_indexes = outArgs.get_DgDp(j,i).getDerivativeMultiVector().getParamIndexes(); TEUCHOS_TEST_FOR_EXCEPTION(p_indexes.size() > 0, Teuchos::Exceptions::InvalidParameter, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Non-empty paramIndexes for dg/dp(" << i << "," << j << ") is not currently supported." << std::endl); } } } if (do_sens) { Teuchos::RCP<const Epetra_Map> p_map = model->get_p_map(i); Teuchos::RCP<const Epetra_Map> f_map = model->get_f_map(); int num_params = p_map->NumGlobalElements(); int num_resids = f_map->NumGlobalElements(); bool p_dist = p_map->DistributedGlobal(); bool f_dist = f_map->DistributedGlobal(); DerivativeSupport ds = model_outargs.supports(OUT_ARG_DfDp,i); // Determine which layout to use for df/dp. Ideally one would look // at num_params, num_resids, what is supported by the underlying // model evaluator, and the sensitivity method, and make the best // choice to minimze the number of solves. However this choice depends // also on what layout of dg/dx is supported (e.g., if only the operator // form is supported for forward sensitivities, then df/dp must be // DERIV_MV_BY_COL). For simplicity, we order the conditional tests // to get the right layout in most situations. DerivativeLayout dfdp_layout; if (sensitivity_method == "Forward") { if (ds.supports(DERIV_MV_BY_COL) && !p_dist) dfdp_layout = COL; else if (ds.supports(DERIV_TRANS_MV_BY_ROW) && !f_dist) dfdp_layout = ROW; else if (ds.supports(DERIV_LINEAR_OP)) dfdp_layout = OP; else TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "For df/dp(" << i <<") with forward sensitivities, " << "underlying ModelEvaluator must support DERIV_LINEAR_OP, " << "DERIV_MV_BY_COL with p not distributed, or " "DERIV_TRANS_MV_BY_ROW with f not distributed." << std::endl); } else if (sensitivity_method == "Adjoint") { if (ds.supports(DERIV_LINEAR_OP)) dfdp_layout = OP; else if (ds.supports(DERIV_TRANS_MV_BY_ROW) && !f_dist) dfdp_layout = ROW; else if (ds.supports(DERIV_MV_BY_COL) && !p_dist) dfdp_layout = COL; else TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "For df/dp(" << i <<") with adjoint sensitivities, " << "underlying ModelEvaluator must support DERIV_LINEAR_OP, " << "DERIV_MV_BY_COL with p not distributed, or " "DERIV_TRANS_MV_BY_ROW with f not distributed." << std::endl); } else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Unknown sensitivity method" << sensitivity_method << ". Valid choices are \"Forward\" and \"Adjoint\"." << std::endl); if (dfdp_layout == COL) { Teuchos::RCP<Epetra_MultiVector> dfdp = Teuchos::rcp(new Epetra_MultiVector(*f_map, num_params)); // Teuchos::Array<int> p_indexes = // outArgs.get_DgDp(i,0).getDerivativeMultiVector().getParamIndexes(); // EpetraExt::ModelEvaluator::DerivativeMultiVector // dmv_dfdp(dfdp, DERIV_MV_BY_COL, p_indexes); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dfdp(dfdp, DERIV_MV_BY_COL); model_outargs.set_DfDp(i,dmv_dfdp); } else if (dfdp_layout == ROW) { Teuchos::RCP<Epetra_MultiVector> dfdp = Teuchos::rcp(new Epetra_MultiVector(*p_map, num_resids)); // Teuchos::Array<int> p_indexes = // outArgs.get_DgDp(i,0).getDerivativeMultiVector().getParamIndexes(); // EpetraExt::ModelEvaluator::DerivativeMultiVector // dmv_dfdp(dfdp, DERIV_TRANS_MV_BY_ROW, p_indexes); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dfdp(dfdp, DERIV_TRANS_MV_BY_ROW); model_outargs.set_DfDp(i,dmv_dfdp); } else if (dfdp_layout == OP) { Teuchos::RCP<Epetra_Operator> dfdp_op = model->create_DfDp_op(i); TEUCHOS_TEST_FOR_EXCEPTION( dfdp_op == Teuchos::null, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Needed df/dp operator (" << i << ") is null!" << std::endl); model_outargs.set_DfDp(i,dfdp_op); } } } for (int j=0; j<num_g; j++) { // g Teuchos::RCP<Epetra_Vector> g_out = outArgs.get_g(j); if (g_out != Teuchos::null) { g_out->PutScalar(0.0); model_outargs.set_g(j, g_out); } // dg/dx do_sens = false; for (int i=0; i<num_p; i++) { Teuchos::RCP<Epetra_MultiVector> dgdp_out; if (!outArgs.supports(OUT_ARG_DgDp, j, i).none() && !outArgs.get_DgDp(j,i).isEmpty()) { do_sens = true; } } if (do_sens) { Teuchos::RCP<const Epetra_Map> g_map = model->get_g_map(j); Teuchos::RCP<const Epetra_Map> x_map = model->get_x_map(); int num_responses = g_map->NumGlobalElements(); int num_solution = x_map->NumGlobalElements(); bool g_dist = g_map->DistributedGlobal(); bool x_dist = x_map->DistributedGlobal(); DerivativeSupport ds = model_outargs.supports(OUT_ARG_DgDx,j); DerivativeLayout dgdx_layout; if (sensitivity_method == "Forward") { if (ds.supports(DERIV_LINEAR_OP)) dgdx_layout = OP; else if (ds.supports(DERIV_MV_BY_COL) && !x_dist) dgdx_layout = COL; else if (ds.supports(DERIV_TRANS_MV_BY_ROW) && !g_dist) dgdx_layout = ROW; else TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "For dg/dx(" << j <<") with forward sensitivities, " << "underlying ModelEvaluator must support DERIV_LINEAR_OP, " << "DERIV_MV_BY_COL with x not distributed, or " "DERIV_TRANS_MV_BY_ROW with g not distributed." << std::endl); } else if (sensitivity_method == "Adjoint") { if (ds.supports(DERIV_TRANS_MV_BY_ROW) && !g_dist) dgdx_layout = ROW; else if (ds.supports(DERIV_MV_BY_COL) && !x_dist) dgdx_layout = COL; else if (ds.supports(DERIV_LINEAR_OP)) dgdx_layout = OP; else TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "For dg/dx(" << j <<") with adjoint sensitivities, " << "underlying ModelEvaluator must support DERIV_LINEAR_OP, " << "DERIV_MV_BY_COL with x not distributed, or " "DERIV_TRANS_MV_BY_ROW with g not distributed." << std::endl); } else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Unknown sensitivity method" << sensitivity_method << ". Valid choices are \"Forward\" and \"Adjoint\"." << std::endl); if (dgdx_layout == OP) { Teuchos::RCP<Epetra_Operator> dgdx_op = model->create_DgDx_op(j); TEUCHOS_TEST_FOR_EXCEPTION( dgdx_op == Teuchos::null, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Needed dg/dx operator (" << j << ") is null!" << std::endl); model_outargs.set_DgDx(j,dgdx_op); } else if (dgdx_layout == ROW) { Teuchos::RCP<Epetra_MultiVector> dgdx = Teuchos::rcp(new Epetra_MultiVector(*x_map, num_responses)); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dgdx(dgdx, DERIV_TRANS_MV_BY_ROW); model_outargs.set_DgDx(j,dmv_dgdx); } else if (dgdx_layout == COL) { Teuchos::RCP<Epetra_MultiVector> dgdx = Teuchos::rcp(new Epetra_MultiVector(*g_map, num_solution)); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dgdx(dgdx, DERIV_MV_BY_COL); model_outargs.set_DgDx(j,dmv_dgdx); } // dg/dp for (int i=0; i<num_p; i++) { if (!outArgs.supports(OUT_ARG_DgDp,j,i).none()) { Derivative dgdp = outArgs.get_DgDp(j,i); if (dgdp.getLinearOp() != Teuchos::null) { Teuchos::RCP<const Epetra_Map> g_map = model->get_g_map(j); Teuchos::RCP<const Epetra_Map> p_map = model->get_p_map(i); int num_responses = g_map->NumGlobalElements(); int num_params = p_map->NumGlobalElements(); bool g_dist = g_map->DistributedGlobal(); bool p_dist = p_map->DistributedGlobal(); DerivativeSupport ds = model_outargs.supports(OUT_ARG_DgDp,j,i); if (ds.supports(DERIV_LINEAR_OP)) { Teuchos::RCP<Epetra_Operator> dgdp_op = model->create_DgDp_op(j,i); TEUCHOS_TEST_FOR_EXCEPTION( dgdp_op == Teuchos::null, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Needed dg/dp operator (" << j << "," << i << ") is null!" << std::endl); model_outargs.set_DgDp(j,i,dgdp_op); } else if (ds.supports(DERIV_MV_BY_COL) && !p_dist) { Teuchos::RCP<Epetra_MultiVector> dgdp = Teuchos::rcp(new Epetra_MultiVector(*g_map, num_params)); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dgdp(dgdp, DERIV_MV_BY_COL); model_outargs.set_DgDp(j,i,dmv_dgdp); } else if (ds.supports(DERIV_TRANS_MV_BY_ROW) && !g_dist) { Teuchos::RCP<Epetra_MultiVector> dgdp = Teuchos::rcp(new Epetra_MultiVector(*p_map, num_responses)); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dgdp(dgdp, DERIV_TRANS_MV_BY_ROW); model_outargs.set_DgDp(j,i,dmv_dgdp); } else TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "For dg/dp(" << j << "," << i << ") with operator sensitivities, "<< "underlying ModelEvaluator must support DERIV_LINEAR_OP, " << "DERIV_MV_BY_COL with p not distributed, or " "DERIV_TRANS_MV_BY_ROW with g not distributed." << std::endl); } else model_outargs.set_DgDp(j,i,outArgs.get_DgDp(j,i)); } } } } // (1) Calculate g, df/dp, dg/dp, dg/dx model->evalModel(model_inargs, model_outargs); // Ensure Jacobian is up-to-date if (do_sens) grp->computeJacobian(); // Handle operator dg/dp for (int i=0; i<num_p; i++) { for (int j=0; j<num_g; j++) { if (!outArgs.supports(OUT_ARG_DgDp, j, i).none()) { if (outArgs.get_DgDp(j,i).getLinearOp() != Teuchos::null) { Teuchos::RCP<Epetra_Operator> op = outArgs.get_DgDp(j,i).getLinearOp(); Teuchos::RCP<SensitivityOperator> sens_op = Teuchos::rcp_dynamic_cast<SensitivityOperator>(op); sens_op->setup(model_outargs.get_DfDp(i), model_outargs.get_DgDx(j), model_outargs.get_DgDp(j,i), piroParams, grp, tls_strategy); } } } } if (sensitivity_method == "Forward") { for (int i=0; i<num_p; i++) { // See if there are any forward sensitivities we need to do // that aren't handled by the operator do_sens = false; for (int j=0; j<num_g; j++) { if (!outArgs.supports(OUT_ARG_DgDp, j, i).none()) { if (outArgs.get_DgDp(j,i).getMultiVector() != Teuchos::null) do_sens = true; } } if (!do_sens) continue; if (!model_outargs.supports(OUT_ARG_DfDp, i).none()) { TEUCHOS_TEST_FOR_EXCEPTION( model_outargs.get_DfDp(i).getLinearOp()!=Teuchos::null, std::logic_error, std::endl <<"Piro::Epetra::NOXSolver::evalModel(): " << "Can\'t use df/dp operator " << i << " with non-operator " << "forward sensitivities." << std::endl); Teuchos::RCP<Epetra_MultiVector> dfdp = model_outargs.get_DfDp(i).getMultiVector(); if (dfdp != Teuchos::null) { int num_cols = dfdp->NumVectors(); // (2) Calculate dx/dp multivector from -(J^{-1}*df/dp) Teuchos::RCP<Epetra_MultiVector> dxdp = Teuchos::rcp(new Epetra_MultiVector(dfdp->Map(), num_cols)); NOX::Epetra::MultiVector dfdp_nox( dfdp, NOX::DeepCopy, NOX::Epetra::MultiVector::CreateView); NOX::Epetra::MultiVector dxdp_nox( dxdp, NOX::DeepCopy, NOX::Epetra::MultiVector::CreateView); grp->applyJacobianInverseMultiVector(*piroParams, dfdp_nox, dxdp_nox); dxdp_nox.scale(-1.0); // (3) Calculate dg/dp = dg/dx*dx/dp + dg/dp for (int j=0; j<num_g; j++) { if (!outArgs.supports(OUT_ARG_DgDp, j, i).none()) { Teuchos::RCP<Epetra_MultiVector> dgdp_out = outArgs.get_DgDp(j,i).getMultiVector(); if (dgdp_out != Teuchos::null) { Derivative dgdx_dv = model_outargs.get_DgDx(j); Teuchos::RCP<Epetra_Operator> dgdx_op = dgdx_dv.getLinearOp(); Teuchos::RCP<Epetra_MultiVector> dgdx = dgdx_dv.getMultiVector(); Derivative dfdp_dv = model_outargs.get_DfDp(i); EDerivativeMultiVectorOrientation dgdp_orient = outArgs.get_DgDp(j,i).getMultiVectorOrientation(); if (dgdx_op != Teuchos::null) { bool transpose = false; if (dgdp_orient == DERIV_TRANS_MV_BY_ROW) transpose = true; Epetra_MultiVector tmp(dgdx_op->OperatorRangeMap(), dxdp->NumVectors()); dgdx_op->Apply(*dxdp, tmp); if (transpose) { TEUCHOS_TEST_FOR_EXCEPTION( dgdp_out->Map().DistributedGlobal(), std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Can\'t handle special case: " << " dg/dx operator, " << " transposed, distributed dg/dp. " << std::endl); for (int j=0; j<dgdp_out->NumVectors(); j++) for (int i=0; i<dgdp_out->MyLength(); i++) (*dgdp_out)[j][i] += tmp[i][j]; } else dgdp_out->Update(1.0, tmp, 1.0); } else { Teuchos::RCP<Epetra_MultiVector> arg1, arg2; EDerivativeMultiVectorOrientation dfdp_orient = model_outargs.get_DfDp(i).getMultiVectorOrientation(); EDerivativeMultiVectorOrientation dgdx_orient = model_outargs.get_DgDx(j).getMultiVectorOrientation(); char flag1, flag2; if (dgdp_orient == DERIV_MV_BY_COL) { arg1 = dgdx; arg2 = dxdp; if (dgdx_orient == DERIV_MV_BY_COL) flag1 = 'N'; else flag1 = 'T'; if (dfdp_orient == DERIV_MV_BY_COL) flag2 = 'N'; else flag2 = 'T'; } else { arg1 = dxdp; arg2 = dgdx; if (dfdp_orient == DERIV_MV_BY_COL) flag1 = 'T'; else flag1 = 'N'; if (dgdx_orient == DERIV_MV_BY_COL) flag2 = 'T'; else flag2 = 'N'; } dgdp_out->Multiply(flag1, flag2, 1.0, *arg1, *arg2, 1.0); } } } } } } } } else if (sensitivity_method == "Adjoint") { // Hold on to original Jacobian operator Teuchos::RCP<NOX::Epetra::LinearSystem> linSys = grp->getLinearSystem(); Teuchos::RCP<Epetra_Operator> jac = linSys->getJacobianOperator(); tls_strategy->createJacobianTranspose(); const NOX::Epetra::Vector& x_nox = dynamic_cast<const NOX::Epetra::Vector&>(grp->getX()); tls_strategy->createTransposePreconditioner(x_nox, *piroParams); for (int j=0; j<num_g; j++) { // See if there are any forward sensitivities we need to do // that aren't handled by the operator do_sens = false; for (int i=0; i<num_p; i++) { if (!outArgs.supports(OUT_ARG_DgDp, j, i).none()) { if (outArgs.get_DgDp(j,i).getMultiVector() != Teuchos::null) do_sens = true; } } if (!do_sens) continue; if (!model_outargs.supports(OUT_ARG_DgDx, j).none()) { TEUCHOS_TEST_FOR_EXCEPTION( model_outargs.get_DgDx(j).getLinearOp()!=Teuchos::null, std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Can\'t use dg/dx operator " << j << " with non-operator " << "adjoint sensitivities." << std::endl); Teuchos::RCP<Epetra_MultiVector> dgdx = model_outargs.get_DgDx(j).getMultiVector(); if (dgdx != Teuchos::null) { int num_cols = dgdx->NumVectors(); // (2) Calculate xbar multivector from -(J^{-T}*dg/dx) Teuchos::RCP<Epetra_MultiVector> xbar = Teuchos::rcp(new Epetra_MultiVector(dgdx->Map(), num_cols)); for (int col=0; col<num_cols; col++) { Teuchos::RCP<Epetra_Vector> gx = Teuchos::rcp((*dgdx)(col),false); Teuchos::RCP<Epetra_Vector> xb = Teuchos::rcp((*xbar)(col),false); NOX::Epetra::Vector dgdx_nox( gx, NOX::Epetra::Vector::CreateView, NOX::DeepCopy); NOX::Epetra::Vector xbar_nox( xb, NOX::Epetra::Vector::CreateView, NOX::DeepCopy); // Solve tls_strategy->applyJacobianTransposeInverse( *piroParams, dgdx_nox, xbar_nox); } xbar->Scale(-1.0); // (3) Calculate dg/dp^T = df/dp^T*xbar + dg/dp^T for (int i=0; i<num_p; i++) { if (!outArgs.supports(OUT_ARG_DgDp, j, i).none()) { Teuchos::RCP<Epetra_MultiVector> dgdp_out = outArgs.get_DgDp(j,i).getMultiVector(); if (dgdp_out != Teuchos::null) { Derivative dfdp_dv = model_outargs.get_DfDp(i); Teuchos::RCP<Epetra_Operator> dfdp_op = dfdp_dv.getLinearOp(); Teuchos::RCP<Epetra_MultiVector> dfdp = dfdp_dv.getMultiVector(); Derivative dgdx_dv = model_outargs.get_DgDx(j); EDerivativeMultiVectorOrientation dgdp_orient = outArgs.get_DgDp(j,i).getMultiVectorOrientation(); if (dfdp_op != Teuchos::null) { bool transpose = false; if (dgdp_orient == DERIV_MV_BY_COL) transpose = true; Epetra_MultiVector tmp(dfdp_op->OperatorDomainMap(), xbar->NumVectors()); dfdp_op->SetUseTranspose(true); dfdp_op->Apply(*xbar, tmp); dfdp_op->SetUseTranspose(false); if (transpose) { TEUCHOS_TEST_FOR_EXCEPTION( dgdp_out->Map().DistributedGlobal(), std::logic_error, std::endl << "Piro::Epetra::NOXSolver::evalModel(): " << "Can\'t handle special case: " << " df/dp operator, " << " transposed, distributed dg/dp. " << std::endl); for (int j=0; j<dgdp_out->NumVectors(); j++) for (int i=0; i<dgdp_out->MyLength(); i++) (*dgdp_out)[j][i] += tmp[i][j]; } else dgdp_out->Update(1.0, tmp, 1.0); } else { Teuchos::RCP<Epetra_MultiVector> arg1, arg2; EDerivativeMultiVectorOrientation dgdp_orient = model_outargs.get_DgDp(j,i).getMultiVectorOrientation(); EDerivativeMultiVectorOrientation dfdp_orient = model_outargs.get_DfDp(i).getMultiVectorOrientation(); EDerivativeMultiVectorOrientation dgdx_orient = model_outargs.get_DgDx(j).getMultiVectorOrientation(); char flag1, flag2; if (dgdp_orient == DERIV_TRANS_MV_BY_ROW) { arg1 = dfdp; arg2 = xbar; if (dfdp_orient == DERIV_TRANS_MV_BY_ROW) flag1 = 'N'; else flag1 = 'T'; if (dgdx_orient == DERIV_TRANS_MV_BY_ROW) flag2 = 'N'; else flag2 = 'T'; } else { arg1 = xbar; arg2 = dfdp; if (dgdx_orient == DERIV_TRANS_MV_BY_ROW) flag1 = 'T'; else flag1 = 'N'; if (dfdp_orient == DERIV_TRANS_MV_BY_ROW) flag2 = 'T'; else flag2 = 'N'; } dgdp_out->Multiply(flag1, flag2, 1.0, *arg1, *arg2, 1.0); } } } } } } } // Set original operators in linear system jac->SetUseTranspose(false); linSys->setJacobianOperatorForSolve(jac); linSys->destroyPreconditioner(); } if (status == NOX::StatusTest::Converged) if (observer != Teuchos::null) observer->observeSolution(*finalSolution); // return the final solution as an additional g-vector, if requested Teuchos::RCP<Epetra_Vector> gx_out = outArgs.get_g(num_g); if (gx_out != Teuchos::null) *gx_out = *finalSolution; // Clear RCPs to parameter vectors for (int i=0; i<num_p; i++) interface->inargs_set_p(Teuchos::null, i); }
void VanderPolModel::evalModelImpl( const ModelEvaluatorBase::InArgs<double> &inArgs, const ModelEvaluatorBase::OutArgs<double> &outArgs ) const { using Teuchos::as; using Teuchos::outArg; using Teuchos::optInArg; using Teuchos::inOutArg; using Sacado::Fad::DFad; TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error, "Error, setParameterList must be called first!\n" ); const RCP<const VectorBase<double> > x_in = inArgs.get_x().assert_not_null(); Thyra::ConstDetachedVectorView<double> x_in_view( *x_in ); double t = inArgs.get_t(); double eps = epsilon_; if (acceptModelParams_) { const RCP<const VectorBase<double> > p_in = inArgs.get_p(0).assert_not_null(); Thyra::ConstDetachedVectorView<double> p_in_view( *p_in ); eps = p_in_view[0]; } RCP<const VectorBase<double> > x_dot_in; double alpha = -1.0; double beta = -1.0; if (isImplicit_) { x_dot_in = inArgs.get_x_dot().assert_not_null(); alpha = inArgs.get_alpha(); beta = inArgs.get_beta(); } const RCP<VectorBase<double> > f_out = outArgs.get_f(); const RCP<Thyra::LinearOpBase<double> > W_out = outArgs.get_W_op(); RCP<Thyra::MultiVectorBase<double> > DfDp_out; if (acceptModelParams_) { Derivative<double> DfDp = outArgs.get_DfDp(0); DfDp_out = DfDp.getMultiVector(); } // Determine how many derivatives we will compute int num_derivs = 0; if (nonnull(W_out)) { num_derivs += 2; if (isImplicit_) { num_derivs += 2; } } if (nonnull(DfDp_out)) num_derivs += 1; // Set up the FAD derivative objects int deriv_i = 0; Array<DFad<double> > x_dot_fad; int x_dot_idx_offset = 0; if (isImplicit_) { Thyra::ConstDetachedVectorView<double> x_dot_in_view( *x_dot_in ); if (nonnull(W_out)) { x_dot_idx_offset = deriv_i; x_dot_fad = convertToIndepVarFadArray<double>(x_dot_in_view.sv().values()(), num_derivs, inOutArg(deriv_i)); } else { x_dot_fad = convertToPassiveFadArray<double>(x_dot_in_view.sv().values()()); } } Array<DFad<double> > x_fad; int x_idx_offset = 0; if (nonnull(W_out)) { x_idx_offset = deriv_i; x_fad = convertToIndepVarFadArray<double>(x_in_view.sv().values()(), num_derivs, inOutArg(deriv_i)); } else { x_fad = convertToPassiveFadArray<double>(x_in_view.sv().values()()); } DFad<double> eps_fad(eps); // Default passive int eps_idx_offset = 0; if (nonnull(DfDp_out)) { eps_idx_offset = deriv_i; eps_fad = DFad<double>(num_derivs, deriv_i++, eps); } // Compute the function Array<DFad<double> > f_fad(2); this->eval_f<DFad<double> >( x_dot_fad, x_fad, eps_fad, t, f_fad ); // Extract the output if (nonnull(f_out)) { Thyra::DetachedVectorView<double> f_out_view( *f_out ); for ( int i = 0; i < as<int>(f_fad.size()); ++i ) f_out_view[i] = f_fad[i].val(); } if (nonnull(W_out)) { const RCP<Thyra::MultiVectorBase<double> > matrix = Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<double> >(W_out, true); Thyra::DetachedMultiVectorView<double> matrix_view( *matrix ); if (isImplicit_) { for ( int i = 0; i < matrix_view.subDim(); ++i) { for ( int j = 0; j < matrix_view.numSubCols(); ++j) { matrix_view(i, j) = alpha * f_fad[i].dx(x_dot_idx_offset+j) + beta * f_fad[i].dx(x_idx_offset + j); } } } else { for ( int i = 0; i < matrix_view.subDim(); ++i) { for ( int j = 0; j < matrix_view.numSubCols(); ++j) { matrix_view(i, j) = f_fad[i].dx(x_idx_offset + j); } } } } if (nonnull(DfDp_out)) { Thyra::DetachedMultiVectorView<double> DfDp_out_view( *DfDp_out ); for ( int i = 0; i < DfDp_out_view.subDim(); ++i ) DfDp_out_view(i,0) = f_fad[i].dx(eps_idx_offset); } }