NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDJnDxa(LOCA::MultiContinuation::AbstractGroup& grp, const NOX::Abstract::Vector& nullVector, const NOX::Abstract::MultiVector& aVector, NOX::Abstract::MultiVector& result) const { string callingFunction = "LOCA::DerivUtils::computeDJnDxa()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Allocate base Jn vector and fill with J times n Teuchos::RCP<NOX::Abstract::Vector> baseJnVectorPtr = nullVector.clone(NOX::ShapeCopy); if (!grp.isJacobian()) { finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); } else finalStatus = NOX::Abstract::Group::Ok; status = grp.applyJacobian(nullVector, *baseJnVectorPtr); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Now that Jn is known, call other routine status = computeDJnDxa(grp, nullVector, aVector, *baseJnVectorPtr, result); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); return finalStatus; }
NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDfDp(LOCA::MultiContinuation::AbstractGroup& grp, const vector<int>& param_ids, NOX::Abstract::MultiVector& result, bool isValidF) const { string callingFunction = "LOCA::DerivUtils::computeDfDp()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Views of f, df/dp NOX::Abstract::Vector *f = &result[0]; NOX::Abstract::Vector *dfdp = NULL; // Compute base residual F if (!isValidF) { finalStatus = grp.computeF(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); *f = grp.getF(); } else finalStatus = NOX::Abstract::Group::Ok; double param; double eps; // Loop over each parameter for (unsigned int i=0; i<param_ids.size(); i++) { // Perturb single parameter in this group, and return perturbation, eps eps = perturbParam(grp, param, param_ids[i]); // Compute perturbed residual status = grp.computeF(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Difference perturbed and base vector dfdp = &result[i+1]; dfdp->update(1.0, grp.getF(), -1.0, *f, 0.0); dfdp->scale(1.0/eps); // Restore original parameter value grp.setParam(param_ids[i], param); } return finalStatus; }
double LOCA::DerivUtils::perturbParam(LOCA::MultiContinuation::AbstractGroup& grp, double& paramOrig, int param_id) const { paramOrig = grp.getParam(param_id); // Find perturbation size and perturb parameter double eps = epsScalar(paramOrig); double param = paramOrig + eps; // Copy this perturbed parameter vector into group grp.setParam(param_id, param); // Return perturbation size return eps; }
NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDJnDxa(LOCA::MultiContinuation::AbstractGroup& grp, const NOX::Abstract::Vector& nullVector, const NOX::Abstract::MultiVector& aVector, const NOX::Abstract::Vector& JnVector, NOX::Abstract::MultiVector& result) const { string callingFunction = "LOCA::DerivUtils::computeDJnDxa()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Copy original solution vector Teuchos::RCP<NOX::Abstract::Vector> Xvec = grp.getX().clone(NOX::DeepCopy); // Loop over each column of multivector for (int i=0; i<aVector.numVectors(); i++) { // Perturb solution vector in direction of aVector, return perturbation double eps = perturbXVec(grp, *Xvec, aVector[i]); // Fill perturbed Jn vector finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); status = grp.applyJacobian(nullVector, result[i]); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Difference perturbed and base vector result[i].update(-1.0, JnVector, 1.0); result[i].scale(1.0/eps); } // Restore original solution vector grp.setX(*Xvec); return finalStatus; }
NOX::Abstract::Group::ReturnType LOCA::Epetra::ModelEvaluatorInterface:: computeDfDp(LOCA::MultiContinuation::AbstractGroup& grp, const vector<int>& param_ids, NOX::Abstract::MultiVector& result, bool isValidF) const { // Break result into f and df/dp NOX::Epetra::Vector& f = dynamic_cast<NOX::Epetra::Vector&>(result[0]); Epetra_Vector& epetra_f = f.getEpetraVector(); std::vector<int> dfdp_index(result.numVectors()-1); for (unsigned int i=0; i<dfdp_index.size(); i++) dfdp_index[i] = i+1; Teuchos::RefCountPtr<NOX::Epetra::MultiVector> dfdp = Teuchos::rcp_dynamic_cast<NOX::Epetra::MultiVector>(result.subView(dfdp_index)); Epetra_MultiVector& epetra_dfdp = dfdp->getEpetraMultiVector(); // Create inargs EpetraExt::ModelEvaluator::InArgs inargs = model_->createInArgs(); const NOX::Epetra::Vector& x = dynamic_cast<const NOX::Epetra::Vector&>(grp.getX()); const Epetra_Vector& epetra_x = x.getEpetraVector(); inargs.set_x(Teuchos::rcp(&epetra_x, false)); inargs.set_p(0, Teuchos::rcp(¶m_vec, false)); if (inargs.supports(EpetraExt::ModelEvaluator::IN_ARG_x_dot)) { // Create x_dot, filled with zeros if (x_dot == NULL) x_dot = new Epetra_Vector(epetra_x.Map()); inargs.set_x_dot(Teuchos::rcp(x_dot, false)); } // Create outargs EpetraExt::ModelEvaluator::OutArgs outargs = model_->createOutArgs(); if (!isValidF) { EpetraExt::ModelEvaluator::Evaluation<Epetra_Vector> eval_f; Teuchos::RefCountPtr<Epetra_Vector> F = Teuchos::rcp(&epetra_f, false); eval_f.reset(F, EpetraExt::ModelEvaluator::EVAL_TYPE_EXACT); outargs.set_f(eval_f); } Teuchos::RefCountPtr<Epetra_MultiVector> DfDp = Teuchos::rcp(&epetra_dfdp, false); Teuchos::Array<int> param_indexes(param_ids.size()); for (unsigned int i=0; i<param_ids.size(); i++) param_indexes[i] = param_ids[i]; EpetraExt::ModelEvaluator::DerivativeMultiVector dmv(DfDp, EpetraExt::ModelEvaluator::DERIV_MV_BY_COL, param_indexes); EpetraExt::ModelEvaluator::Derivative deriv(dmv); outargs.set_DfDp(0, deriv); model_->evalModel(inargs, outargs); return NOX::Abstract::Group::Ok; }
double LOCA::DerivUtils::perturbXVec(LOCA::MultiContinuation::AbstractGroup& grp, const NOX::Abstract::Vector& xVector, const NOX::Abstract::Vector& aVector) const { // Allocate tempertory xVector Teuchos::RCP<NOX::Abstract::Vector> tmpXVecPtr = xVector.clone(NOX::DeepCopy); // Get perturbation size for directional derivative double eps = epsVector(*tmpXVecPtr, aVector); // Perturb temp vector and copy into group's x vector grp.setX(tmpXVecPtr->update(eps, aVector, 1.0)); // Return perturbation size return eps; }
NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDwtJnDx(LOCA::MultiContinuation::AbstractGroup& grp, const NOX::Abstract::MultiVector& w, const NOX::Abstract::Vector& nullVector, NOX::Abstract::MultiVector& result) const { string callingFunction = "LOCA::DerivUtils::computeDwtJnDx()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Vector to store w^T*J Teuchos::RCP<NOX::Abstract::MultiVector> wtJ = w.clone(NOX::ShapeCopy); // Compute base w^T*J finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); status = grp.applyJacobianTransposeMultiVector(w, *wtJ); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Copy original solution vector Teuchos::RCP<NOX::Abstract::Vector> Xvec = grp.getX().clone(NOX::DeepCopy); // Perturb solution vector in direction of nullVector, return perturbation double eps = perturbXVec(grp, *Xvec, nullVector); // Fill perturbed w^T*J vector finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); status = grp.applyJacobianTransposeMultiVector(w, result); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Difference perturbed and base vector result.update(-1.0, *wtJ, 1.0); result.scale(1.0/eps); // Restore original solution vector grp.setX(*Xvec); return finalStatus; }
NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDwtJDp(LOCA::MultiContinuation::AbstractGroup& grp, const vector<int>& paramIDs, const NOX::Abstract::Vector& w, NOX::Abstract::MultiVector& result, bool isValid) const { string callingFunction = "LOCA::DerivUtils::computeDwtJDp()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Views of w^T*J, d(w^T*J)/dp NOX::Abstract::Vector *wtJ = &result[0]; NOX::Abstract::Vector *dwtJdp = NULL; // Compute base residual w^T*J if (!isValid) { finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); status = grp.applyJacobianTranspose(w, *wtJ); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } else finalStatus = NOX::Abstract::Group::Ok; double param; double eps; // Loop over each parameter for (unsigned int i=0; i<paramIDs.size(); i++) { // Perturb single parameter in this group, and return perturbation, eps eps = perturbParam(grp, param, paramIDs[i]); // Fill perturbed w^T*J vector status = grp.computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); dwtJdp = &result[i+1]; status = grp.applyJacobianTranspose(w, *dwtJdp); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Difference perturbed and base vector dwtJdp->update(-1.0, *wtJ, 1.0); dwtJdp->scale(1.0/eps); // Restore original parameter value grp.setParam(paramIDs[i], param); } return finalStatus; }
NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDwtJnDp( LOCA::MultiContinuation::AbstractGroup& grp, const vector<int>& paramIDs, const NOX::Abstract::Vector& w, const NOX::Abstract::Vector& nullVector, NOX::Abstract::MultiVector::DenseMatrix& result, bool isValid) const { string callingFunction = "LOCA::DerivUtils::computeDwtJnDp()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Vector to store J*n Teuchos::RCP<NOX::Abstract::Vector> Jn = w.clone(NOX::ShapeCopy); double base_wtJn; // Compute base w^T*J*n if (!isValid) { // Compute J finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); // Compute J*n status = grp.applyJacobian(nullVector, *Jn); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute w^T*J*n base_wtJn = w.innerProduct(*Jn); result(0,0) = base_wtJn; } else { base_wtJn = result(0,0); finalStatus = NOX::Abstract::Group::Ok; } double param; double eps; double perturb_wtJn; // Loop over each parameter for (unsigned int i=0; i<paramIDs.size(); i++) { // Perturb single parameter in this group, and return perturbation, eps eps = perturbParam(grp, param, paramIDs[i]); // Compute perturbed J status = grp.computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute perturbed J*n status = grp.applyJacobian(nullVector, *Jn); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute perturbed w^T*J*n perturb_wtJn = w.innerProduct(*Jn); // Difference perturbed and base values result(0,i+1) = (perturb_wtJn - base_wtJn) / eps; // Restore original parameter value grp.setParam(paramIDs[i], param); } return finalStatus; }