void N_VAbs_Petsc(N_Vector x, N_Vector z) { Vec *xv = NV_PVEC_PTC(x); Vec *zv = NV_PVEC_PTC(z); if(z != x) VecCopy(*xv, *zv); /* copy x~>z */ VecAbs(*zv); return; }
void PetscVector<T>::abs() { this->_restore_array(); PetscErrorCode ierr = 0; if(this->type() != GHOSTED) { ierr = VecAbs(_vec); CHKERRABORT(libMesh::COMM_WORLD,ierr); } else { Vec loc_vec; ierr = VecGhostGetLocalForm (_vec,&loc_vec); CHKERRABORT(libMesh::COMM_WORLD,ierr); ierr = VecAbs(loc_vec); CHKERRABORT(libMesh::COMM_WORLD,ierr); ierr = VecGhostRestoreLocalForm (_vec,&loc_vec); CHKERRABORT(libMesh::COMM_WORLD,ierr); } }
/* Stokes output: --------------------------------- Operator summary: K G f, h u p --------------------------------- Solution summary: max_u min_u average_u |r_1| |r_2| --------------------------------- Solver summary: name --------------------------------- Petsc build summary: */ PetscErrorCode BSSCR_stokes_output( PetscViewer v, Mat stokes_A, Vec stokes_b, Vec stokes_x, KSP ksp, PetscInt monitor_index ) { Mat K,G,D,C; Vec f,h, u,p; K = G = D = C = PETSC_NULL; f = h = PETSC_NULL; u = p = PETSC_NULL; MatNestGetSubMat( stokes_A, 0,0, &K ); MatNestGetSubMat( stokes_A, 0,1, &G ); MatNestGetSubMat( stokes_A, 1,0, &D ); MatNestGetSubMat( stokes_A, 1,1, &C ); VecNestGetSubVec( stokes_x, 0, &u ); VecNestGetSubVec( stokes_x, 1, &p ); VecNestGetSubVec( stokes_b, 0, &f ); VecNestGetSubVec( stokes_b, 1, &h ); PetscViewerASCIIPrintf( v, "Stokes Output:\n"); PetscViewerASCIIPushTab( v ); /*--------------------------------------------------------------------------------------------*/ PetscViewerASCIIPrintf( v, "--------------------------------------------------\n"); PetscViewerASCIIPrintf( v, "Operator summary:\n"); PetscViewerASCIIPushTab( v ); if (K) { BSSCR_MatInfoLog(v,K, "stokes_A11"); PetscViewerASCIIPrintf( v, "\n"); } if (G) { BSSCR_MatInfoLog(v,G, "stokes_A12"); PetscViewerASCIIPrintf( v, "\n"); } if (D) { BSSCR_MatInfoLog(v,D, "stokes_A21"); PetscViewerASCIIPrintf( v, "\n"); } if (C) { BSSCR_MatInfoLog(v,C, "stokes_A22"); PetscViewerASCIIPrintf( v, "\n"); } if (f) { BSSCR_VecInfoLog(v,f,"stokes_b1"); PetscViewerASCIIPrintf( v, "\n"); } if (h) { BSSCR_VecInfoLog(v,h,"stokes_b2"); PetscViewerASCIIPrintf( v, "\n"); } PetscViewerASCIIPopTab( v ); /*--------------------------------------------------------------------------------------------*/ PetscViewerASCIIPrintf( v, "--------------------------------------------------\n"); PetscViewerASCIIPrintf( v, "Solution summary:\n"); PetscViewerASCIIPushTab( v ); if (u) { BSSCR_VecInfoLog(v,u,"x1"); PetscViewerASCIIPrintf( v, "\n"); } if (p) { BSSCR_VecInfoLog(v,p,"x2"); PetscViewerASCIIPrintf( v, "\n"); } { PetscScalar s,sum; PetscReal r,max,min; PetscInt N, loc; double r1,r2; Vec K_d; PetscInt loc_max, loc_min; VecGetSize( u, &N ); VecMax( u, &loc, &r ); PetscViewerASCIIPrintf( v, "u_max: %1.12e [%d] \n", r, loc ); VecMin( u, &loc, &r ); PetscViewerASCIIPrintf( v, "u_min: %1.12e [%d] \n", r, loc ); VecDot( u,u, &s ); PetscViewerASCIIPrintf( v, "u_rms: %1.12e \n", sqrt( PetscRealPart(s) )/N ); VecDuplicate( u, &K_d ); MatGetDiagonal( K, K_d ); VecMax( K_d, &loc_max, &max ); VecMin( K_d, &loc_min, &min ); PetscViewerASCIIPrintf( v,"Algebraic contrast: max(K_d)=%.3e [%d] , min(K_d)=%.3e [%d] , max(K_d)/min(K_d) = %.8e \n", max,loc_max, min,loc_min, max/min ); MatGetRowMax( K, K_d, PETSC_NULL ); VecMax( K_d, &loc_max, &max ); MatGetRowMin( K, K_d, PETSC_NULL ); VecAbs( K_d ); VecMin( K_d, &loc_min, &min ); PetscViewerASCIIPrintf( v,"Algebraic contrast: max(K)=%.3e [%d] , |min(K)|=%.3e [%d] , max(K)/|min(K)| = %.8e \n", max,loc_max, min,loc_min, max/min ); Stg_VecDestroy(&K_d ); PetscViewerASCIIPrintf( v, "\n"); VecGetSize( p, &N ); VecMax( p, &loc, &r ); PetscViewerASCIIPrintf( v, "p_max: %1.12e [%d] \n", r, loc ); VecMin( p, &loc, &r ); PetscViewerASCIIPrintf( v, "p_min: %1.12e [%d] \n", r, loc ); VecDot( p,p, &s ); PetscViewerASCIIPrintf( v, "p_rms: %1.12e \n", sqrt( PetscRealPart(s) )/N ); VecSum( p, &sum ); PetscViewerASCIIPrintf( v, "sum(p): %1.12e \n", sum ); PetscViewerASCIIPrintf( v, "\n"); r1 = BSSCR_StokesMomentumResidual( K,G,f, u,p ); PetscViewerASCIIPrintf( v, "|r1| = %1.12e <momentum> \n", r1 ); r2 = BSSCR_StokesContinuityResidual( G,C,h, u,p ); PetscViewerASCIIPrintf( v, "|r2| = %1.12e <continuity> \n", r2 ); PetscViewerASCIIPrintf( v, "\n"); } PetscViewerASCIIPopTab( v ); /*--------------------------------------------------------------------------------------------*/ if (ksp) { PetscViewerASCIIPrintf( v, "--------------------------------------------------\n"); PetscViewerASCIIPrintf( v, "Solver summary:\n"); PetscViewerASCIIPushTab( v ); BSSCR_KSPLogSolve( v, monitor_index, ksp ); BSSCR_BSSCR_KSPLogSolveSummary( v, monitor_index, ksp ); PetscViewerASCIIPrintf( v, "\n"); PetscViewerASCIIPopTab( v ); } /*--------------------------------------------------------------------------------------------*/ PetscViewerASCIIPrintf( v, "--------------------------------------------------\n"); PetscViewerASCIIPrintf( v, "Petsc build summary:\n"); PetscViewerASCIIPushTab( v ); BSSCR_GeneratePetscHeader_for_viewer( v ); PetscViewerASCIIPrintf( v, "\n"); PetscViewerASCIIPopTab( v ); /*--------------------------------------------------------------------------------------------*/ PetscViewerASCIIPopTab(v); PetscFunctionReturn(0); }
PetscErrorCode PCBDDCScalingSetUp(PC pc) { PC_IS* pcis=(PC_IS*)pc->data; PC_BDDC* pcbddc=(PC_BDDC*)pc->data; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(pc,PC_CLASSID,1); ierr = PetscLogEventBegin(PC_BDDC_Scaling[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr); /* create work vector for the operator */ ierr = VecDestroy(&pcbddc->work_scaling);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_B,&pcbddc->work_scaling);CHKERRQ(ierr); /* always rebuild pcis->D */ if (pcis->use_stiffness_scaling) { PetscScalar *a; PetscInt i,n; ierr = MatGetDiagonal(pcbddc->local_mat,pcis->vec1_N);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecAbs(pcis->D);CHKERRQ(ierr); ierr = VecGetLocalSize(pcis->D,&n);CHKERRQ(ierr); ierr = VecGetArray(pcis->D,&a);CHKERRQ(ierr); for (i=0;i<n;i++) if (PetscAbsScalar(a[i])<PETSC_SMALL) a[i] = 1.0; ierr = VecRestoreArray(pcis->D,&a);CHKERRQ(ierr); } ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->D,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->D,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecPointwiseDivide(pcis->D,pcis->D,pcis->vec1_B);CHKERRQ(ierr); /* now setup */ if (pcbddc->use_deluxe_scaling) { if (!pcbddc->deluxe_ctx) { ierr = PCBDDCScalingCreate_Deluxe(pc);CHKERRQ(ierr); } ierr = PCBDDCScalingSetUp_Deluxe(pc);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingRestriction_C",PCBDDCScalingRestriction_Deluxe);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingExtension_C",PCBDDCScalingExtension_Deluxe);CHKERRQ(ierr); } else { ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingRestriction_C",PCBDDCScalingRestriction_Basic);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingExtension_C",PCBDDCScalingExtension_Basic);CHKERRQ(ierr); } /* test */ if (pcbddc->dbg_flag) { Mat B0_B = NULL; Vec B0_Bv = NULL, B0_Bv2 = NULL; Vec vec2_global; PetscViewer viewer = pcbddc->dbg_viewer; PetscReal error; /* extension -> from local to parallel */ ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr); ierr = VecSetRandom(pcis->vec1_B,NULL);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_global,&vec2_global);CHKERRQ(ierr); ierr = VecCopy(pcis->vec1_global,vec2_global);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); if (pcbddc->benign_n) { IS is_dummy; ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr); ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr); ierr = ISDestroy(&is_dummy);CHKERRQ(ierr); ierr = MatCreateVecs(B0_B,NULL,&B0_Bv);CHKERRQ(ierr); ierr = VecDuplicate(B0_Bv,&B0_Bv2);CHKERRQ(ierr); ierr = MatMult(B0_B,pcis->vec1_B,B0_Bv);CHKERRQ(ierr); } ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,pcis->vec1_global);CHKERRQ(ierr); if (pcbddc->benign_saddle_point) { PetscReal errorl = 0.; ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); if (pcbddc->benign_n) { ierr = MatMult(B0_B,pcis->vec1_B,B0_Bv2);CHKERRQ(ierr); ierr = VecAXPY(B0_Bv,-1.0,B0_Bv2);CHKERRQ(ierr); ierr = VecNorm(B0_Bv,NORM_INFINITY,&errorl);CHKERRQ(ierr); } ierr = MPI_Allreduce(&errorl,&error,1,MPIU_REAL,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer,"Error benign extension %1.14e\n",error);CHKERRQ(ierr); } ierr = VecAXPY(pcis->vec1_global,-1.0,vec2_global);CHKERRQ(ierr); ierr = VecNorm(pcis->vec1_global,NORM_INFINITY,&error);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer,"Error scaling extension %1.14e\n",error);CHKERRQ(ierr); ierr = VecDestroy(&vec2_global);CHKERRQ(ierr); /* restriction -> from parallel to local */ ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr); ierr = VecSetRandom(pcis->vec1_B,NULL);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = PCBDDCScalingRestriction(pc,pcis->vec1_global,pcis->vec1_B);CHKERRQ(ierr); ierr = VecScale(pcis->vec1_B,-1.0);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecNorm(pcis->vec1_global,NORM_INFINITY,&error);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer,"Error scaling restriction %1.14e\n",error);CHKERRQ(ierr); ierr = MatDestroy(&B0_B);CHKERRQ(ierr); ierr = VecDestroy(&B0_Bv);CHKERRQ(ierr); ierr = VecDestroy(&B0_Bv2);CHKERRQ(ierr); } ierr = PetscLogEventEnd(PC_BDDC_Scaling[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode TaoSolve_NTR(Tao tao) { TAO_NTR *tr = (TAO_NTR *)tao->data; PC pc; KSPConvergedReason ksp_reason; TaoConvergedReason reason; PetscReal fmin, ftrial, prered, actred, kappa, sigma, beta; PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius; PetscReal f, gnorm; PetscReal delta; PetscReal norm_d; PetscErrorCode ierr; PetscInt iter = 0; PetscInt bfgsUpdates = 0; PetscInt needH; PetscInt i_max = 5; PetscInt j_max = 1; PetscInt i, j, N, n, its; PetscFunctionBegin; if (tao->XL || tao->XU || tao->ops->computebounds) { ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by ntr algorithm\n");CHKERRQ(ierr); } tao->trust = tao->trust0; /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); if (NTR_PC_BFGS == tr->pc_type && !tr->M) { ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&tr->M);CHKERRQ(ierr); ierr = MatLMVMAllocateVectors(tr->M,tao->solution);CHKERRQ(ierr); } /* Check convergence criteria */ ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient);CHKERRQ(ierr); ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); needH = 1; ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason);CHKERRQ(ierr); if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); /* Create vectors for the limited memory preconditioner */ if ((NTR_PC_BFGS == tr->pc_type) && (BFGS_SCALE_BFGS != tr->bfgs_scale_type)) { if (!tr->Diag) { ierr = VecDuplicate(tao->solution, &tr->Diag);CHKERRQ(ierr); } } switch(tr->ksp_type) { case NTR_KSP_NASH: ierr = KSPSetType(tao->ksp, KSPNASH);CHKERRQ(ierr); if (tao->ksp->ops->setfromoptions) { (*tao->ksp->ops->setfromoptions)(tao->ksp); } break; case NTR_KSP_STCG: ierr = KSPSetType(tao->ksp, KSPSTCG);CHKERRQ(ierr); if (tao->ksp->ops->setfromoptions) { (*tao->ksp->ops->setfromoptions)(tao->ksp); } break; default: ierr = KSPSetType(tao->ksp, KSPGLTR);CHKERRQ(ierr); if (tao->ksp->ops->setfromoptions) { (*tao->ksp->ops->setfromoptions)(tao->ksp); } break; } /* Modify the preconditioner to use the bfgs approximation */ ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr); switch(tr->pc_type) { case NTR_PC_NONE: ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); if (pc->ops->setfromoptions) { (*pc->ops->setfromoptions)(pc); } break; case NTR_PC_AHESS: ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr); if (pc->ops->setfromoptions) { (*pc->ops->setfromoptions)(pc); } ierr = PCJacobiSetUseAbs(pc);CHKERRQ(ierr); break; case NTR_PC_BFGS: ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr); if (pc->ops->setfromoptions) { (*pc->ops->setfromoptions)(pc); } ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr); ierr = PCShellSetContext(pc, tr->M);CHKERRQ(ierr); ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr); break; default: /* Use the pc method set by pc_type */ break; } /* Initialize trust-region radius */ switch(tr->init_type) { case NTR_INIT_CONSTANT: /* Use the initial radius specified */ break; case NTR_INIT_INTERPOLATION: /* Use the initial radius specified */ max_radius = 0.0; for (j = 0; j < j_max; ++j) { fmin = f; sigma = 0.0; if (needH) { ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); needH = 0; } for (i = 0; i < i_max; ++i) { ierr = VecCopy(tao->solution, tr->W);CHKERRQ(ierr); ierr = VecAXPY(tr->W, -tao->trust/gnorm, tao->gradient);CHKERRQ(ierr); ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); if (PetscIsInfOrNanReal(ftrial)) { tau = tr->gamma1_i; } else { if (ftrial < fmin) { fmin = ftrial; sigma = -tao->trust / gnorm; } ierr = MatMult(tao->hessian, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = VecDot(tao->gradient, tao->stepdirection, &prered);CHKERRQ(ierr); prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm)); actred = f - ftrial; if ((PetscAbsScalar(actred) <= tr->epsilon) && (PetscAbsScalar(prered) <= tr->epsilon)) { kappa = 1.0; } else { kappa = actred / prered; } tau_1 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust + (1.0 - tr->theta_i) * prered - actred); tau_2 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust - (1.0 + tr->theta_i) * prered + actred); tau_min = PetscMin(tau_1, tau_2); tau_max = PetscMax(tau_1, tau_2); if (PetscAbsScalar(kappa - 1.0) <= tr->mu1_i) { /* Great agreement */ max_radius = PetscMax(max_radius, tao->trust); if (tau_max < 1.0) { tau = tr->gamma3_i; } else if (tau_max > tr->gamma4_i) { tau = tr->gamma4_i; } else { tau = tau_max; } } else if (PetscAbsScalar(kappa - 1.0) <= tr->mu2_i) { /* Good agreement */ max_radius = PetscMax(max_radius, tao->trust); if (tau_max < tr->gamma2_i) { tau = tr->gamma2_i; } else if (tau_max > tr->gamma3_i) { tau = tr->gamma3_i; } else { tau = tau_max; } } else { /* Not good agreement */ if (tau_min > 1.0) { tau = tr->gamma2_i; } else if (tau_max < tr->gamma1_i) { tau = tr->gamma1_i; } else if ((tau_min < tr->gamma1_i) && (tau_max >= 1.0)) { tau = tr->gamma1_i; } else if ((tau_1 >= tr->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < tr->gamma1_i) || (tau_2 >= 1.0))) { tau = tau_1; } else if ((tau_2 >= tr->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < tr->gamma1_i) || (tau_2 >= 1.0))) { tau = tau_2; } else { tau = tau_max; } } } tao->trust = tau * tao->trust; } if (fmin < f) { f = fmin; ierr = VecAXPY(tao->solution, sigma, tao->gradient);CHKERRQ(ierr); ierr = TaoComputeGradient(tao,tao->solution, tao->gradient);CHKERRQ(ierr); ierr = VecNorm(tao->gradient, NORM_2, &gnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); needH = 1; ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason);CHKERRQ(ierr); if (reason != TAO_CONTINUE_ITERATING) { PetscFunctionReturn(0); } } } tao->trust = PetscMax(tao->trust, max_radius); /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); break; default: /* Norm of the first direction will initialize radius */ tao->trust = 0.0; break; } /* Set initial scaling for the BFGS preconditioner This step is done after computing the initial trust-region radius since the function value may have decreased */ if (NTR_PC_BFGS == tr->pc_type) { if (f != 0.0) { delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); } else { delta = 2.0 / (gnorm*gnorm); } ierr = MatLMVMSetDelta(tr->M,delta);CHKERRQ(ierr); } /* Have not converged; continue with Newton method */ while (reason == TAO_CONTINUE_ITERATING) { ++iter; tao->ksp_its=0; /* Compute the Hessian */ if (needH) { ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); needH = 0; } if (NTR_PC_BFGS == tr->pc_type) { if (BFGS_SCALE_AHESS == tr->bfgs_scale_type) { /* Obtain diagonal for the bfgs preconditioner */ ierr = MatGetDiagonal(tao->hessian, tr->Diag);CHKERRQ(ierr); ierr = VecAbs(tr->Diag);CHKERRQ(ierr); ierr = VecReciprocal(tr->Diag);CHKERRQ(ierr); ierr = MatLMVMSetScale(tr->M,tr->Diag);CHKERRQ(ierr); } /* Update the limited memory preconditioner */ ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient);CHKERRQ(ierr); ++bfgsUpdates; } while (reason == TAO_CONTINUE_ITERATING) { ierr = KSPSetOperators(tao->ksp, tao->hessian, tao->hessian_pre);CHKERRQ(ierr); /* Solve the trust region subproblem */ if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPNASHGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPSTCGGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else { /* NTR_KSP_GLTR */ ierr = KSPGLTRSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPGLTRGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } if (0.0 == tao->trust) { /* Radius was uninitialized; use the norm of the direction */ if (norm_d > 0.0) { tao->trust = norm_d; /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); } else { /* The direction was bad; set radius to default value and re-solve the trust-region subproblem to get a direction */ tao->trust = tao->trust0; /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPNASHGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPSTCGGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else { /* NTR_KSP_GLTR */ ierr = KSPGLTRSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPGLTRGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } if (norm_d == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); } } ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); ierr = KSPGetConvergedReason(tao->ksp, &ksp_reason);CHKERRQ(ierr); if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) && (NTR_PC_BFGS == tr->pc_type) && (bfgsUpdates > 1)) { /* Preconditioner is numerically indefinite; reset the approximate if using BFGS preconditioning. */ if (f != 0.0) { delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); } else { delta = 2.0 / (gnorm*gnorm); } ierr = MatLMVMSetDelta(tr->M, delta);CHKERRQ(ierr); ierr = MatLMVMReset(tr->M);CHKERRQ(ierr); ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient);CHKERRQ(ierr); bfgsUpdates = 1; } if (NTR_UPDATE_REDUCTION == tr->update_type) { /* Get predicted reduction */ if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else { /* gltr */ ierr = KSPGLTRGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } if (prered >= 0.0) { /* The predicted reduction has the wrong sign. This cannot happen in infinite precision arithmetic. Step should be rejected! */ tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); } else { /* Compute trial step and function value */ ierr = VecCopy(tao->solution,tr->W);CHKERRQ(ierr); ierr = VecAXPY(tr->W, 1.0, tao->stepdirection);CHKERRQ(ierr); ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); if (PetscIsInfOrNanReal(ftrial)) { tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); } else { /* Compute and actual reduction */ actred = f - ftrial; prered = -prered; if ((PetscAbsScalar(actred) <= tr->epsilon) && (PetscAbsScalar(prered) <= tr->epsilon)) { kappa = 1.0; } else { kappa = actred / prered; } /* Accept or reject the step and update radius */ if (kappa < tr->eta1) { /* Reject the step */ tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); } else { /* Accept the step */ if (kappa < tr->eta2) { /* Marginal bad step */ tao->trust = tr->alpha2 * PetscMin(tao->trust, norm_d); } else if (kappa < tr->eta3) { /* Reasonable step */ tao->trust = tr->alpha3 * tao->trust; } else if (kappa < tr->eta4) { /* Good step */ tao->trust = PetscMax(tr->alpha4 * norm_d, tao->trust); } else { /* Very good step */ tao->trust = PetscMax(tr->alpha5 * norm_d, tao->trust); } break; } } } } else { /* Get predicted reduction */ if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else { /* gltr */ ierr = KSPGLTRGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } if (prered >= 0.0) { /* The predicted reduction has the wrong sign. This cannot happen in infinite precision arithmetic. Step should be rejected! */ tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else { ierr = VecCopy(tao->solution, tr->W);CHKERRQ(ierr); ierr = VecAXPY(tr->W, 1.0, tao->stepdirection);CHKERRQ(ierr); ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); if (PetscIsInfOrNanReal(ftrial)) { tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else { ierr = VecDot(tao->gradient, tao->stepdirection, &beta);CHKERRQ(ierr); actred = f - ftrial; prered = -prered; if ((PetscAbsScalar(actred) <= tr->epsilon) && (PetscAbsScalar(prered) <= tr->epsilon)) { kappa = 1.0; } else { kappa = actred / prered; } tau_1 = tr->theta * beta / (tr->theta * beta - (1.0 - tr->theta) * prered + actred); tau_2 = tr->theta * beta / (tr->theta * beta + (1.0 + tr->theta) * prered - actred); tau_min = PetscMin(tau_1, tau_2); tau_max = PetscMax(tau_1, tau_2); if (kappa >= 1.0 - tr->mu1) { /* Great agreement; accept step and update radius */ if (tau_max < 1.0) { tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); } else if (tau_max > tr->gamma4) { tao->trust = PetscMax(tao->trust, tr->gamma4 * norm_d); } else { tao->trust = PetscMax(tao->trust, tau_max * norm_d); } break; } else if (kappa >= 1.0 - tr->mu2) { /* Good agreement */ if (tau_max < tr->gamma2) { tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); } else if (tau_max > tr->gamma3) { tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); } else if (tau_max < 1.0) { tao->trust = tau_max * PetscMin(tao->trust, norm_d); } else { tao->trust = PetscMax(tao->trust, tau_max * norm_d); } break; } else { /* Not good agreement */ if (tau_min > 1.0) { tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); } else if (tau_max < tr->gamma1) { tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else if ((tau_min < tr->gamma1) && (tau_max >= 1.0)) { tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else if ((tau_1 >= tr->gamma1) && (tau_1 < 1.0) && ((tau_2 < tr->gamma1) || (tau_2 >= 1.0))) { tao->trust = tau_1 * PetscMin(tao->trust, norm_d); } else if ((tau_2 >= tr->gamma1) && (tau_2 < 1.0) && ((tau_1 < tr->gamma1) || (tau_2 >= 1.0))) { tao->trust = tau_2 * PetscMin(tao->trust, norm_d); } else { tao->trust = tau_max * PetscMin(tao->trust, norm_d); } } } } } /* The step computed was not good and the radius was decreased. Monitor the radius to terminate. */ ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, tao->trust, &reason);CHKERRQ(ierr); } /* The radius may have been increased; modify if it is too large */ tao->trust = PetscMin(tao->trust, tr->max_radius); if (reason == TAO_CONTINUE_ITERATING) { ierr = VecCopy(tr->W, tao->solution);CHKERRQ(ierr); f = ftrial; ierr = TaoComputeGradient(tao, tao->solution, tao->gradient); ierr = VecNorm(tao->gradient, NORM_2, &gnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); needH = 1; ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, tao->trust, &reason);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
static PetscErrorCode QPIPSetInitialPoint(TAO_BQPIP *qp, Tao tao) { PetscErrorCode ierr; PetscReal two=2.0,p01=1; PetscReal gap1,gap2,fff,mu; PetscFunctionBegin; /* Compute function, Gradient R=Hx+b, and Hessian */ ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); ierr = VecMedian(qp->XL, tao->solution, qp->XU, tao->solution);CHKERRQ(ierr); ierr = MatMult(tao->hessian, tao->solution, tao->gradient);CHKERRQ(ierr); ierr = VecCopy(qp->C0, qp->Work);CHKERRQ(ierr); ierr = VecAXPY(qp->Work, 0.5, tao->gradient);CHKERRQ(ierr); ierr = VecAXPY(tao->gradient, 1.0, qp->C0);CHKERRQ(ierr); ierr = VecDot(tao->solution, qp->Work, &fff);CHKERRQ(ierr); qp->pobj = fff + qp->c; /* Initialize Primal Vectors */ /* T = XU - X; G = X - XL */ ierr = VecCopy(qp->XU, qp->T);CHKERRQ(ierr); ierr = VecAXPY(qp->T, -1.0, tao->solution);CHKERRQ(ierr); ierr = VecCopy(tao->solution, qp->G);CHKERRQ(ierr); ierr = VecAXPY(qp->G, -1.0, qp->XL);CHKERRQ(ierr); ierr = VecSet(qp->GZwork, p01);CHKERRQ(ierr); ierr = VecSet(qp->TSwork, p01);CHKERRQ(ierr); ierr = VecPointwiseMax(qp->G, qp->G, qp->GZwork);CHKERRQ(ierr); ierr = VecPointwiseMax(qp->T, qp->T, qp->TSwork);CHKERRQ(ierr); /* Initialize Dual Variable Vectors */ ierr = VecCopy(qp->G, qp->Z);CHKERRQ(ierr); ierr = VecReciprocal(qp->Z);CHKERRQ(ierr); ierr = VecCopy(qp->T, qp->S);CHKERRQ(ierr); ierr = VecReciprocal(qp->S);CHKERRQ(ierr); ierr = MatMult(tao->hessian, qp->Work, qp->RHS);CHKERRQ(ierr); ierr = VecAbs(qp->RHS);CHKERRQ(ierr); ierr = VecSet(qp->Work, p01);CHKERRQ(ierr); ierr = VecPointwiseMax(qp->RHS, qp->RHS, qp->Work);CHKERRQ(ierr); ierr = VecPointwiseDivide(qp->RHS, tao->gradient, qp->RHS);CHKERRQ(ierr); ierr = VecNorm(qp->RHS, NORM_1, &gap1);CHKERRQ(ierr); mu = PetscMin(10.0,(gap1+10.0)/qp->m); ierr = VecScale(qp->S, mu);CHKERRQ(ierr); ierr = VecScale(qp->Z, mu);CHKERRQ(ierr); ierr = VecSet(qp->TSwork, p01);CHKERRQ(ierr); ierr = VecSet(qp->GZwork, p01);CHKERRQ(ierr); ierr = VecPointwiseMax(qp->S, qp->S, qp->TSwork);CHKERRQ(ierr); ierr = VecPointwiseMax(qp->Z, qp->Z, qp->GZwork);CHKERRQ(ierr); qp->mu=0;qp->dinfeas=1.0;qp->pinfeas=1.0; while ( (qp->dinfeas+qp->pinfeas)/(qp->m+qp->n) >= qp->mu ){ ierr = VecScale(qp->G, two);CHKERRQ(ierr); ierr = VecScale(qp->Z, two);CHKERRQ(ierr); ierr = VecScale(qp->S, two);CHKERRQ(ierr); ierr = VecScale(qp->T, two);CHKERRQ(ierr); ierr = QPIPComputeResidual(qp,tao);CHKERRQ(ierr); ierr = VecCopy(tao->solution, qp->R3);CHKERRQ(ierr); ierr = VecAXPY(qp->R3, -1.0, qp->G);CHKERRQ(ierr); ierr = VecAXPY(qp->R3, -1.0, qp->XL);CHKERRQ(ierr); ierr = VecCopy(tao->solution, qp->R5);CHKERRQ(ierr); ierr = VecAXPY(qp->R5, 1.0, qp->T);CHKERRQ(ierr); ierr = VecAXPY(qp->R5, -1.0, qp->XU);CHKERRQ(ierr); ierr = VecNorm(qp->R3, NORM_INFINITY, &gap1);CHKERRQ(ierr); ierr = VecNorm(qp->R5, NORM_INFINITY, &gap2);CHKERRQ(ierr); qp->pinfeas=PetscMax(gap1,gap2); /* Compute the duality gap */ ierr = VecDot(qp->G, qp->Z, &gap1);CHKERRQ(ierr); ierr = VecDot(qp->T, qp->S, &gap2);CHKERRQ(ierr); qp->gap = (gap1+gap2); qp->dobj = qp->pobj - qp->gap; if (qp->m>0) qp->mu=qp->gap/(qp->m); else qp->mu=0.0; qp->rgap=qp->gap/( PetscAbsReal(qp->dobj) + PetscAbsReal(qp->pobj) + 1.0 ); } PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat A,RHS,C,F,X,S; Vec u,x,b; Vec xschur,bschur,uschur; IS is_schur; PetscErrorCode ierr; PetscMPIInt size; PetscInt isolver=0,size_schur,m,n,nfact,nsolve,nrhs; PetscReal norm,tol=PETSC_SQRT_MACHINE_EPSILON; PetscRandom rand; PetscBool data_provided,herm,symm,use_lu; PetscReal sratio = 5.1/12.; PetscViewer fd; /* viewer */ char solver[256]; char file[PETSC_MAX_PATH_LEN]; /* input file name */ PetscInitialize(&argc,&args,(char*)0,help); ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size);CHKERRQ(ierr); if (size > 1) SETERRQ(PETSC_COMM_WORLD,1,"This is a uniprocessor test"); /* Determine which type of solver we want to test for */ herm = PETSC_FALSE; symm = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-symmetric_solve",&symm,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL,"-hermitian_solve",&herm,NULL);CHKERRQ(ierr); if (herm) symm = PETSC_TRUE; /* Determine file from which we read the matrix A */ ierr = PetscOptionsGetString(NULL,NULL,"-f",file,PETSC_MAX_PATH_LEN,&data_provided);CHKERRQ(ierr); if (!data_provided) { /* get matrices from PETSc distribution */ sprintf(file,PETSC_DIR); ierr = PetscStrcat(file,"/share/petsc/datafiles/matrices/");CHKERRQ(ierr); if (symm) { #if defined (PETSC_USE_COMPLEX) ierr = PetscStrcat(file,"hpd-complex-");CHKERRQ(ierr); #else ierr = PetscStrcat(file,"spd-real-");CHKERRQ(ierr); #endif } else { #if defined (PETSC_USE_COMPLEX) ierr = PetscStrcat(file,"nh-complex-");CHKERRQ(ierr); #else ierr = PetscStrcat(file,"ns-real-");CHKERRQ(ierr); #endif } #if defined(PETSC_USE_64BIT_INDICES) ierr = PetscStrcat(file,"int64-");CHKERRQ(ierr); #else ierr = PetscStrcat(file,"int32-");CHKERRQ(ierr); #endif #if defined (PETSC_USE_REAL_SINGLE) ierr = PetscStrcat(file,"float32");CHKERRQ(ierr); #else ierr = PetscStrcat(file,"float64");CHKERRQ(ierr); #endif } /* Load matrix A */ ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file,FILE_MODE_READ,&fd);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatLoad(A,fd);CHKERRQ(ierr); ierr = PetscViewerDestroy(&fd);CHKERRQ(ierr); ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr); if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ, "This example is not intended for rectangular matrices (%d, %d)", m, n); /* Create dense matrix C and X; C holds true solution with identical colums */ nrhs = 2; ierr = PetscOptionsGetInt(NULL,NULL,"-nrhs",&nrhs,NULL);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&C);CHKERRQ(ierr); ierr = MatSetSizes(C,m,PETSC_DECIDE,PETSC_DECIDE,nrhs);CHKERRQ(ierr); ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr); ierr = MatSetFromOptions(C);CHKERRQ(ierr); ierr = MatSetUp(C);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rand);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rand);CHKERRQ(ierr); ierr = MatSetRandom(C,rand);CHKERRQ(ierr); ierr = MatDuplicate(C,MAT_DO_NOT_COPY_VALUES,&X);CHKERRQ(ierr); /* Create vectors */ ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr); ierr = VecSetSizes(x,n,PETSC_DECIDE);CHKERRQ(ierr); ierr = VecSetFromOptions(x);CHKERRQ(ierr); ierr = VecDuplicate(x,&b);CHKERRQ(ierr); ierr = VecDuplicate(x,&u);CHKERRQ(ierr); /* save the true solution */ ierr = PetscOptionsGetInt(NULL,NULL,"-solver",&isolver,NULL);CHKERRQ(ierr); switch (isolver) { #if defined(PETSC_HAVE_MUMPS) case 0: ierr = PetscStrcpy(solver,MATSOLVERMUMPS);CHKERRQ(ierr); break; #endif #if defined(PETSC_HAVE_MKL_PARDISO) case 1: ierr = PetscStrcpy(solver,MATSOLVERMKL_PARDISO);CHKERRQ(ierr); break; #endif default: ierr = PetscStrcpy(solver,MATSOLVERPETSC);CHKERRQ(ierr); break; } #if defined (PETSC_USE_COMPLEX) if (isolver == 0 && symm && !data_provided) { /* MUMPS (5.0.0) does not have support for hermitian matrices, so make them symmetric */ PetscScalar im = PetscSqrtScalar((PetscScalar)-1.); PetscScalar val = -1.0; val = val + im; ierr = MatSetValue(A,1,0,val,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } #endif ierr = PetscOptionsGetReal(NULL,NULL,"-schur_ratio",&sratio,NULL);CHKERRQ(ierr); if (sratio < 0. || sratio > 1.) { SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ, "Invalid ratio for schur degrees of freedom %f", sratio); } size_schur = (PetscInt)(sratio*m); ierr = PetscPrintf(PETSC_COMM_SELF,"Solving with %s: nrhs %d, sym %d, herm %d, size schur %d, size mat %d\n",solver,nrhs,symm,herm,size_schur,m);CHKERRQ(ierr); /* Test LU/Cholesky Factorization */ use_lu = PETSC_FALSE; if (!symm) use_lu = PETSC_TRUE; #if defined (PETSC_USE_COMPLEX) if (isolver == 1) use_lu = PETSC_TRUE; #endif if (herm && !use_lu) { /* test also conversion routines inside the solver packages */ ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = MatConvert(A,MATSEQSBAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr); } if (use_lu) { ierr = MatGetFactor(A,solver,MAT_FACTOR_LU,&F);CHKERRQ(ierr); } else { if (herm) { ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr); } else { ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_SPD,PETSC_FALSE);CHKERRQ(ierr); } ierr = MatGetFactor(A,solver,MAT_FACTOR_CHOLESKY,&F);CHKERRQ(ierr); } ierr = ISCreateStride(PETSC_COMM_SELF,size_schur,m-size_schur,1,&is_schur);CHKERRQ(ierr); ierr = MatFactorSetSchurIS(F,is_schur);CHKERRQ(ierr); ierr = ISDestroy(&is_schur);CHKERRQ(ierr); if (use_lu) { ierr = MatLUFactorSymbolic(F,A,NULL,NULL,NULL);CHKERRQ(ierr); } else { ierr = MatCholeskyFactorSymbolic(F,A,NULL,NULL);CHKERRQ(ierr); } for (nfact = 0; nfact < 3; nfact++) { Mat AD; if (!nfact) { ierr = VecSetRandom(x,rand);CHKERRQ(ierr); if (symm && herm) { ierr = VecAbs(x);CHKERRQ(ierr); } ierr = MatDiagonalSet(A,x,ADD_VALUES);CHKERRQ(ierr); } if (use_lu) { ierr = MatLUFactorNumeric(F,A,NULL);CHKERRQ(ierr); } else { ierr = MatCholeskyFactorNumeric(F,A,NULL);CHKERRQ(ierr); } ierr = MatFactorCreateSchurComplement(F,&S);CHKERRQ(ierr); ierr = MatCreateVecs(S,&xschur,&bschur);CHKERRQ(ierr); ierr = VecDuplicate(xschur,&uschur);CHKERRQ(ierr); if (nfact == 1) { ierr = MatFactorInvertSchurComplement(F);CHKERRQ(ierr); } for (nsolve = 0; nsolve < 2; nsolve++) { ierr = VecSetRandom(x,rand);CHKERRQ(ierr); ierr = VecCopy(x,u);CHKERRQ(ierr); if (nsolve) { ierr = MatMult(A,x,b);CHKERRQ(ierr); ierr = MatSolve(F,b,x);CHKERRQ(ierr); } else { ierr = MatMultTranspose(A,x,b);CHKERRQ(ierr); ierr = MatSolveTranspose(F,b,x);CHKERRQ(ierr); } /* Check the error */ ierr = VecAXPY(u,-1.0,x);CHKERRQ(ierr); /* u <- (-1.0)x + u */ ierr = VecNorm(u,NORM_2,&norm);CHKERRQ(ierr); if (norm > tol) { PetscReal resi; if (nsolve) { ierr = MatMult(A,x,u);CHKERRQ(ierr); /* u = A*x */ } else { ierr = MatMultTranspose(A,x,u);CHKERRQ(ierr); /* u = A*x */ } ierr = VecAXPY(u,-1.0,b);CHKERRQ(ierr); /* u <- (-1.0)b + u */ ierr = VecNorm(u,NORM_2,&resi);CHKERRQ(ierr); if (nsolve) { ierr = PetscPrintf(PETSC_COMM_SELF,"(f %d, s %d) MatSolve error: Norm of error %g, residual %f\n",nfact,nsolve,norm,resi);CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_SELF,"(f %d, s %d) MatSolveTranspose error: Norm of error %g, residual %f\n",nfact,nsolve,norm,resi);CHKERRQ(ierr); } } ierr = VecSetRandom(xschur,rand);CHKERRQ(ierr); ierr = VecCopy(xschur,uschur);CHKERRQ(ierr); if (nsolve) { ierr = MatMult(S,xschur,bschur);CHKERRQ(ierr); ierr = MatFactorSolveSchurComplement(F,bschur,xschur);CHKERRQ(ierr); } else { ierr = MatMultTranspose(S,xschur,bschur);CHKERRQ(ierr); ierr = MatFactorSolveSchurComplementTranspose(F,bschur,xschur);CHKERRQ(ierr); } /* Check the error */ ierr = VecAXPY(uschur,-1.0,xschur);CHKERRQ(ierr); /* u <- (-1.0)x + u */ ierr = VecNorm(uschur,NORM_2,&norm);CHKERRQ(ierr); if (norm > tol) { PetscReal resi; if (nsolve) { ierr = MatMult(S,xschur,uschur);CHKERRQ(ierr); /* u = A*x */ } else { ierr = MatMultTranspose(S,xschur,uschur);CHKERRQ(ierr); /* u = A*x */ } ierr = VecAXPY(uschur,-1.0,bschur);CHKERRQ(ierr); /* u <- (-1.0)b + u */ ierr = VecNorm(uschur,NORM_2,&resi);CHKERRQ(ierr); if (nsolve) { ierr = PetscPrintf(PETSC_COMM_SELF,"(f %d, s %d) MatFactorSolveSchurComplement error: Norm of error %g, residual %f\n",nfact,nsolve,norm,resi);CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_SELF,"(f %d, s %d) MatFactorSolveSchurComplementTranspose error: Norm of error %g, residual %f\n",nfact,nsolve,norm,resi);CHKERRQ(ierr); } } } ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&AD); if (!nfact) { ierr = MatMatMult(AD,C,MAT_INITIAL_MATRIX,2.0,&RHS);CHKERRQ(ierr); } else { ierr = MatMatMult(AD,C,MAT_REUSE_MATRIX,2.0,&RHS);CHKERRQ(ierr); } ierr = MatDestroy(&AD);CHKERRQ(ierr); for (nsolve = 0; nsolve < 2; nsolve++) { ierr = MatMatSolve(F,RHS,X);CHKERRQ(ierr); /* Check the error */ ierr = MatAXPY(X,-1.0,C,SAME_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(X,NORM_FROBENIUS,&norm);CHKERRQ(ierr); if (norm > tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"(f %D, s %D) MatMatSolve: Norm of error %g\n",nfact,nsolve,norm);CHKERRQ(ierr); } } ierr = MatDestroy(&S);CHKERRQ(ierr); ierr = VecDestroy(&xschur);CHKERRQ(ierr); ierr = VecDestroy(&bschur);CHKERRQ(ierr); ierr = VecDestroy(&uschur);CHKERRQ(ierr); } /* Free data structures */ ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = MatDestroy(&F);CHKERRQ(ierr); ierr = MatDestroy(&X);CHKERRQ(ierr); ierr = MatDestroy(&RHS);CHKERRQ(ierr); ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
extern PetscErrorCode MatLMVMUpdate(Mat M, Vec x, Vec g) { MatLMVMCtx *ctx; PetscReal rhotemp, rhotol; PetscReal y0temp, s0temp; PetscReal yDy, yDs, sDs; PetscReal sigmanew, denom; PetscErrorCode ierr; PetscInt i; PetscBool same; PetscReal yy_sum=0.0, ys_sum=0.0, ss_sum=0.0; PetscFunctionBegin; PetscValidHeaderSpecific(x,VEC_CLASSID,2); PetscValidHeaderSpecific(g,VEC_CLASSID,3); ierr = PetscObjectTypeCompare((PetscObject)M,MATSHELL,&same);CHKERRQ(ierr); if (!same) SETERRQ(PETSC_COMM_SELF,1,"Matrix M is not type MatLMVM"); ierr = MatShellGetContext(M,(void**)&ctx);CHKERRQ(ierr); if (!ctx->allocated) { ierr = MatLMVMAllocateVectors(M, x); CHKERRQ(ierr); } if (0 == ctx->iter) { ierr = MatLMVMReset(M);CHKERRQ(ierr); } else { ierr = VecAYPX(ctx->Gprev,-1.0,g);CHKERRQ(ierr); ierr = VecAYPX(ctx->Xprev,-1.0,x);CHKERRQ(ierr); ierr = VecDot(ctx->Gprev,ctx->Xprev,&rhotemp);CHKERRQ(ierr); ierr = VecDot(ctx->Gprev,ctx->Gprev,&y0temp);CHKERRQ(ierr); rhotol = ctx->eps * y0temp; if (rhotemp > rhotol) { ++ctx->nupdates; ctx->lmnow = PetscMin(ctx->lmnow+1, ctx->lm); ierr=PetscObjectDereference((PetscObject)ctx->S[ctx->lm]);CHKERRQ(ierr); ierr=PetscObjectDereference((PetscObject)ctx->Y[ctx->lm]);CHKERRQ(ierr); for (i = ctx->lm-1; i >= 0; --i) { ctx->S[i+1] = ctx->S[i]; ctx->Y[i+1] = ctx->Y[i]; ctx->rho[i+1] = ctx->rho[i]; } ctx->S[0] = ctx->Xprev; ctx->Y[0] = ctx->Gprev; PetscObjectReference((PetscObject)ctx->S[0]); PetscObjectReference((PetscObject)ctx->Y[0]); ctx->rho[0] = 1.0 / rhotemp; /* Compute the scaling */ switch(ctx->scaleType) { case MatLMVM_Scale_None: break; case MatLMVM_Scale_Scalar: /* Compute s^T s */ ierr = VecDot(ctx->Xprev,ctx->Xprev,&s0temp);CHKERRQ(ierr); /* Scalar is positive; safeguards are not required. */ /* Save information for scalar scaling */ ctx->yy_history[(ctx->nupdates - 1) % ctx->scalar_history] = y0temp; ctx->ys_history[(ctx->nupdates - 1) % ctx->scalar_history] = rhotemp; ctx->ss_history[(ctx->nupdates - 1) % ctx->scalar_history] = s0temp; /* Compute summations for scalar scaling */ yy_sum = 0; /* No safeguard required; y^T y > 0 */ ys_sum = 0; /* No safeguard required; y^T s > 0 */ ss_sum = 0; /* No safeguard required; s^T s > 0 */ for (i = 0; i < PetscMin(ctx->nupdates, ctx->scalar_history); ++i) { yy_sum += ctx->yy_history[i]; ys_sum += ctx->ys_history[i]; ss_sum += ctx->ss_history[i]; } if (0.0 == ctx->s_alpha) { /* Safeguard ys_sum */ if (0.0 == ys_sum) { ys_sum = TAO_ZERO_SAFEGUARD; } sigmanew = ss_sum / ys_sum; } else if (1.0 == ctx->s_alpha) { /* Safeguard yy_sum */ if (0.0 == yy_sum) { yy_sum = TAO_ZERO_SAFEGUARD; } sigmanew = ys_sum / yy_sum; } else { denom = 2*ctx->s_alpha*yy_sum; /* Safeguard denom */ if (0.0 == denom) { denom = TAO_ZERO_SAFEGUARD; } sigmanew = ((2*ctx->s_alpha-1)*ys_sum + PetscSqrtScalar((2*ctx->s_alpha-1)*(2*ctx->s_alpha-1)*ys_sum*ys_sum - 4*(ctx->s_alpha)*(ctx->s_alpha-1)*yy_sum*ss_sum)) / denom; } switch(ctx->limitType) { case MatLMVM_Limit_Average: if (1.0 == ctx->mu) { ctx->sigma = sigmanew; } else if (ctx->mu) { ctx->sigma = ctx->mu * sigmanew + (1.0 - ctx->mu) * ctx->sigma; } break; case MatLMVM_Limit_Relative: if (ctx->mu) { ctx->sigma = TaoMid((1.0 - ctx->mu) * ctx->sigma, sigmanew, (1.0 + ctx->mu) * ctx->sigma); } break; case MatLMVM_Limit_Absolute: if (ctx->nu) { ctx->sigma = TaoMid(ctx->sigma - ctx->nu, sigmanew, ctx->sigma + ctx->nu); } break; default: ctx->sigma = sigmanew; break; } break; case MatLMVM_Scale_Broyden: /* Original version */ /* Combine DFP and BFGS */ /* This code appears to be numerically unstable. We use the */ /* original version because this was used to generate all of */ /* the data and because it may be the least unstable of the */ /* bunch. */ /* P = Q = inv(D); */ ierr = VecCopy(ctx->D,ctx->P);CHKERRQ(ierr); ierr = VecReciprocal(ctx->P);CHKERRQ(ierr); ierr = VecCopy(ctx->P,ctx->Q);CHKERRQ(ierr); /* V = y*y */ ierr = VecPointwiseMult(ctx->V,ctx->Gprev,ctx->Gprev);CHKERRQ(ierr); /* W = inv(D)*s */ ierr = VecPointwiseMult(ctx->W,ctx->Xprev,ctx->P);CHKERRQ(ierr); ierr = VecDot(ctx->W,ctx->Xprev,&sDs);CHKERRQ(ierr); /* Safeguard rhotemp and sDs */ if (0.0 == rhotemp) { rhotemp = TAO_ZERO_SAFEGUARD; } if (0.0 == sDs) { sDs = TAO_ZERO_SAFEGUARD; } if (1.0 != ctx->phi) { /* BFGS portion of the update */ /* U = (inv(D)*s)*(inv(D)*s) */ ierr = VecPointwiseMult(ctx->U,ctx->W,ctx->W);CHKERRQ(ierr); /* Assemble */ ierr = VecAXPY(ctx->P,1.0/rhotemp,ctx->V);CHKERRQ(ierr); ierr = VecAXPY(ctx->P,-1.0/sDs,ctx->U);CHKERRQ(ierr); } if (0.0 != ctx->phi) { /* DFP portion of the update */ /* U = inv(D)*s*y */ ierr = VecPointwiseMult(ctx->U, ctx->W, ctx->Gprev);CHKERRQ(ierr); /* Assemble */ ierr = VecAXPY(ctx->Q,1.0/rhotemp + sDs/(rhotemp*rhotemp), ctx->V);CHKERRQ(ierr); ierr = VecAXPY(ctx->Q,-2.0/rhotemp,ctx->U);CHKERRQ(ierr); } if (0.0 == ctx->phi) { ierr = VecCopy(ctx->P,ctx->U);CHKERRQ(ierr); } else if (1.0 == ctx->phi) { ierr = VecCopy(ctx->Q,ctx->U);CHKERRQ(ierr); } else { /* Broyden update U=(1-phi)*P + phi*Q */ ierr = VecCopy(ctx->Q,ctx->U);CHKERRQ(ierr); ierr = VecAXPBY(ctx->U,1.0-ctx->phi, ctx->phi, ctx->P);CHKERRQ(ierr); } /* Obtain inverse and ensure positive definite */ ierr = VecReciprocal(ctx->U);CHKERRQ(ierr); ierr = VecAbs(ctx->U);CHKERRQ(ierr); switch(ctx->rScaleType) { case MatLMVM_Rescale_None: break; case MatLMVM_Rescale_Scalar: case MatLMVM_Rescale_GL: if (ctx->rScaleType == MatLMVM_Rescale_GL) { /* Gilbert and Lemarachal use the old diagonal */ ierr = VecCopy(ctx->D,ctx->P);CHKERRQ(ierr); } else { /* The default version uses the current diagonal */ ierr = VecCopy(ctx->U,ctx->P);CHKERRQ(ierr); } /* Compute s^T s */ ierr = VecDot(ctx->Xprev,ctx->Xprev,&s0temp);CHKERRQ(ierr); /* Save information for special cases of scalar rescaling */ ctx->yy_rhistory[(ctx->nupdates - 1) % ctx->rescale_history] = y0temp; ctx->ys_rhistory[(ctx->nupdates - 1) % ctx->rescale_history] = rhotemp; ctx->ss_rhistory[(ctx->nupdates - 1) % ctx->rescale_history] = s0temp; if (0.5 == ctx->r_beta) { if (1 == PetscMin(ctx->nupdates, ctx->rescale_history)) { ierr = VecPointwiseMult(ctx->V,ctx->Y[0],ctx->P);CHKERRQ(ierr); ierr = VecDot(ctx->V,ctx->Y[0],&yy_sum);CHKERRQ(ierr); ierr = VecPointwiseDivide(ctx->W,ctx->S[0],ctx->P);CHKERRQ(ierr); ierr = VecDot(ctx->W,ctx->S[0],&ss_sum);CHKERRQ(ierr); ys_sum = ctx->ys_rhistory[0]; } else { ierr = VecCopy(ctx->P,ctx->Q);CHKERRQ(ierr); ierr = VecReciprocal(ctx->Q);CHKERRQ(ierr); /* Compute summations for scalar scaling */ yy_sum = 0; /* No safeguard required */ ys_sum = 0; /* No safeguard required */ ss_sum = 0; /* No safeguard required */ for (i = 0; i < PetscMin(ctx->nupdates, ctx->rescale_history); ++i) { ierr = VecPointwiseMult(ctx->V,ctx->Y[i],ctx->P);CHKERRQ(ierr); ierr = VecDot(ctx->V,ctx->Y[i],&yDy);CHKERRQ(ierr); yy_sum += yDy; ierr = VecPointwiseMult(ctx->W,ctx->S[i],ctx->Q);CHKERRQ(ierr); ierr = VecDot(ctx->W,ctx->S[i],&sDs);CHKERRQ(ierr); ss_sum += sDs; ys_sum += ctx->ys_rhistory[i]; } } } else if (0.0 == ctx->r_beta) { if (1 == PetscMin(ctx->nupdates, ctx->rescale_history)) { /* Compute summations for scalar scaling */ ierr = VecPointwiseDivide(ctx->W,ctx->S[0],ctx->P);CHKERRQ(ierr); ierr = VecDot(ctx->W, ctx->Y[0], &ys_sum);CHKERRQ(ierr); ierr = VecDot(ctx->W, ctx->W, &ss_sum);CHKERRQ(ierr); yy_sum += ctx->yy_rhistory[0]; } else { ierr = VecCopy(ctx->Q, ctx->P);CHKERRQ(ierr); ierr = VecReciprocal(ctx->Q);CHKERRQ(ierr); /* Compute summations for scalar scaling */ yy_sum = 0; /* No safeguard required */ ys_sum = 0; /* No safeguard required */ ss_sum = 0; /* No safeguard required */ for (i = 0; i < PetscMin(ctx->nupdates, ctx->rescale_history); ++i) { ierr = VecPointwiseMult(ctx->W, ctx->S[i], ctx->Q);CHKERRQ(ierr); ierr = VecDot(ctx->W, ctx->Y[i], &yDs);CHKERRQ(ierr); ys_sum += yDs; ierr = VecDot(ctx->W, ctx->W, &sDs);CHKERRQ(ierr); ss_sum += sDs; yy_sum += ctx->yy_rhistory[i]; } } } else if (1.0 == ctx->r_beta) { /* Compute summations for scalar scaling */ yy_sum = 0; /* No safeguard required */ ys_sum = 0; /* No safeguard required */ ss_sum = 0; /* No safeguard required */ for (i = 0; i < PetscMin(ctx->nupdates, ctx->rescale_history); ++i) { ierr = VecPointwiseMult(ctx->V, ctx->Y[i], ctx->P);CHKERRQ(ierr); ierr = VecDot(ctx->V, ctx->S[i], &yDs);CHKERRQ(ierr); ys_sum += yDs; ierr = VecDot(ctx->V, ctx->V, &yDy);CHKERRQ(ierr); yy_sum += yDy; ss_sum += ctx->ss_rhistory[i]; } } else { ierr = VecCopy(ctx->Q, ctx->P);CHKERRQ(ierr); ierr = VecPow(ctx->P, ctx->r_beta);CHKERRQ(ierr); ierr = VecPointwiseDivide(ctx->Q, ctx->P, ctx->Q);CHKERRQ(ierr); /* Compute summations for scalar scaling */ yy_sum = 0; /* No safeguard required */ ys_sum = 0; /* No safeguard required */ ss_sum = 0; /* No safeguard required */ for (i = 0; i < PetscMin(ctx->nupdates, ctx->rescale_history); ++i) { ierr = VecPointwiseMult(ctx->V, ctx->P, ctx->Y[i]);CHKERRQ(ierr); ierr = VecPointwiseMult(ctx->W, ctx->Q, ctx->S[i]);CHKERRQ(ierr); ierr = VecDot(ctx->V, ctx->V, &yDy);CHKERRQ(ierr); ierr = VecDot(ctx->V, ctx->W, &yDs);CHKERRQ(ierr); ierr = VecDot(ctx->W, ctx->W, &sDs);CHKERRQ(ierr); yy_sum += yDy; ys_sum += yDs; ss_sum += sDs; } } if (0.0 == ctx->r_alpha) { /* Safeguard ys_sum */ if (0.0 == ys_sum) { ys_sum = TAO_ZERO_SAFEGUARD; } sigmanew = ss_sum / ys_sum; } else if (1.0 == ctx->r_alpha) { /* Safeguard yy_sum */ if (0.0 == yy_sum) { ys_sum = TAO_ZERO_SAFEGUARD; } sigmanew = ys_sum / yy_sum; } else { denom = 2*ctx->r_alpha*yy_sum; /* Safeguard denom */ if (0.0 == denom) { denom = TAO_ZERO_SAFEGUARD; } sigmanew = ((2*ctx->r_alpha-1)*ys_sum + PetscSqrtScalar((2*ctx->r_alpha-1)*(2*ctx->r_alpha-1)*ys_sum*ys_sum - 4*ctx->r_alpha*(ctx->r_alpha-1)*yy_sum*ss_sum)) / denom; } /* If Q has small values, then Q^(r_beta - 1) */ /* can have very large values. Hence, ys_sum */ /* and ss_sum can be infinity. In this case, */ /* sigmanew can either be not-a-number or infinity. */ if (PetscIsInfOrNanReal(sigmanew)) { /* sigmanew is not-a-number; skip rescaling */ } else if (!sigmanew) { /* sigmanew is zero; this is a bad case; skip rescaling */ } else { /* sigmanew is positive */ ierr = VecScale(ctx->U, sigmanew);CHKERRQ(ierr); } break; } /* Modify for previous information */ switch(ctx->limitType) { case MatLMVM_Limit_Average: if (1.0 == ctx->mu) { ierr = VecCopy(ctx->D, ctx->U);CHKERRQ(ierr); } else if (ctx->mu) { ierr = VecAXPBY(ctx->D,ctx->mu, 1.0-ctx->mu,ctx->U);CHKERRQ(ierr); } break; case MatLMVM_Limit_Relative: if (ctx->mu) { /* P = (1-mu) * D */ ierr = VecAXPBY(ctx->P, 1.0-ctx->mu, 0.0, ctx->D);CHKERRQ(ierr); /* Q = (1+mu) * D */ ierr = VecAXPBY(ctx->Q, 1.0+ctx->mu, 0.0, ctx->D);CHKERRQ(ierr); ierr = VecMedian(ctx->P, ctx->U, ctx->Q, ctx->D);CHKERRQ(ierr); } break; case MatLMVM_Limit_Absolute: if (ctx->nu) { ierr = VecCopy(ctx->P, ctx->D);CHKERRQ(ierr); ierr = VecShift(ctx->P, -ctx->nu);CHKERRQ(ierr); ierr = VecCopy(ctx->D, ctx->Q);CHKERRQ(ierr); ierr = VecShift(ctx->Q, ctx->nu);CHKERRQ(ierr); ierr = VecMedian(ctx->P, ctx->U, ctx->Q, ctx->P);CHKERRQ(ierr); } break; default: ierr = VecCopy(ctx->U, ctx->D);CHKERRQ(ierr); break; } break; } ierr = PetscObjectDereference((PetscObject)ctx->Xprev);CHKERRQ(ierr); ierr = PetscObjectDereference((PetscObject)ctx->Gprev);CHKERRQ(ierr); ctx->Xprev = ctx->S[ctx->lm]; ctx->Gprev = ctx->Y[ctx->lm]; ierr = PetscObjectReference((PetscObject)ctx->S[ctx->lm]);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject)ctx->Y[ctx->lm]);CHKERRQ(ierr); } else { ++ctx->nrejects; } } ++ctx->iter; ierr = VecCopy(x, ctx->Xprev);CHKERRQ(ierr); ierr = VecCopy(g, ctx->Gprev);CHKERRQ(ierr); PetscFunctionReturn(0); }