PetscErrorCode SNESSolve_Composite(SNES snes) { Vec F; Vec X; Vec B; PetscInt i; PetscReal fnorm = 0.0, xnorm = 0.0, snorm = 0.0; PetscErrorCode ierr; SNESNormSchedule normtype; SNES_Composite *comp = (SNES_Composite*)snes->data; PetscFunctionBegin; X = snes->vec_sol; F = snes->vec_func; B = snes->vec_rhs; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; comp->innerFailures = 0; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESSetWorkVecs(snes, 1);CHKERRQ(ierr); snes->reason = SNES_CONVERGED_ITERATING; ierr = SNESGetNormSchedule(snes, &normtype);CHKERRQ(ierr); if (normtype == SNES_NORM_ALWAYS || normtype == SNES_NORM_INITIAL_ONLY || normtype == SNES_NORM_INITIAL_FINAL_ONLY) { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); } else snes->vec_func_init_set = PETSC_FALSE; if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, &fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ } SNESCheckFunctionNorm(snes,fnorm); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); } else { ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); } /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } for (i = 0; i < snes->max_its; i++) { /* Copy the state before modification by application of the composite solver; we will subtract the new state after application */ ierr = VecCopy(X, snes->work[0]);CHKERRQ(ierr); if (comp->type == SNES_COMPOSITE_ADDITIVE) { ierr = SNESCompositeApply_Additive(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else if (comp->type == SNES_COMPOSITE_MULTIPLICATIVE) { ierr = SNESCompositeApply_Multiplicative(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else if (comp->type == SNES_COMPOSITE_ADDITIVEOPTIMAL) { ierr = SNESCompositeApply_AdditiveOptimal(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported SNESComposite type"); if (snes->reason < 0) break; /* Compute the solution update for convergence testing */ ierr = VecAXPY(snes->work[0], -1.0, X);CHKERRQ(ierr); ierr = VecScale(snes->work[0], -1.0);CHKERRQ(ierr); if ((i == snes->max_its - 1) && (normtype == SNES_NORM_INITIAL_FINAL_ONLY || normtype == SNES_NORM_FINAL_ONLY)) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->xl && snes->xu) { ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, &fnorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } else { ierr = VecNormBegin(F, NORM_2, &fnorm);CHKERRQ(ierr); ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = VecNormEnd(F, NORM_2, &fnorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,fnorm); } else if (normtype == SNES_NORM_ALWAYS) { ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ if (normtype == SNES_NORM_ALWAYS) {ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,snorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);} if (snes->reason) break; /* Call general purpose update function */ if (snes->ops->update) {ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);} } if (normtype == SNES_NORM_ALWAYS) { if (i == snes->max_its) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",snes->max_its);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; PetscFunctionReturn(0); }
static PetscErrorCode SNESCompositeApply_Multiplicative(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec FSub; SNESConvergedReason reason; PetscFunctionBegin; if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } while (next->next) { /* only copy the function over in the case where the functions correspond */ if (next->snes->pcside == PC_RIGHT && next->snes->normschedule != SNES_NORM_NONE) { ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); next = next->next; ierr = SNESSetInitialFunction(next->snes,FSub);CHKERRQ(ierr); } else { next = next->next; } ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } if (next->snes->pcside == PC_RIGHT) { ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); ierr = VecCopy(FSub,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } else if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } PetscFunctionReturn(0); }
static PetscErrorCode SNESCompositeApply_Additive(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec Y,Xorig; SNESConvergedReason reason; PetscFunctionBegin; Y = snes->vec_sol_update; if (!jac->Xorig) {ierr = VecDuplicate(X,&jac->Xorig);CHKERRQ(ierr);} Xorig = jac->Xorig; ierr = VecCopy(X,Xorig);CHKERRQ(ierr); if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); while (next->next) { next = next->next; ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } } next = jac->head; ierr = VecCopy(Xorig,Y);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Y);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } ierr = VecAXPY(Y,-1.0,Xorig);CHKERRQ(ierr); ierr = VecAXPY(X,next->dmp,Y);CHKERRQ(ierr); while (next->next) { next = next->next; ierr = VecCopy(Xorig,Y);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Y);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } ierr = VecAXPY(Y,-1.0,Xorig);CHKERRQ(ierr); ierr = VecAXPY(X,next->dmp,Y);CHKERRQ(ierr); } if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } PetscFunctionReturn(0); }
/* approximately solve the overdetermined system: 2*F(x_i)\cdot F(\x_j)\alpha_i = 0 \alpha_i = 1 Which minimizes the L2 norm of the linearization of: ||F(\sum_i \alpha_i*x_i)||^2 With the constraint that \sum_i\alpha_i = 1 Where x_i is the solution from the ith subsolver. */ static PetscErrorCode SNESCompositeApply_AdditiveOptimal(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec *Xes = jac->Xes,*Fes = jac->Fes; PetscInt i,j; PetscScalar tot,total,ftf; PetscReal min_fnorm; PetscInt min_i; SNESConvergedReason reason; PetscFunctionBegin; if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { next = jac->head; ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); while (next->next) { next = next->next; ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } } next = jac->head; i = 0; ierr = VecCopy(X,Xes[i]);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Xes[i]);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } while (next->next) { i++; next = next->next; ierr = VecCopy(X,Xes[i]);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Xes[i]);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } /* all the solutions are collected; combine optimally */ for (i=0;i<jac->n;i++) { for (j=0;j<i+1;j++) { ierr = VecDotBegin(Fes[i],Fes[j],&jac->h[i + j*jac->n]);CHKERRQ(ierr); } ierr = VecDotBegin(Fes[i],F,&jac->g[i]);CHKERRQ(ierr); } for (i=0;i<jac->n;i++) { for (j=0;j<i+1;j++) { ierr = VecDotEnd(Fes[i],Fes[j],&jac->h[i + j*jac->n]);CHKERRQ(ierr); if (i == j) jac->fnorms[i] = PetscSqrtReal(PetscRealPart(jac->h[i + j*jac->n])); } ierr = VecDotEnd(Fes[i],F,&jac->g[i]);CHKERRQ(ierr); } ftf = (*fnorm)*(*fnorm); for (i=0; i<jac->n; i++) { for (j=i+1;j<jac->n;j++) { jac->h[i + j*jac->n] = jac->h[j + i*jac->n]; } } for (i=0; i<jac->n; i++) { for (j=0; j<jac->n; j++) { jac->h[i + j*jac->n] = jac->h[i + j*jac->n] - jac->g[j] - jac->g[i] + ftf; } jac->beta[i] = ftf - jac->g[i]; } #if defined(PETSC_MISSING_LAPACK_GELSS) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"SNESCOMPOSITE with ADDITIVEOPTIMAL requires the LAPACK GELSS routine."); #else jac->info = 0; jac->rcond = -1.; ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) PetscStackCall("LAPACKgelss",LAPACKgelss_(&jac->n,&jac->n,&jac->nrhs,jac->h,&jac->lda,jac->beta,&jac->lda,jac->s,&jac->rcond,&jac->rank,jac->work,&jac->lwork,jac->rwork,&jac->info)); #else PetscStackCall("LAPACKgelss",LAPACKgelss_(&jac->n,&jac->n,&jac->nrhs,jac->h,&jac->lda,jac->beta,&jac->lda,jac->s,&jac->rcond,&jac->rank,jac->work,&jac->lwork,&jac->info)); #endif ierr = PetscFPTrapPop();CHKERRQ(ierr); if (jac->info < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"Bad argument to GELSS"); if (jac->info > 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD failed to converge"); #endif tot = 0.; total = 0.; for (i=0; i<jac->n; i++) { if (snes->errorifnotconverged && PetscIsInfOrNanScalar(jac->beta[i])) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD generated inconsistent output"); ierr = PetscInfo2(snes,"%D: %g\n",i,(double)PetscRealPart(jac->beta[i]));CHKERRQ(ierr); tot += jac->beta[i]; total += PetscAbsScalar(jac->beta[i]); } ierr = VecScale(X,(1. - tot));CHKERRQ(ierr); ierr = VecMAXPY(X,jac->n,jac->beta,Xes);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } /* take the minimum-normed candidate if it beats the combination by a factor of rtol or the combination has stagnated */ min_fnorm = jac->fnorms[0]; min_i = 0; for (i=0; i<jac->n; i++) { if (jac->fnorms[i] < min_fnorm) { min_fnorm = jac->fnorms[i]; min_i = i; } } /* stagnation or divergence restart to the solution of the solver that failed the least */ if (PetscRealPart(total) < jac->stol || min_fnorm*jac->rtol < *fnorm) { ierr = VecCopy(jac->Xes[min_i],X);CHKERRQ(ierr); ierr = VecCopy(jac->Fes[min_i],F);CHKERRQ(ierr); *fnorm = min_fnorm; } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_VINEWTONRSLS(SNES snes) { SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*)snes->data; PetscErrorCode ierr; PetscInt maxits,i,lits; PetscBool lssucceed; MatStructure flg = DIFFERENT_NONZERO_PATTERN; PetscReal fnorm,gnorm,xnorm=0,ynorm; Vec Y,X,F; KSPConvergedReason kspreason; PetscFunctionBegin; snes->numFailures = 0; snes->numLinearSolveFailures = 0; snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* solution vector */ F = snes->vec_func; /* residual vector */ Y = snes->work[0]; /* work vectors */ ierr = SNESLineSearchSetVIFunctions(snes->linesearch, SNESVIProjectOntoBounds, SNESVIComputeInactiveSetFnorm);CHKERRQ(ierr); ierr = SNESLineSearchSetVecs(snes->linesearch, X, PETSC_NULL, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = SNESLineSearchSetUp(snes->linesearch);CHKERRQ(ierr); ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.0; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(fnorm)) SETERRQ(((PetscObject)X)->comm,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); SNESLogConvHistory(snes,fnorm,0); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* set parameter for default relative tolerance convergence test */ snes->ttol = fnorm*snes->rtol; /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); for (i=0; i<maxits; i++) { IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ IS IS_redact; /* redundant active set */ VecScatter scat_act,scat_inact; PetscInt nis_act,nis_inact; Vec Y_act,Y_inact,F_inact; Mat jac_inact_inact,prejac_inact_inact; PetscBool isequal; /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); /* Create active and inactive index sets */ /*original ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); */ ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr); if (vi->checkredundancy) { (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr); if (IS_redact){ ierr = ISSort(IS_redact);CHKERRQ(ierr); ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); } else { ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); } } else { ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); } /* Create inactive set submatrix */ ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); if (0) { /* Dead code (temporary developer hack) */ IS keptrows; ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); if (keptrows) { PetscInt cnt,*nrows,k; const PetscInt *krows,*inact; PetscInt rstart=jac_inact_inact->rmap->rstart; ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); ierr = ISDestroy(&IS_act);CHKERRQ(ierr); ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); for (k=0; k<cnt; k++) { nrows[k] = inact[krows[k]-rstart]; } ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); ierr = ISDestroy(&keptrows);CHKERRQ(ierr); ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); ierr = ISCreateGeneral(((PetscObject)snes)->comm,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); } } ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr); /* remove later */ /* ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(((PetscObject)(vi->xu))->comm));CHKERRQ(ierr); ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(((PetscObject)(vi->xl))->comm));CHKERRQ(ierr); ierr = VecView(X,PETSC_VIEWER_BINARY_(((PetscObject)X)->comm));CHKERRQ(ierr); ierr = VecView(F,PETSC_VIEWER_BINARY_(((PetscObject)F)->comm));CHKERRQ(ierr); ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(((PetscObject)IS_inact)->comm));CHKERRQ(ierr); */ /* Get sizes of active and inactive sets */ ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); /* Create active and inactive set vectors */ ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_inact,&F_inact);CHKERRQ(ierr); ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_act,&Y_act);CHKERRQ(ierr); ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_inact,&Y_inact);CHKERRQ(ierr); /* Create scatter contexts */ ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); /* Do a vec scatter to active and inactive set vectors */ ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); /* Active set direction = 0 */ ierr = VecSet(Y_act,0);CHKERRQ(ierr); if (snes->jacobian != snes->jacobian_pre) { ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); } else prejac_inact_inact = jac_inact_inact; ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); if (!isequal) { ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); flg = DIFFERENT_NONZERO_PATTERN; } /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ /* ierr = MatView(snes->jacobian_pre,0); */ ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); { PC pc; PetscBool flg; ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); if (flg) { KSP *subksps; ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); ierr = PetscFree(subksps);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); if (flg) { PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; const PetscInt *ii; ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); for (j=0; j<n; j++) { if (ii[j] < N) cnts[0]++; else if (ii[j] < 2*N) cnts[1]++; else if (ii[j] < 3*N) cnts[2]++; } ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); } } } ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); if (kspreason < 0) { if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); snes->reason = SNES_DIVERGED_LINEAR_SOLVE; break; } } ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecDestroy(&F_inact);CHKERRQ(ierr); ierr = VecDestroy(&Y_act);CHKERRQ(ierr); ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); ierr = ISDestroy(&IS_act);CHKERRQ(ierr); if (!isequal) { ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); } ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); if (snes->jacobian != snes->jacobian_pre) { ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); } ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); snes->linear_its += lits; ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); /* if (snes->ops->precheck) { PetscBool changed_y = PETSC_FALSE; ierr = (*snes->ops->precheck)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr); } if (PetscLogPrintInfo){ ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); } */ /* Compute a (scaled) negative update in the line search routine: Y <- X - lambda*Y and evaluate G = function(Y) (depends on the line search). */ ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); ynorm = 1; gnorm = fnorm; ierr = SNESLineSearchApply(snes->linesearch, X, F, &gnorm, Y);CHKERRQ(ierr); ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &gnorm, &ynorm);CHKERRQ(ierr); ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); PetscFunctionReturn(0); } ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr); if (!lssucceed) { if (++snes->numFailures >= snes->maxFailures) { PetscBool ismin; snes->reason = SNES_DIVERGED_LINE_SEARCH; ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,F,X,gnorm,&ismin);CHKERRQ(ierr); if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; break; } } /* Update function and solution vectors */ fnorm = gnorm; /* Monitor convergence */ ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); SNESLogConvHistory(snes,snes->norm,lits); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence, xnorm = || X || */ if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) break; } ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); if (i == maxits) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }