PETSC_EXTERN void PETSC_STDCALL taolinesearchsetobjectiveandgradientroutine_(TaoLineSearch *ls, void (PETSC_STDCALL *func)(TaoLineSearch*, Vec *, PetscReal *, Vec *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr) { CHKFORTRANNULLOBJECT(ctx); PetscObjectAllocateFortranPointers(*ls,NFUNCS); if (!func) { *ierr = TaoLineSearchSetObjectiveAndGradientRoutine(*ls,0,ctx); } else { ((PetscObject)*ls)->fortran_func_pointers[OBJGRAD] = (PetscVoidFunction)func; *ierr = TaoLineSearchSetObjectiveAndGradientRoutine(*ls, ourtaolinesearchobjectiveandgradientroutine,ctx); } }
PETSC_EXTERN PetscErrorCode TaoCreate_GPCG(Tao tao) { TAO_GPCG *gpcg; PetscErrorCode ierr; PetscFunctionBegin; tao->ops->setup = TaoSetup_GPCG; tao->ops->solve = TaoSolve_GPCG; tao->ops->view = TaoView_GPCG; tao->ops->setfromoptions = TaoSetFromOptions_GPCG; tao->ops->destroy = TaoDestroy_GPCG; tao->ops->computedual = TaoComputeDual_GPCG; ierr = PetscNewLog(tao,&gpcg);CHKERRQ(ierr); tao->data = (void*)gpcg; /* Override default settings (unless already changed) */ if (!tao->max_it_changed) tao->max_it=500; if (!tao->max_funcs_changed) tao->max_funcs = 100000; #if defined(PETSC_USE_REAL_SINGLE) if (!tao->fatol_changed) tao->fatol=1e-6; if (!tao->frtol_changed) tao->frtol=1e-6; if (!tao->gatol_changed) tao->grtol=1e-6; if (!tao->grtol_changed) tao->grtol=1e-6; #else if (!tao->fatol_changed) tao->fatol=1e-12; if (!tao->frtol_changed) tao->frtol=1e-12; if (!tao->gatol_changed) tao->grtol=1e-12; if (!tao->grtol_changed) tao->grtol=1e-12; #endif /* Initialize pointers and variables */ gpcg->n=0; gpcg->maxgpits = 8; gpcg->pg_ftol = 0.1; gpcg->gp_iterates=0; /* Cumulative number */ gpcg->total_gp_its = 0; /* Initialize pointers and variables */ gpcg->n_bind=0; gpcg->n_free = 0; gpcg->n_upper=0; gpcg->n_lower=0; gpcg->subset_type = TAO_SUBSET_MASK; gpcg->Hsub=NULL; gpcg->Hsub_pre=NULL; ierr = KSPCreate(((PetscObject)tao)->comm, &tao->ksp);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(tao->ksp, tao->hdr.prefix);CHKERRQ(ierr); ierr = KSPSetType(tao->ksp,KSPNASH);CHKERRQ(ierr); ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr); ierr = TaoLineSearchSetType(tao->linesearch, TAOLINESEARCHGPCG);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch, GPCGObjectiveAndGradient, tao);CHKERRQ(ierr); ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode TaoSolve_SSILS(Tao tao) { TAO_SSLS *ssls = (TAO_SSLS *)tao->data; PetscReal psi, ndpsi, normd, innerd, t=0; PetscReal delta, rho; PetscInt iter=0,kspits; TaoConvergedReason reason; TaoLineSearchConvergedReason ls_reason; PetscErrorCode ierr; PetscFunctionBegin; /* Assume that Setup has been called! Set the structure for the Jacobian and create a linear solver. */ delta = ssls->delta; rho = ssls->rho; ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,Tao_SSLS_FunctionGradient,tao);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveRoutine(tao->linesearch,Tao_SSLS_Function,tao);CHKERRQ(ierr); /* Calculate the function value and fischer function value at the current iterate */ ierr = TaoLineSearchComputeObjectiveAndGradient(tao->linesearch,tao->solution,&psi,ssls->dpsi);CHKERRQ(ierr); ierr = VecNorm(ssls->dpsi,NORM_2,&ndpsi);CHKERRQ(ierr); while (1) { ierr=PetscInfo3(tao, "iter: %D, merit: %g, ndpsi: %g\n",iter, (double)ssls->merit, (double)ndpsi);CHKERRQ(ierr); /* Check the termination criteria */ ierr = TaoMonitor(tao,iter++,ssls->merit,ndpsi,0.0,t,&reason);CHKERRQ(ierr); if (reason!=TAO_CONTINUE_ITERATING) break; /* Calculate direction. (Really negative of newton direction. Therefore, rest of the code uses -d.) */ ierr = KSPSetOperators(tao->ksp,tao->jacobian,tao->jacobian_pre);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp,ssls->ff,tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr); tao->ksp_its+=kspits; ierr = VecNorm(tao->stepdirection,NORM_2,&normd);CHKERRQ(ierr); ierr = VecDot(tao->stepdirection,ssls->dpsi,&innerd);CHKERRQ(ierr); /* Make sure that we have a descent direction */ if (innerd <= delta*pow(normd, rho)) { ierr = PetscInfo(tao, "newton direction not descent\n");CHKERRQ(ierr); ierr = VecCopy(ssls->dpsi,tao->stepdirection);CHKERRQ(ierr); ierr = VecDot(tao->stepdirection,ssls->dpsi,&innerd);CHKERRQ(ierr); } ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); innerd = -innerd; ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0); ierr = TaoLineSearchApply(tao->linesearch,tao->solution,&psi,ssls->dpsi,tao->stepdirection,&t,&ls_reason);CHKERRQ(ierr); ierr = VecNorm(ssls->dpsi,NORM_2,&ndpsi);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*MC TAOGPCG - gradient projected conjugate gradient algorithm is an active-set conjugate-gradient based method for bound-constrained minimization Options Database Keys: + -tao_gpcg_maxpgits - maximum number of gradient projections for GPCG iterate - -tao_subset_type - "subvec","mask","matrix-free", strategies for handling active-sets Level: beginner M*/ EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "TaoCreate_GPCG" PetscErrorCode TaoCreate_GPCG(Tao tao) { TAO_GPCG *gpcg; PetscErrorCode ierr; PetscFunctionBegin; tao->ops->setup = TaoSetup_GPCG; tao->ops->solve = TaoSolve_GPCG; tao->ops->view = TaoView_GPCG; tao->ops->setfromoptions = TaoSetFromOptions_GPCG; tao->ops->destroy = TaoDestroy_GPCG; tao->ops->computedual = TaoComputeDual_GPCG; ierr = PetscNewLog(tao,&gpcg);CHKERRQ(ierr); tao->data = (void*)gpcg; tao->max_it = 500; tao->max_funcs = 100000; #if defined(PETSC_USE_REAL_SINGLE) tao->fatol = 1e-6; tao->frtol = 1e-6; #else tao->fatol = 1e-12; tao->frtol = 1e-12; #endif /* Initialize pointers and variables */ gpcg->n=0; gpcg->maxgpits = 8; gpcg->pg_ftol = 0.1; gpcg->gp_iterates=0; /* Cumulative number */ gpcg->total_gp_its = 0; /* Initialize pointers and variables */ gpcg->n_bind=0; gpcg->n_free = 0; gpcg->n_upper=0; gpcg->n_lower=0; gpcg->subset_type = TAO_SUBSET_MASK; /* gpcg->ksp_type = GPCG_KSP_STCG; */ ierr = KSPCreate(((PetscObject)tao)->comm, &tao->ksp);CHKERRQ(ierr); ierr = KSPSetType(tao->ksp,KSPNASH);CHKERRQ(ierr); ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr); ierr = TaoLineSearchSetType(tao->linesearch, TAOLINESEARCHGPCG);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch, GPCGObjectiveAndGradient, tao);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode TaoSolve_ASILS(Tao tao) { TAO_SSLS *asls = (TAO_SSLS *)tao->data; PetscReal psi,ndpsi, normd, innerd, t=0; PetscInt iter=0, nf; PetscErrorCode ierr; TaoConvergedReason reason; TaoLineSearchConvergedReason ls_reason; PetscFunctionBegin; /* Assume that Setup has been called! Set the structure for the Jacobian and create a linear solver. */ ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,Tao_ASLS_FunctionGradient,tao);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveRoutine(tao->linesearch,Tao_SSLS_Function,tao);CHKERRQ(ierr); /* Calculate the function value and fischer function value at the current iterate */ ierr = TaoLineSearchComputeObjectiveAndGradient(tao->linesearch,tao->solution,&psi,asls->dpsi);CHKERRQ(ierr); ierr = VecNorm(asls->dpsi,NORM_2,&ndpsi);CHKERRQ(ierr); while (1) { /* Check the termination criteria */ ierr = PetscInfo3(tao,"iter %D, merit: %g, ||dpsi||: %g\n",iter, (double)asls->merit, (double)ndpsi);CHKERRQ(ierr); ierr = TaoMonitor(tao, iter++, asls->merit, ndpsi, 0.0, t, &reason);CHKERRQ(ierr); if (TAO_CONTINUE_ITERATING != reason) break; /* We are going to solve a linear system of equations. We need to set the tolerances for the solve so that we maintain an asymptotic rate of convergence that is superlinear. Note: these tolerances are for the reduced system. We really need to make sure that the full system satisfies the full-space conditions. This rule gives superlinear asymptotic convergence asls->atol = min(0.5, asls->merit*sqrt(asls->merit)); asls->rtol = 0.0; This rule gives quadratic asymptotic convergence asls->atol = min(0.5, asls->merit*asls->merit); asls->rtol = 0.0; Calculate a free and fixed set of variables. The fixed set of variables are those for the d_b is approximately equal to zero. The definition of approximately changes as we approach the solution to the problem. No one rule is guaranteed to work in all cases. The following definition is based on the norm of the Jacobian matrix. If the norm is large, the tolerance becomes smaller. */ ierr = MatNorm(tao->jacobian,NORM_1,&asls->identifier);CHKERRQ(ierr); asls->identifier = PetscMin(asls->merit, 1e-2) / (1 + asls->identifier); ierr = VecSet(asls->t1,-asls->identifier);CHKERRQ(ierr); ierr = VecSet(asls->t2, asls->identifier);CHKERRQ(ierr); ierr = ISDestroy(&asls->fixed);CHKERRQ(ierr); ierr = ISDestroy(&asls->free);CHKERRQ(ierr); ierr = VecWhichBetweenOrEqual(asls->t1, asls->db, asls->t2, &asls->fixed);CHKERRQ(ierr); ierr = ISComplementVec(asls->fixed,asls->t1, &asls->free);CHKERRQ(ierr); ierr = ISGetSize(asls->fixed,&nf);CHKERRQ(ierr); ierr = PetscInfo1(tao,"Number of fixed variables: %D\n", nf);CHKERRQ(ierr); /* We now have our partition. Now calculate the direction in the fixed variable space. */ ierr = TaoVecGetSubVec(asls->ff, asls->fixed, tao->subset_type, 0.0, &asls->r1); ierr = TaoVecGetSubVec(asls->da, asls->fixed, tao->subset_type, 1.0, &asls->r2); ierr = VecPointwiseDivide(asls->r1,asls->r1,asls->r2);CHKERRQ(ierr); ierr = VecSet(tao->stepdirection,0.0);CHKERRQ(ierr); ierr = VecISAXPY(tao->stepdirection, asls->fixed,1.0,asls->r1);CHKERRQ(ierr); /* Our direction in the Fixed Variable Set is fixed. Calculate the information needed for the step in the Free Variable Set. To do this, we need to know the diagonal perturbation and the right hand side. */ ierr = TaoVecGetSubVec(asls->da, asls->free, tao->subset_type, 0.0, &asls->r1);CHKERRQ(ierr); ierr = TaoVecGetSubVec(asls->ff, asls->free, tao->subset_type, 0.0, &asls->r2);CHKERRQ(ierr); ierr = TaoVecGetSubVec(asls->db, asls->free, tao->subset_type, 1.0, &asls->r3);CHKERRQ(ierr); ierr = VecPointwiseDivide(asls->r1,asls->r1, asls->r3);CHKERRQ(ierr); ierr = VecPointwiseDivide(asls->r2,asls->r2, asls->r3);CHKERRQ(ierr); /* r1 is the diagonal perturbation r2 is the right hand side r3 is no longer needed Now need to modify r2 for our direction choice in the fixed variable set: calculate t1 = J*d, take the reduced vector of t1 and modify r2. */ ierr = MatMult(tao->jacobian, tao->stepdirection, asls->t1);CHKERRQ(ierr); ierr = TaoVecGetSubVec(asls->t1,asls->free,tao->subset_type,0.0,&asls->r3);CHKERRQ(ierr); ierr = VecAXPY(asls->r2, -1.0, asls->r3);CHKERRQ(ierr); /* Calculate the reduced problem matrix and the direction */ if (!asls->w && (tao->subset_type == TAO_SUBSET_MASK || tao->subset_type == TAO_SUBSET_MATRIXFREE)) { ierr = VecDuplicate(tao->solution, &asls->w);CHKERRQ(ierr); } ierr = TaoMatGetSubMat(tao->jacobian, asls->free, asls->w, tao->subset_type,&asls->J_sub);CHKERRQ(ierr); if (tao->jacobian != tao->jacobian_pre) { ierr = TaoMatGetSubMat(tao->jacobian_pre, asls->free, asls->w, tao->subset_type, &asls->Jpre_sub);CHKERRQ(ierr); } else { ierr = MatDestroy(&asls->Jpre_sub);CHKERRQ(ierr); asls->Jpre_sub = asls->J_sub; ierr = PetscObjectReference((PetscObject)(asls->Jpre_sub));CHKERRQ(ierr); } ierr = MatDiagonalSet(asls->J_sub, asls->r1,ADD_VALUES);CHKERRQ(ierr); ierr = TaoVecGetSubVec(tao->stepdirection, asls->free, tao->subset_type, 0.0, &asls->dxfree);CHKERRQ(ierr); ierr = VecSet(asls->dxfree, 0.0);CHKERRQ(ierr); /* Calculate the reduced direction. (Really negative of Newton direction. Therefore, rest of the code uses -d.) */ ierr = KSPReset(tao->ksp); ierr = KSPSetOperators(tao->ksp, asls->J_sub, asls->Jpre_sub);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, asls->r2, asls->dxfree);CHKERRQ(ierr); /* Add the direction in the free variables back into the real direction. */ ierr = VecISAXPY(tao->stepdirection, asls->free, 1.0,asls->dxfree);CHKERRQ(ierr); /* Check the real direction for descent and if not, use the negative gradient direction. */ ierr = VecNorm(tao->stepdirection, NORM_2, &normd);CHKERRQ(ierr); ierr = VecDot(tao->stepdirection, asls->dpsi, &innerd);CHKERRQ(ierr); if (innerd <= asls->delta*pow(normd, asls->rho)) { ierr = PetscInfo1(tao,"Gradient direction: %5.4e.\n", (double)innerd);CHKERRQ(ierr); ierr = PetscInfo1(tao, "Iteration %D: newton direction not descent\n", iter);CHKERRQ(ierr); ierr = VecCopy(asls->dpsi, tao->stepdirection);CHKERRQ(ierr); ierr = VecDot(asls->dpsi, tao->stepdirection, &innerd);CHKERRQ(ierr); } ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); innerd = -innerd; /* We now have a correct descent direction. Apply a linesearch to find the new iterate. */ ierr = TaoLineSearchSetInitialStepLength(tao->linesearch, 1.0);CHKERRQ(ierr); ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &psi,asls->dpsi, tao->stepdirection, &t, &ls_reason);CHKERRQ(ierr); ierr = VecNorm(asls->dpsi, NORM_2, &ndpsi);CHKERRQ(ierr); } PetscFunctionReturn(0); }