PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) { PetscErrorCode ierr; PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); const PetscScalar *x,*xl,*xu,*f; PetscInt i,n,act[2] = {0,0},fact[2],N; /* Number of components that actually hit the bounds (c.f. active variables) */ PetscInt act_bound[2] = {0,0},fact_bound[2]; PetscReal rnorm,fnorm; double tmp; PetscFunctionBegin; ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr); ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); rnorm = 0.0; for (i=0; i<n; i++) { if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++; else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++; else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Can never get here"); } for (i=0; i<n; i++) { if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++; else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++; } ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); fnorm = PetscSqrtReal(fnorm); ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); if (snes->ntruebounds) tmp = ((double)(fact[0]+fact[1]))/((double)snes->ntruebounds); else tmp = 0.0; ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active lower constraints %D/%D upper constraints %D/%D Percent of total %g Percent of bounded %g\n",its,(double)fnorm,fact[0],fact_bound[0],fact[1],fact_bound[1],((double)(fact[0]+fact[1]))/((double)N),tmp);CHKERRQ(ierr); ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscDrawView - Prints the PetscDraw data structure. Collective on PetscDraw Input Parameters: + indraw - the PetscDraw context - viewer - visualization context Options Database Keys: . -draw_view - print the ksp data structure at the end of a PetscDrawSetFromOptions() call Note: The available visualization contexts include + PETSC_VIEWER_STDOUT_SELF - standard output (default) - PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first processor opens the file. All other processors send their data to the first processor to print. The user can open an alternative visualization context with PetscViewerASCIIOpen() - output to a specified file. Level: beginner .keywords: PetscDraw, view .seealso: PCView(), PetscViewerASCIIOpen() @*/ PetscErrorCode PetscDrawView(PetscDraw indraw,PetscViewer viewer) { PetscErrorCode ierr; PetscBool isdraw; #if defined(PETSC_HAVE_SAWS) PetscBool isams; #endif PetscFunctionBegin; PetscValidHeaderSpecific(indraw,PETSC_DRAW_CLASSID,1); if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)indraw)); PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(indraw,1,viewer,2); ierr = PetscObjectPrintClassNamePrefixType((PetscObject)indraw,viewer);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); #if defined(PETSC_HAVE_SAWS) ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&isams);CHKERRQ(ierr); #endif if (isdraw) { PetscDraw draw; char str[36]; PetscReal x,y,bottom,h; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); ierr = PetscStrcpy(str,"PetscDraw: ");CHKERRQ(ierr); ierr = PetscStrcat(str,((PetscObject)indraw)->type_name);CHKERRQ(ierr); ierr = PetscDrawBoxedString(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); bottom = y - h; ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); #if defined(PETSC_HAVE_SAWS) } else if (isams) { PetscMPIInt rank; ierr = PetscObjectName((PetscObject)indraw);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); if (!((PetscObject)indraw)->amsmem && !rank) { ierr = PetscObjectViewSAWs((PetscObject)indraw,viewer);CHKERRQ(ierr); } #endif } else if (indraw->ops->view) { ierr = (*indraw->ops->view)(indraw,viewer);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* Default (short) SNES Monitor, same as SNESMonitorDefault() except it prints fewer digits of the residual as the residual gets smaller. This is because the later digits are meaningless and are often different on different machines; by using this routine different machines will usually generate the same output. */ PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) { PetscErrorCode ierr; PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); PetscFunctionBegin; ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); if (fgnorm > 1.e-9) { ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr); } else if (fgnorm > 1.e-11){ ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); } ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode SNESSetFromOptions_QN(SNES snes) { PetscErrorCode ierr; SNES_QN *qn = (SNES_QN*)snes->data; PetscBool monflg = PETSC_FALSE,flg; SNESLineSearch linesearch; SNESQNRestartType rtype = qn->restart_type; SNESQNScaleType stype = qn->scale_type; SNESQNType qtype = qn->type; PetscFunctionBegin; ierr = PetscOptionsHead("SNES QN options");CHKERRQ(ierr); ierr = PetscOptionsInt("-snes_qn_m","Number of past states saved for L-BFGS methods","SNESQN",qn->m,&qn->m,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-snes_qn_powell_gamma","Powell angle tolerance", "SNESQN", qn->powell_gamma, &qn->powell_gamma, NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-snes_qn_powell_downhill","Powell descent tolerance", "SNESQN", qn->powell_downhill, &qn->powell_downhill, NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-snes_qn_monitor", "Monitor for the QN methods", "SNESQN", monflg, &monflg, NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-snes_qn_single_reduction", "Aggregate reductions", "SNESQN", qn->singlereduction, &qn->singlereduction, NULL);CHKERRQ(ierr); ierr = PetscOptionsEnum("-snes_qn_scale_type","Scaling type","SNESQNSetScaleType",SNESQNScaleTypes,(PetscEnum)stype,(PetscEnum*)&stype,&flg);CHKERRQ(ierr); if (flg) ierr = SNESQNSetScaleType(snes,stype);CHKERRQ(ierr); ierr = PetscOptionsEnum("-snes_qn_restart_type","Restart type","SNESQNSetRestartType",SNESQNRestartTypes,(PetscEnum)rtype,(PetscEnum*)&rtype,&flg);CHKERRQ(ierr); if (flg) ierr = SNESQNSetRestartType(snes,rtype);CHKERRQ(ierr); ierr = PetscOptionsEnum("-snes_qn_type","Quasi-Newton update type","",SNESQNTypes, (PetscEnum)qtype,(PetscEnum*)&qtype,&flg);CHKERRQ(ierr); if (flg) {ierr = SNESQNSetType(snes,qtype);CHKERRQ(ierr);} ierr = PetscOptionsTail();CHKERRQ(ierr); if (!snes->linesearch) { ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); if (qn->type == SNES_QN_LBFGS) { ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr); } else if (qn->type == SNES_QN_BROYDEN) { ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr); } else { ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); } } if (monflg) { qn->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode BSSCR_KSPNormInfToNorm2Monitor(KSP ksp,PetscInt n,PetscReal rnorm, void *dummy) { PetscErrorCode ierr; PetscViewerASCIIMonitor viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)ksp)->comm); PetscReal R_normInf, R_norm2; PetscInt R_size; Vec R, work, w1, w2; PetscFunctionBegin; ierr = VecDuplicate(ksp->vec_rhs,&work);CHKERRQ(ierr); ierr = VecDuplicate(ksp->vec_rhs,&w1);CHKERRQ(ierr); ierr = VecDuplicate(ksp->vec_rhs,&w2);CHKERRQ(ierr); KSPBuildResidual( ksp, w1,w2, &R ); VecNorm( R, NORM_INFINITY, &R_normInf ); VecNorm( R, NORM_2, &R_norm2 ); VecGetSize( R, &R_size ); ierr = PetscViewerASCIIMonitorCreate(((PetscObject)ksp)->comm,"stdout",0,&viewer); CHKERRQ(ierr); if(R_norm2 == 0.0) { ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D KSP Residual Spikiness - INFINITY (%s) \n", n, ((PetscObject)ksp)->prefix ? ((PetscObject)ksp)->prefix: "" ); CHKERRQ(ierr); } else{ ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D KSP Residual Spikiness %14.12e (%s) Max / Rms \n", n, sqrt((double) R_size) * R_normInf / R_norm2, ((PetscObject)ksp)->prefix ? ((PetscObject)ksp)->prefix: ""); CHKERRQ(ierr); } ierr = PetscViewerASCIIMonitorDestroy(viewer); CHKERRQ(ierr); Stg_VecDestroy(&work); Stg_VecDestroy(&w1); Stg_VecDestroy(&w2); PetscFunctionReturn(0); }
/*@C SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value. Collective on SNES Input Parameters: + snes - iterative context . it - iteration number . rnorm - 2-norm (preconditioned) residual value (may be estimated). - dummy - unused monitor context Options Database Key: . -snes_monitor_range - Activates SNESMonitorRange() Level: intermediate .keywords: SNES, default, monitor, residual .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate() @*/ PetscErrorCode SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy) { PetscErrorCode ierr; PetscReal perc,rel; PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); /* should be in a MonitorRangeContext */ static PetscReal prev; PetscFunctionBegin; if (!it) prev = rnorm; ierr = SNESMonitorRange_Private(snes,it,&perc);CHKERRQ(ierr); rel = (prev - rnorm)/prev; prev = rnorm; ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2f relative decrease %5.2e ratio %5.2e \n",it,(double)rnorm,(double)100.0*perc,(double)rel,(double)rel/perc);CHKERRQ(ierr); ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C KSPLSQRMonitorDefault - Print the residual norm at each iteration of the LSQR method and the norm of the residual of the normal equations A'*A x = A' b Collective on KSP Input Parameters: + ksp - iterative context . n - iteration number . rnorm - 2-norm (preconditioned) residual value (may be estimated). - dummy - unused monitor context Level: intermediate .keywords: KSP, default, monitor, residual .seealso: KSPMonitorSet(), KSPMonitorTrueResidualNorm(), KSPMonitorLGResidualNormCreate(), KSPMonitorDefault() @*/ PetscErrorCode KSPLSQRMonitorDefault(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy) { PetscErrorCode ierr; PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ksp)); KSP_LSQR *lsqr = (KSP_LSQR*)ksp->data; PetscFunctionBegin; ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);CHKERRQ(ierr); if (((PetscObject)ksp)->prefix) { ierr = PetscViewerASCIIPrintf(viewer," Residual norm and norm of normal equations for %s solve.\n",((PetscObject)ksp)->prefix);CHKERRQ(ierr); } if (!n) { ierr = PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e Residual norm normal equations %14.12e\n",n,rnorm,lsqr->arnorm);CHKERRQ(ierr); } ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C RGView - Prints the RG data structure. Collective on RG Input Parameters: + rg - the region context - viewer - optional visualization context Note: The available visualization contexts include + PETSC_VIEWER_STDOUT_SELF - standard output (default) - PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first processor opens the file. All other processors send their data to the first processor to print. The user can open an alternative visualization context with PetscViewerASCIIOpen() - output to a specified file. Level: beginner @*/ PetscErrorCode RGView(RG rg,PetscViewer viewer) { PetscBool isascii; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(rg,RG_CLASSID,1); if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)rg)); PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(rg,1,viewer,2); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); if (isascii) { ierr = PetscObjectPrintClassNamePrefixType((PetscObject)rg,viewer);CHKERRQ(ierr); if (rg->ops->view) { ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); ierr = (*rg->ops->view)(rg,viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); } if (rg->complement) { ierr = PetscViewerASCIIPrintf(viewer," selected region is the complement of the specified one\n");CHKERRQ(ierr); } } PetscFunctionReturn(0); }
static PetscErrorCode SNESSetFromOptions_NCG(SNES snes) { SNES_NCG *ncg = (SNES_NCG *)snes->data; PetscErrorCode ierr; PetscBool debug; SNESLineSearch linesearch; SNESNCGType ncgtype=ncg->type; PetscFunctionBegin; ierr = PetscOptionsHead("SNES NCG options"); CHKERRQ(ierr); ierr = PetscOptionsBool("-snes_ncg_monitor","Monitor NCG iterations","SNES",ncg->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL); CHKERRQ(ierr); ierr = PetscOptionsEnum("-snes_ncg_type","NCG Beta type used","SNESNCGSetType",SNESNCGTypes,(PetscEnum)ncg->type,(PetscEnum*)&ncgtype,PETSC_NULL); CHKERRQ(ierr); ierr = SNESNCGSetType(snes, ncgtype); CHKERRQ(ierr); if (debug) { ncg->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); CHKERRQ(ierr); } ierr = PetscOptionsTail(); CHKERRQ(ierr); if (!snes->linesearch) { ierr = SNESGetSNESLineSearch(snes, &linesearch); CHKERRQ(ierr); if (!snes->pc) { ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP); CHKERRQ(ierr); } else { ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2); CHKERRQ(ierr); } } PetscFunctionReturn(0); }
/*@ EPSPrintSolution - Prints the computed eigenvalues. Collective on EPS Input Parameters: + eps - the eigensolver context - viewer - optional visualization context Options Database Key: . -eps_terse - print only minimal information Note: By default, this function prints a table with eigenvalues and associated relative errors. With -eps_terse only the eigenvalues are printed. Level: intermediate .seealso: PetscViewerASCIIOpen() @*/ PetscErrorCode EPSPrintSolution(EPS eps,PetscViewer viewer) { PetscBool terse,errok,isascii; PetscReal error,re,im; PetscScalar kr,ki; PetscInt i,j; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(eps,EPS_CLASSID,1); if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)eps)); PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(eps,1,viewer,2); EPSCheckSolved(eps,1); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii); CHKERRQ(ierr); if (!isascii) PetscFunctionReturn(0); ierr = PetscOptionsHasName(NULL,"-eps_terse",&terse); CHKERRQ(ierr); if (terse) { if (eps->nconv<eps->nev) { ierr = PetscViewerASCIIPrintf(viewer," Problem: less than %D eigenvalues converged\n\n",eps->nev); CHKERRQ(ierr); } else { errok = PETSC_TRUE; for (i=0; i<eps->nev; i++) { ierr = EPSComputeRelativeError(eps,i,&error); CHKERRQ(ierr); errok = (errok && error<5.0*eps->tol)? PETSC_TRUE: PETSC_FALSE; } if (errok) { ierr = PetscViewerASCIIPrintf(viewer," All requested eigenvalues computed up to the required tolerance:"); CHKERRQ(ierr); for (i=0; i<=(eps->nev-1)/8; i++) { ierr = PetscViewerASCIIPrintf(viewer,"\n "); CHKERRQ(ierr); for (j=0; j<PetscMin(8,eps->nev-8*i); j++) { ierr = EPSGetEigenpair(eps,8*i+j,&kr,&ki,NULL,NULL); CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) re = PetscRealPart(kr); im = PetscImaginaryPart(kr); #else re = kr; im = ki; #endif if (PetscAbs(re)/PetscAbs(im)<PETSC_SMALL) re = 0.0; if (PetscAbs(im)/PetscAbs(re)<PETSC_SMALL) im = 0.0; if (im!=0.0) { ierr = PetscViewerASCIIPrintf(viewer,"%.5f%+.5fi",(double)re,(double)im); CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer,"%.5f",(double)re); CHKERRQ(ierr); } if (8*i+j+1<eps->nev) { ierr = PetscViewerASCIIPrintf(viewer,", "); CHKERRQ(ierr); } } } ierr = PetscViewerASCIIPrintf(viewer,"\n\n"); CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," Problem: some of the first %D relative errors are higher than the tolerance\n\n",eps->nev); CHKERRQ(ierr); } } } else { ierr = PetscViewerASCIIPrintf(viewer," Number of converged approximate eigenpairs: %D\n\n",eps->nconv); CHKERRQ(ierr); if (eps->nconv>0) { ierr = PetscViewerASCIIPrintf(viewer, " k ||Ax-k%sx||/||kx||\n" " ----------------- ------------------\n",eps->isgeneralized?"B":""); CHKERRQ(ierr); for (i=0; i<eps->nconv; i++) { ierr = EPSGetEigenpair(eps,i,&kr,&ki,NULL,NULL); CHKERRQ(ierr); ierr = EPSComputeRelativeError(eps,i,&error); CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) re = PetscRealPart(kr); im = PetscImaginaryPart(kr); #else re = kr; im = ki; #endif if (im!=0.0) { ierr = PetscViewerASCIIPrintf(viewer," % 9f%+9f i %12g\n",(double)re,(double)im,(double)error); CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," % 12f %12g\n",(double)re,(double)error); CHKERRQ(ierr); } } ierr = PetscViewerASCIIPrintf(viewer,"\n"); CHKERRQ(ierr); } } PetscFunctionReturn(0); }
/*@C SNESUpdateCheckJacobian - Checks each Jacobian computed by the nonlinear solver comparing the users function with a finite difference computation. Options Database: + -snes_check_jacobian - use this every time SNESSolve() is called - -snes_check_jacobian_view - Display difference between approximate and hand-coded Jacobian Level: intermediate .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESSolve() @*/ PetscErrorCode SNESUpdateCheckJacobian(SNES snes,PetscInt it) { Mat A = snes->jacobian,B; Vec x = snes->vec_sol,f = snes->vec_func,f1 = snes->vec_sol_update; PetscErrorCode ierr; PetscReal nrm,gnorm; PetscErrorCode (*objective)(SNES,Vec,PetscReal*,void*); void *ctx; PetscReal fnorm,f1norm,dnorm; PetscInt m,n,M,N; PetscBool complete_print = PETSC_FALSE; void *functx; PetscViewer viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); PetscFunctionBegin; ierr = PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_check_jacobian_view",&complete_print);CHKERRQ(ierr); if (A != snes->jacobian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot check Jacobian with alternative preconditioner"); ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Testing hand-coded Jacobian, if the ratio is O(1.e-8), the hand-coded Jacobian is probably correct.\n");CHKERRQ(ierr); if (!complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Run with -snes_check_jacobian_view [viewer][:filename][:format] to show difference of hand-coded and finite difference Jacobian.\n");CHKERRQ(ierr); } /* compute both versions of Jacobian */ ierr = SNESComputeJacobian(snes,x,A,A);CHKERRQ(ierr); ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,B,B,functx);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Finite difference Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(B,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); } /* compare */ ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(B,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(A,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Hand-coded minus finite difference Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(B,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); } if (!gnorm) gnorm = 1; /* just in case */ ierr = PetscViewerASCIIPrintf(viewer," %g = ||J - Jfd||//J|| %g = ||J - Jfd||\n",(double)(nrm/gnorm),(double)nrm);CHKERRQ(ierr); ierr = SNESGetObjective(snes,&objective,&ctx);CHKERRQ(ierr); if (objective) { ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&fnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Objective Function \n");CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } ierr = SNESObjectiveComputeFunctionDefaultFD(snes,x,f1,NULL);CHKERRQ(ierr); ierr = VecNorm(f1,NORM_2,&f1norm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Finite-Difference Objective Function\n");CHKERRQ(ierr); ierr = VecView(f1,viewer);CHKERRQ(ierr); } /* compare the two */ ierr = VecAXPY(f,-1.0,f1);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&dnorm);CHKERRQ(ierr); if (!fnorm) fnorm = 1.; ierr = PetscViewerASCIIPrintf(viewer," %g = Norm of objective function ratio %g = difference\n",dnorm/fnorm,dnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Difference\n");CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } } ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode PCBDDCNullSpaceAssembleCoarse(PC pc, Mat coarse_mat, MatNullSpace* CoarseNullSpace) { PC_BDDC *pcbddc = (PC_BDDC*)pc->data; Mat_IS *matis = (Mat_IS*)pc->pmat->data; MatNullSpace tempCoarseNullSpace=NULL; const Vec *nsp_vecs; Vec *coarse_nsp_vecs,local_vec,local_primal_vec,wcoarse_vec,wcoarse_rhs; PetscInt nsp_size,coarse_nsp_size,i; PetscBool nsp_has_cnst; PetscReal test_null; PetscErrorCode ierr; PetscFunctionBegin; tempCoarseNullSpace = 0; coarse_nsp_size = 0; coarse_nsp_vecs = 0; ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr); if (coarse_mat) { ierr = PetscMalloc1(nsp_size+1,&coarse_nsp_vecs);CHKERRQ(ierr); for (i=0;i<nsp_size+1;i++) { ierr = MatCreateVecs(coarse_mat,&coarse_nsp_vecs[i],NULL);CHKERRQ(ierr); } if (pcbddc->dbg_flag) { ierr = MatCreateVecs(coarse_mat,&wcoarse_vec,&wcoarse_rhs);CHKERRQ(ierr); } } ierr = MatCreateVecs(pcbddc->ConstraintMatrix,&local_vec,&local_primal_vec);CHKERRQ(ierr); if (nsp_has_cnst) { ierr = VecSet(local_vec,1.0);CHKERRQ(ierr); ierr = MatMult(pcbddc->ConstraintMatrix,local_vec,local_primal_vec);CHKERRQ(ierr); ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); if (coarse_mat) { PetscScalar *array_out; const PetscScalar *array_in; PetscInt lsize; if (pcbddc->dbg_flag) { PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); ierr = MatMult(coarse_mat,wcoarse_vec,wcoarse_rhs);CHKERRQ(ierr); ierr = VecNorm(wcoarse_rhs,NORM_INFINITY,&test_null);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(dbg_viewer,"Constant coarse null space error % 1.14e\n",test_null);CHKERRQ(ierr); ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr); } ierr = VecGetLocalSize(pcbddc->coarse_vec,&lsize);CHKERRQ(ierr); ierr = VecGetArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr); ierr = VecGetArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr); ierr = PetscMemcpy(array_out,array_in,lsize*sizeof(PetscScalar));CHKERRQ(ierr); ierr = VecRestoreArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr); ierr = VecRestoreArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr); coarse_nsp_size++; } } for (i=0;i<nsp_size;i++) { ierr = VecScatterBegin(matis->rctx,nsp_vecs[i],local_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(matis->rctx,nsp_vecs[i],local_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = MatMult(pcbddc->ConstraintMatrix,local_vec,local_primal_vec);CHKERRQ(ierr); ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); if (coarse_mat) { PetscScalar *array_out; const PetscScalar *array_in; PetscInt lsize; if (pcbddc->dbg_flag) { PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); ierr = MatMult(coarse_mat,wcoarse_vec,wcoarse_rhs);CHKERRQ(ierr); ierr = VecNorm(wcoarse_rhs,NORM_2,&test_null);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(dbg_viewer,"Vec %d coarse null space error % 1.14e\n",i,test_null);CHKERRQ(ierr); ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr); } ierr = VecGetLocalSize(pcbddc->coarse_vec,&lsize);CHKERRQ(ierr); ierr = VecGetArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr); ierr = VecGetArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr); ierr = PetscMemcpy(array_out,array_in,lsize*sizeof(PetscScalar));CHKERRQ(ierr); ierr = VecRestoreArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr); ierr = VecRestoreArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr); coarse_nsp_size++; } } if (coarse_nsp_size > 0) { ierr = PCBDDCOrthonormalizeVecs(coarse_nsp_size,coarse_nsp_vecs);CHKERRQ(ierr); ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,coarse_nsp_size,coarse_nsp_vecs,&tempCoarseNullSpace);CHKERRQ(ierr); for (i=0;i<nsp_size+1;i++) { ierr = VecDestroy(&coarse_nsp_vecs[i]);CHKERRQ(ierr); } } if (coarse_mat) { ierr = PetscFree(coarse_nsp_vecs);CHKERRQ(ierr); if (pcbddc->dbg_flag) { ierr = VecDestroy(&wcoarse_vec);CHKERRQ(ierr); ierr = VecDestroy(&wcoarse_rhs);CHKERRQ(ierr); } } ierr = VecDestroy(&local_vec);CHKERRQ(ierr); ierr = VecDestroy(&local_primal_vec);CHKERRQ(ierr); *CoarseNullSpace = tempCoarseNullSpace; PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat C,Credundant; MatInfo info; PetscMPIInt rank,size,subsize; PetscInt i,j,m = 3,n = 2,low,high,iglobal; PetscInt Ii,J,ldim,nsubcomms; PetscErrorCode ierr; PetscBool flg_info,flg_mat; PetscScalar v,one = 1.0; Vec x,y; MPI_Comm subcomm; ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; ierr = PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); n = 2*size; ierr = MatCreate(PETSC_COMM_WORLD,&C);CHKERRQ(ierr); ierr = MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n);CHKERRQ(ierr); ierr = MatSetFromOptions(C);CHKERRQ(ierr); ierr = MatSetUp(C);CHKERRQ(ierr); /* Create the matrix for the five point stencil, YET AGAIN */ for (i=0; i<m; i++) { for (j=2*rank; j<2*rank+2; j++) { v = -1.0; Ii = j + n*i; if (i>0) {J = Ii - n; ierr = MatSetValues(C,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);} if (i<m-1) {J = Ii + n; ierr = MatSetValues(C,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);} if (j>0) {J = Ii - 1; ierr = MatSetValues(C,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);} if (j<n-1) {J = Ii + 1; ierr = MatSetValues(C,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);} v = 4.0; ierr = MatSetValues(C,1,&Ii,1,&Ii,&v,INSERT_VALUES);CHKERRQ(ierr); } } /* Add extra elements (to illustrate variants of MatGetInfo) */ Ii = n; J = n-2; v = 100.0; ierr = MatSetValues(C,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr); Ii = n-2; J = n; v = 100.0; ierr = MatSetValues(C,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Form vectors */ ierr = MatCreateVecs(C,&x,&y);CHKERRQ(ierr); ierr = VecGetLocalSize(x,&ldim);CHKERRQ(ierr); ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr); for (i=0; i<ldim; i++) { iglobal = i + low; v = one*((PetscReal)i) + 100.0*rank; ierr = VecSetValues(x,1,&iglobal,&v,INSERT_VALUES);CHKERRQ(ierr); } ierr = VecAssemblyBegin(x);CHKERRQ(ierr); ierr = VecAssemblyEnd(x);CHKERRQ(ierr); ierr = MatMult(C,x,y);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,NULL,"-view_info",&flg_info);CHKERRQ(ierr); if (flg_info) { ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = MatGetInfo(C,MAT_GLOBAL_SUM,&info);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"matrix information (global sums):\nnonzeros = %D, allocated nonzeros = %D\n",(PetscInt)info.nz_used,(PetscInt)info.nz_allocated);CHKERRQ(ierr); ierr = MatGetInfo (C,MAT_GLOBAL_MAX,&info);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"matrix information (global max):\nnonzeros = %D, allocated nonzeros = %D\n",(PetscInt)info.nz_used,(PetscInt)info.nz_allocated);CHKERRQ(ierr); } ierr = PetscOptionsHasName(NULL,NULL,"-view_mat",&flg_mat);CHKERRQ(ierr); if (flg_mat) { ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } /* Test MatCreateRedundantMatrix() */ nsubcomms = size; ierr = PetscOptionsGetInt(NULL,NULL,"-nsubcomms",&nsubcomms,NULL);CHKERRQ(ierr); ierr = MatCreateRedundantMatrix(C,nsubcomms,MPI_COMM_NULL,MAT_INITIAL_MATRIX,&Credundant);CHKERRQ(ierr); ierr = MatCreateRedundantMatrix(C,nsubcomms,MPI_COMM_NULL,MAT_REUSE_MATRIX,&Credundant);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)Credundant,&subcomm);CHKERRQ(ierr); ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr); if (subsize==2 && flg_mat) { ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_(subcomm),"\n[%d] Credundant:\n",rank);CHKERRQ(ierr); ierr = MatView(Credundant,PETSC_VIEWER_STDOUT_(subcomm));CHKERRQ(ierr); } ierr = MatDestroy(&Credundant);CHKERRQ(ierr); /* Test MatCreateRedundantMatrix() with user-provided subcomm */ { PetscSubcomm psubcomm; ierr = PetscSubcommCreate(PETSC_COMM_WORLD,&psubcomm);CHKERRQ(ierr); ierr = PetscSubcommSetNumber(psubcomm,nsubcomms);CHKERRQ(ierr); ierr = PetscSubcommSetType(psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr); /* enable runtime switch of psubcomm type, e.g., '-psubcomm_type interlaced */ ierr = PetscSubcommSetFromOptions(psubcomm);CHKERRQ(ierr); ierr = MatCreateRedundantMatrix(C,nsubcomms,PetscSubcommChild(psubcomm),MAT_INITIAL_MATRIX,&Credundant);CHKERRQ(ierr); ierr = MatCreateRedundantMatrix(C,nsubcomms,PetscSubcommChild(psubcomm),MAT_REUSE_MATRIX,&Credundant);CHKERRQ(ierr); ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr); ierr = MatDestroy(&Credundant);CHKERRQ(ierr); } ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&y);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
/*@ DMPlexOrient - Give a consistent orientation to the input mesh Input Parameters: . dm - The DM Note: The orientation data for the DM are change in-place. $ This routine will fail for non-orientable surfaces, such as the Moebius strip. Level: advanced .seealso: DMCreate(), DMPLEX @*/ PetscErrorCode DMPlexOrient(DM dm) { MPI_Comm comm; PetscSF sf; const PetscInt *lpoints; const PetscSFNode *rpoints; PetscSFNode *rorntComp = NULL, *lorntComp = NULL; PetscInt *numNeighbors, **neighbors; PetscSFNode *nrankComp; PetscBool *match, *flipped; PetscBT seenCells, flippedCells, seenFaces; PetscInt *faceFIFO, fTop, fBottom, *cellComp, *faceComp; PetscInt numLeaves, numRoots, dim, h, cStart, cEnd, c, cell, fStart, fEnd, face, off, totNeighbors = 0; PetscMPIInt rank, size, numComponents, comp = 0; PetscBool flg, flg2; PetscViewer viewer = NULL, selfviewer = NULL; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-orientation_view", &flg);CHKERRQ(ierr); ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-orientation_view_synchronized", &flg2);CHKERRQ(ierr); ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &lpoints, &rpoints);CHKERRQ(ierr); /* Truth Table mismatch flips do action mismatch flipA ^ flipB action F 0 flips no F F F F 1 flip yes F T T F 2 flips no T F T T 0 flips yes T T F T 1 flip no T 2 flips yes */ ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMPlexGetVTKCellHeight(dm, &h);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, h+1, &fStart, &fEnd);CHKERRQ(ierr); ierr = PetscBTCreate(cEnd - cStart, &seenCells);CHKERRQ(ierr); ierr = PetscBTMemzero(cEnd - cStart, seenCells);CHKERRQ(ierr); ierr = PetscBTCreate(cEnd - cStart, &flippedCells);CHKERRQ(ierr); ierr = PetscBTMemzero(cEnd - cStart, flippedCells);CHKERRQ(ierr); ierr = PetscBTCreate(fEnd - fStart, &seenFaces);CHKERRQ(ierr); ierr = PetscBTMemzero(fEnd - fStart, seenFaces);CHKERRQ(ierr); ierr = PetscCalloc3(fEnd - fStart, &faceFIFO, cEnd-cStart, &cellComp, fEnd-fStart, &faceComp);CHKERRQ(ierr); /* OLD STYLE - Add an integer array over cells and faces (component) for connected component number Foreach component - Mark the initial cell as seen - Process component as usual - Set component for all seenCells - Wipe seenCells and seenFaces (flippedCells can stay) - Generate parallel adjacency for component using SF and seenFaces - Collect numComponents adj data from each proc to 0 - Build same serial graph - Use same solver - Use Scatterv to to send back flipped flags for each component - Negate flippedCells by component NEW STYLE - Create the adj on each process - Bootstrap to complete graph on proc 0 */ /* Loop over components */ for (cell = cStart; cell < cEnd; ++cell) cellComp[cell-cStart] = -1; do { /* Look for first unmarked cell */ for (cell = cStart; cell < cEnd; ++cell) if (cellComp[cell-cStart] < 0) break; if (cell >= cEnd) break; /* Initialize FIFO with first cell in component */ { const PetscInt *cone; PetscInt coneSize; fTop = fBottom = 0; ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); for (c = 0; c < coneSize; ++c) { faceFIFO[fBottom++] = cone[c]; ierr = PetscBTSet(seenFaces, cone[c]-fStart);CHKERRQ(ierr); } ierr = PetscBTSet(seenCells, cell-cStart);CHKERRQ(ierr); } /* Consider each face in FIFO */ while (fTop < fBottom) { ierr = DMPlexCheckFace_Internal(dm, faceFIFO, &fTop, &fBottom, cStart, fStart, fEnd, seenCells, flippedCells, seenFaces);CHKERRQ(ierr); } /* Set component for cells and faces */ for (cell = 0; cell < cEnd-cStart; ++cell) { if (PetscBTLookup(seenCells, cell)) cellComp[cell] = comp; } for (face = 0; face < fEnd-fStart; ++face) { if (PetscBTLookup(seenFaces, face)) faceComp[face] = comp; } /* Wipe seenCells and seenFaces for next component */ ierr = PetscBTMemzero(fEnd - fStart, seenFaces);CHKERRQ(ierr); ierr = PetscBTMemzero(cEnd - cStart, seenCells);CHKERRQ(ierr); ++comp; } while (1); numComponents = comp; if (flg) { PetscViewer v; ierr = PetscViewerASCIIGetStdout(comm, &v);CHKERRQ(ierr); ierr = PetscViewerASCIIPushSynchronized(v);CHKERRQ(ierr); ierr = PetscViewerASCIISynchronizedPrintf(v, "[%d]BT for serial flipped cells:\n", rank);CHKERRQ(ierr); ierr = PetscBTView(cEnd-cStart, flippedCells, v);CHKERRQ(ierr); ierr = PetscViewerFlush(v);CHKERRQ(ierr); ierr = PetscViewerASCIIPopSynchronized(v);CHKERRQ(ierr); } /* Now all subdomains are oriented, but we need a consistent parallel orientation */ if (numLeaves >= 0) { /* Store orientations of boundary faces*/ ierr = PetscCalloc2(numRoots,&rorntComp,numRoots,&lorntComp);CHKERRQ(ierr); for (face = fStart; face < fEnd; ++face) { const PetscInt *cone, *support, *ornt; PetscInt coneSize, supportSize; ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); if (supportSize != 1) continue; ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr); ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr); ierr = DMPlexGetConeOrientation(dm, support[0], &ornt);CHKERRQ(ierr); for (c = 0; c < coneSize; ++c) if (cone[c] == face) break; if (dim == 1) { /* Use cone position instead, shifted to -1 or 1 */ if (PetscBTLookup(flippedCells, support[0]-cStart)) rorntComp[face].rank = 1-c*2; else rorntComp[face].rank = c*2-1; } else { if (PetscBTLookup(flippedCells, support[0]-cStart)) rorntComp[face].rank = ornt[c] < 0 ? -1 : 1; else rorntComp[face].rank = ornt[c] < 0 ? 1 : -1; } rorntComp[face].index = faceComp[face-fStart]; } /* Communicate boundary edge orientations */ ierr = PetscSFBcastBegin(sf, MPIU_2INT, rorntComp, lorntComp);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf, MPIU_2INT, rorntComp, lorntComp);CHKERRQ(ierr); } /* Get process adjacency */ ierr = PetscMalloc2(numComponents, &numNeighbors, numComponents, &neighbors);CHKERRQ(ierr); viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm)); if (flg2) {ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);} ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&selfviewer);CHKERRQ(ierr); for (comp = 0; comp < numComponents; ++comp) { PetscInt l, n; numNeighbors[comp] = 0; ierr = PetscMalloc1(PetscMax(numLeaves, 0), &neighbors[comp]);CHKERRQ(ierr); /* I know this is p^2 time in general, but for bounded degree its alright */ for (l = 0; l < numLeaves; ++l) { const PetscInt face = lpoints[l]; /* Find a representative face (edge) separating pairs of procs */ if ((face >= fStart) && (face < fEnd) && (faceComp[face-fStart] == comp)) { const PetscInt rrank = rpoints[l].rank; const PetscInt rcomp = lorntComp[face].index; for (n = 0; n < numNeighbors[comp]; ++n) if ((rrank == rpoints[neighbors[comp][n]].rank) && (rcomp == lorntComp[lpoints[neighbors[comp][n]]].index)) break; if (n >= numNeighbors[comp]) { PetscInt supportSize; ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); if (supportSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Boundary faces should see one cell, not %d", supportSize); if (flg) {ierr = PetscViewerASCIIPrintf(selfviewer, "[%d]: component %d, Found representative leaf %d (face %d) connecting to face %d on (%d, %d) with orientation %d\n", rank, comp, l, face, rpoints[l].index, rrank, rcomp, lorntComp[face].rank);CHKERRQ(ierr);} neighbors[comp][numNeighbors[comp]++] = l; } } } totNeighbors += numNeighbors[comp]; } ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&selfviewer);CHKERRQ(ierr); ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); if (flg2) {ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);} ierr = PetscMalloc2(totNeighbors, &nrankComp, totNeighbors, &match);CHKERRQ(ierr); for (comp = 0, off = 0; comp < numComponents; ++comp) { PetscInt n; for (n = 0; n < numNeighbors[comp]; ++n, ++off) { const PetscInt face = lpoints[neighbors[comp][n]]; const PetscInt o = rorntComp[face].rank*lorntComp[face].rank; if (o < 0) match[off] = PETSC_TRUE; else if (o > 0) match[off] = PETSC_FALSE; else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid face %d (%d, %d) neighbor: %d comp: %d", face, rorntComp[face], lorntComp[face], neighbors[comp][n], comp); nrankComp[off].rank = rpoints[neighbors[comp][n]].rank; nrankComp[off].index = lorntComp[lpoints[neighbors[comp][n]]].index; } ierr = PetscFree(neighbors[comp]);CHKERRQ(ierr); } /* Collect the graph on 0 */ if (numLeaves >= 0) { Mat G; PetscBT seenProcs, flippedProcs; PetscInt *procFIFO, pTop, pBottom; PetscInt *N = NULL, *Noff; PetscSFNode *adj = NULL; PetscBool *val = NULL; PetscMPIInt *recvcounts = NULL, *displs = NULL, *Nc, p, o; PetscMPIInt size = 0; ierr = PetscCalloc1(numComponents, &flipped);CHKERRQ(ierr); if (!rank) {ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);} ierr = PetscCalloc4(size, &recvcounts, size+1, &displs, size, &Nc, size+1, &Noff);CHKERRQ(ierr); ierr = MPI_Gather(&numComponents, 1, MPI_INT, Nc, 1, MPI_INT, 0, comm);CHKERRQ(ierr); for (p = 0; p < size; ++p) { displs[p+1] = displs[p] + Nc[p]; } if (!rank) {ierr = PetscMalloc1(displs[size],&N);CHKERRQ(ierr);} ierr = MPI_Gatherv(numNeighbors, numComponents, MPIU_INT, N, Nc, displs, MPIU_INT, 0, comm);CHKERRQ(ierr); for (p = 0, o = 0; p < size; ++p) { recvcounts[p] = 0; for (c = 0; c < Nc[p]; ++c, ++o) recvcounts[p] += N[o]; displs[p+1] = displs[p] + recvcounts[p]; } if (!rank) {ierr = PetscMalloc2(displs[size], &adj, displs[size], &val);CHKERRQ(ierr);} ierr = MPI_Gatherv(nrankComp, totNeighbors, MPIU_2INT, adj, recvcounts, displs, MPIU_2INT, 0, comm);CHKERRQ(ierr); ierr = MPI_Gatherv(match, totNeighbors, MPIU_BOOL, val, recvcounts, displs, MPIU_BOOL, 0, comm);CHKERRQ(ierr); ierr = PetscFree2(numNeighbors, neighbors);CHKERRQ(ierr); if (!rank) { for (p = 1; p <= size; ++p) {Noff[p] = Noff[p-1] + Nc[p-1];} if (flg) { PetscInt n; for (p = 0, off = 0; p < size; ++p) { for (c = 0; c < Nc[p]; ++c) { ierr = PetscPrintf(PETSC_COMM_SELF, "Proc %d Comp %d:\n", p, c);CHKERRQ(ierr); for (n = 0; n < N[Noff[p]+c]; ++n, ++off) { ierr = PetscPrintf(PETSC_COMM_SELF, " edge (%d, %d) (%d):\n", adj[off].rank, adj[off].index, val[off]);CHKERRQ(ierr); } } } } /* Symmetrize the graph */ ierr = MatCreate(PETSC_COMM_SELF, &G);CHKERRQ(ierr); ierr = MatSetSizes(G, Noff[size], Noff[size], Noff[size], Noff[size]);CHKERRQ(ierr); ierr = MatSetUp(G);CHKERRQ(ierr); for (p = 0, off = 0; p < size; ++p) { for (c = 0; c < Nc[p]; ++c) { const PetscInt r = Noff[p]+c; PetscInt n; for (n = 0; n < N[r]; ++n, ++off) { const PetscInt q = Noff[adj[off].rank] + adj[off].index; const PetscScalar o = val[off] ? 1.0 : 0.0; ierr = MatSetValues(G, 1, &r, 1, &q, &o, INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(G, 1, &q, 1, &r, &o, INSERT_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(G, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(G, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = PetscBTCreate(Noff[size], &seenProcs);CHKERRQ(ierr); ierr = PetscBTMemzero(Noff[size], seenProcs);CHKERRQ(ierr); ierr = PetscBTCreate(Noff[size], &flippedProcs);CHKERRQ(ierr); ierr = PetscBTMemzero(Noff[size], flippedProcs);CHKERRQ(ierr); ierr = PetscMalloc1(Noff[size], &procFIFO);CHKERRQ(ierr); pTop = pBottom = 0; for (p = 0; p < Noff[size]; ++p) { if (PetscBTLookup(seenProcs, p)) continue; /* Initialize FIFO with next proc */ procFIFO[pBottom++] = p; ierr = PetscBTSet(seenProcs, p);CHKERRQ(ierr); /* Consider each proc in FIFO */ while (pTop < pBottom) { const PetscScalar *ornt; const PetscInt *neighbors; PetscInt proc, nproc, seen, flippedA, flippedB, mismatch, numNeighbors, n; proc = procFIFO[pTop++]; flippedA = PetscBTLookup(flippedProcs, proc) ? 1 : 0; ierr = MatGetRow(G, proc, &numNeighbors, &neighbors, &ornt);CHKERRQ(ierr); /* Loop over neighboring procs */ for (n = 0; n < numNeighbors; ++n) { nproc = neighbors[n]; mismatch = PetscRealPart(ornt[n]) > 0.5 ? 0 : 1; seen = PetscBTLookup(seenProcs, nproc); flippedB = PetscBTLookup(flippedProcs, nproc) ? 1 : 0; if (mismatch ^ (flippedA ^ flippedB)) { if (seen) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Previously seen procs %d and %d do not match: Fault mesh is non-orientable", proc, nproc); if (!flippedB) { ierr = PetscBTSet(flippedProcs, nproc);CHKERRQ(ierr); } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent mesh orientation: Fault mesh is non-orientable"); } else if (mismatch && flippedA && flippedB) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Attempt to flip already flipped cell: Fault mesh is non-orientable"); if (!seen) { procFIFO[pBottom++] = nproc; ierr = PetscBTSet(seenProcs, nproc);CHKERRQ(ierr); } } } } ierr = PetscFree(procFIFO);CHKERRQ(ierr); ierr = MatDestroy(&G);CHKERRQ(ierr); ierr = PetscFree2(adj, val);CHKERRQ(ierr); ierr = PetscBTDestroy(&seenProcs);CHKERRQ(ierr); } /* Scatter flip flags */ { PetscBool *flips = NULL; if (!rank) { ierr = PetscMalloc1(Noff[size], &flips);CHKERRQ(ierr); for (p = 0; p < Noff[size]; ++p) { flips[p] = PetscBTLookup(flippedProcs, p) ? PETSC_TRUE : PETSC_FALSE; if (flg && flips[p]) {ierr = PetscPrintf(comm, "Flipping Proc+Comp %d:\n", p);CHKERRQ(ierr);} } for (p = 0; p < size; ++p) { displs[p+1] = displs[p] + Nc[p]; } } ierr = MPI_Scatterv(flips, Nc, displs, MPIU_BOOL, flipped, numComponents, MPIU_BOOL, 0, comm);CHKERRQ(ierr); ierr = PetscFree(flips);CHKERRQ(ierr); } if (!rank) {ierr = PetscBTDestroy(&flippedProcs);CHKERRQ(ierr);} ierr = PetscFree(N);CHKERRQ(ierr); ierr = PetscFree4(recvcounts, displs, Nc, Noff);CHKERRQ(ierr); ierr = PetscFree2(nrankComp, match);CHKERRQ(ierr); /* Decide whether to flip cells in each component */ for (c = 0; c < cEnd-cStart; ++c) {if (flipped[cellComp[c]]) {ierr = PetscBTNegate(flippedCells, c);CHKERRQ(ierr);}} ierr = PetscFree(flipped);CHKERRQ(ierr); } if (flg) { PetscViewer v; ierr = PetscViewerASCIIGetStdout(comm, &v);CHKERRQ(ierr); ierr = PetscViewerASCIIPushSynchronized(v);CHKERRQ(ierr); ierr = PetscViewerASCIISynchronizedPrintf(v, "[%d]BT for parallel flipped cells:\n", rank);CHKERRQ(ierr); ierr = PetscBTView(cEnd-cStart, flippedCells, v);CHKERRQ(ierr); ierr = PetscViewerFlush(v);CHKERRQ(ierr); ierr = PetscViewerASCIIPopSynchronized(v);CHKERRQ(ierr); } /* Reverse flipped cells in the mesh */ for (c = cStart; c < cEnd; ++c) { if (PetscBTLookup(flippedCells, c-cStart)) { ierr = DMPlexReverseCell(dm, c);CHKERRQ(ierr); } } ierr = PetscBTDestroy(&seenCells);CHKERRQ(ierr); ierr = PetscBTDestroy(&flippedCells);CHKERRQ(ierr); ierr = PetscBTDestroy(&seenFaces);CHKERRQ(ierr); ierr = PetscFree2(numNeighbors, neighbors);CHKERRQ(ierr); ierr = PetscFree2(rorntComp, lorntComp);CHKERRQ(ierr); ierr = PetscFree3(faceFIFO, cellComp, faceComp);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C KSPView - Prints the KSP data structure. Collective on KSP Input Parameters: + ksp - the Krylov space context - viewer - visualization context Options Database Keys: . -ksp_view - print the ksp data structure at the end of a KSPSolve call Note: The available visualization contexts include + PETSC_VIEWER_STDOUT_SELF - standard output (default) - PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first processor opens the file. All other processors send their data to the first processor to print. The user can open an alternative visualization context with PetscViewerASCIIOpen() - output to a specified file. Level: beginner .keywords: KSP, view .seealso: PCView(), PetscViewerASCIIOpen() @*/ PetscErrorCode KSPView(KSP ksp,PetscViewer viewer) { PetscErrorCode ierr; PetscBool iascii,isbinary,isdraw; #if defined(PETSC_HAVE_AMS) PetscBool isams; #endif PetscFunctionBegin; PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ksp)); PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(ksp,1,viewer,2); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); #if defined(PETSC_HAVE_AMS) ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERAMS,&isams);CHKERRQ(ierr); #endif if (iascii) { ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ksp,viewer,"KSP Object");CHKERRQ(ierr); if (ksp->ops->view) { ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); } if (ksp->guess_zero) { ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D, initial guess is zero\n",ksp->max_it);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D\n", ksp->max_it);CHKERRQ(ierr); } if (ksp->guess_knoll) {ierr = PetscViewerASCIIPrintf(viewer," using preconditioner applied to right hand side for initial guess\n");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer," tolerances: relative=%G, absolute=%G, divergence=%G\n",ksp->rtol,ksp->abstol,ksp->divtol);CHKERRQ(ierr); if (ksp->pc_side == PC_RIGHT) { ierr = PetscViewerASCIIPrintf(viewer," right preconditioning\n");CHKERRQ(ierr); } else if (ksp->pc_side == PC_SYMMETRIC) { ierr = PetscViewerASCIIPrintf(viewer," symmetric preconditioning\n");CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," left preconditioning\n");CHKERRQ(ierr); } if (ksp->guess) {ierr = PetscViewerASCIIPrintf(viewer," using Fischers initial guess method %D with size %D\n",ksp->guess->method,ksp->guess->maxl);CHKERRQ(ierr);} if (ksp->dscale) {ierr = PetscViewerASCIIPrintf(viewer," diagonally scaled system\n");CHKERRQ(ierr);} if (ksp->nullsp) {ierr = PetscViewerASCIIPrintf(viewer," has attached null space\n");CHKERRQ(ierr);} if (!ksp->guess_zero) {ierr = PetscViewerASCIIPrintf(viewer," using nonzero initial guess\n");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer," using %s norm type for convergence test\n",KSPNormTypes[ksp->normtype]);CHKERRQ(ierr); } else if (isbinary) { PetscInt classid = KSP_FILE_CLASSID; MPI_Comm comm; PetscMPIInt rank; char type[256]; ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); ierr = PetscStrncpy(type,((PetscObject)ksp)->type_name,256);CHKERRQ(ierr); ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); } if (ksp->ops->view) { ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); } } else if (isdraw) { PetscDraw draw; char str[36]; PetscReal x,y,bottom,h; PetscBool flg; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);CHKERRQ(ierr); if (!flg) { ierr = PetscStrcpy(str,"KSP: ");CHKERRQ(ierr); ierr = PetscStrcat(str,((PetscObject)ksp)->type_name);CHKERRQ(ierr); ierr = PetscDrawBoxedString(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); bottom = y - h; } else { bottom = y; } ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); #if defined(PETSC_HAVE_AMS) } else if (isams) { if (((PetscObject)ksp)->amsmem == -1) { ierr = PetscObjectViewAMS((PetscObject)ksp,viewer);CHKERRQ(ierr); PetscStackCallAMS(AMS_Memory_take_access,(((PetscObject)ksp)->amsmem)); PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)ksp)->amsmem,"its",&ksp->its,1,AMS_INT,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF)); if (!ksp->res_hist) { ierr = KSPSetResidualHistory(ksp,NULL,PETSC_DECIDE,PETSC_FALSE);CHKERRQ(ierr); } PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)ksp)->amsmem,"res_hist",ksp->res_hist,10,AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF)); PetscStackCallAMS(AMS_Memory_grant_access,(((PetscObject)ksp)->amsmem)); } #endif } else if (ksp->ops->view) { ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); } if (!ksp->pc) {ierr = KSPGetPC(ksp,&ksp->pc);CHKERRQ(ierr);} ierr = PCView(ksp->pc,viewer);CHKERRQ(ierr); if (isdraw) { PetscDraw draw; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode DMPatchSolve(DM dm) { MPI_Comm comm; MPI_Comm commz; DM dmc; PetscSF sfz, sfzr; Vec XC; MatStencil patchSize, commSize, gridRank, lower, upper; PetscInt M, N, P, i, j, k, l, m, n, p = 0; PetscMPIInt rank, size; PetscInt debug = 0; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = DMPatchGetCoarse(dm, &dmc);CHKERRQ(ierr); ierr = DMPatchGetPatchSize(dm, &patchSize);CHKERRQ(ierr); ierr = DMPatchGetCommSize(dm, &commSize);CHKERRQ(ierr); ierr = DMPatchGetCommSize(dm, &commSize);CHKERRQ(ierr); ierr = DMGetGlobalVector(dmc, &XC);CHKERRQ(ierr); ierr = DMDAGetInfo(dmc, 0, &M, &N, &P, &l, &m, &n, 0,0,0,0,0,0);CHKERRQ(ierr); M = PetscMax(M, 1); l = PetscMax(l, 1); N = PetscMax(N, 1); m = PetscMax(m, 1); P = PetscMax(P, 1); n = PetscMax(n, 1); gridRank.i = rank % l; gridRank.j = rank/l % m; gridRank.k = rank/(l*m) % n; if (commSize.i*commSize.j*commSize.k == size || commSize.i*commSize.j*commSize.k == 0) { commSize.i = l; commSize.j = m; commSize.k = n; commz = comm; } else if (commSize.i*commSize.j*commSize.k == 1) { commz = PETSC_COMM_SELF; } else { const PetscMPIInt newComm = ((gridRank.k/commSize.k)*(m/commSize.j) + gridRank.j/commSize.j)*(l/commSize.i) + (gridRank.i/commSize.i); const PetscMPIInt newRank = ((gridRank.k%commSize.k)*commSize.j + gridRank.j%commSize.j)*commSize.i + (gridRank.i%commSize.i); ierr = MPI_Comm_split(comm, newComm, newRank, &commz);CHKERRQ(ierr); if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Rank %d color %d key %d commz %d\n", rank, newComm, newRank, *((PetscMPIInt*) &commz));CHKERRQ(ierr);} } /* Assumptions: - patchSize divides gridSize - commSize divides gridSize - commSize divides l,m,n Ignore multiple patches per rank for now Multiple ranks per patch: - l,m,n divides patchSize - commSize divides patchSize */ for (k = 0; k < P; k += PetscMax(patchSize.k, 1)) { for (j = 0; j < N; j += PetscMax(patchSize.j, 1)) { for (i = 0; i < M; i += PetscMax(patchSize.i, 1), ++p) { MPI_Comm commp = MPI_COMM_NULL; DM dmz = NULL; #if 0 DM dmf = NULL; Mat interpz = NULL; #endif Vec XZ = NULL; PetscScalar *xcarray = NULL; PetscScalar *xzarray = NULL; if ((gridRank.k/commSize.k == p/(l/commSize.i * m/commSize.j) % n/commSize.k) && (gridRank.j/commSize.j == p/(l/commSize.i) % m/commSize.j) && (gridRank.i/commSize.i == p % l/commSize.i)) { if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Rank %d is accepting Patch %d\n", rank, p);CHKERRQ(ierr);} commp = commz; } /* Zoom to coarse patch */ lower.i = i; lower.j = j; lower.k = k; upper.i = i + patchSize.i; upper.j = j + patchSize.j; upper.k = k + patchSize.k; ierr = DMPatchZoom(dmc, XC, lower, upper, commp, &dmz, &sfz, &sfzr);CHKERRQ(ierr); lower.c = 0; /* initialize member, otherwise compiler issues warnings */ upper.c = 0; /* initialize member, otherwise compiler issues warnings */ /* Debug */ ierr = PetscPrintf(comm, "Patch %d: (%d, %d, %d)--(%d, %d, %d)\n", p, lower.i, lower.j, lower.k, upper.i, upper.j, upper.k);CHKERRQ(ierr); if (dmz) {ierr = DMView(dmz, PETSC_VIEWER_STDOUT_(commz));CHKERRQ(ierr);} ierr = PetscSFView(sfz, PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr); ierr = PetscSFView(sfzr, PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr); /* Scatter Xcoarse -> Xzoom */ if (dmz) {ierr = DMGetGlobalVector(dmz, &XZ);CHKERRQ(ierr);} if (XZ) {ierr = VecGetArray(XZ, &xzarray);CHKERRQ(ierr);} ierr = VecGetArray(XC, &xcarray);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sfz, MPIU_SCALAR, xcarray, xzarray);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sfz, MPIU_SCALAR, xcarray, xzarray);CHKERRQ(ierr); ierr = VecRestoreArray(XC, &xcarray);CHKERRQ(ierr); if (XZ) {ierr = VecRestoreArray(XZ, &xzarray);CHKERRQ(ierr);} #if 0 /* Interpolate Xzoom -> Xfine, note that this may be on subcomms */ ierr = DMRefine(dmz, MPI_COMM_NULL, &dmf);CHKERRQ(ierr); ierr = DMCreateInterpolation(dmz, dmf, &interpz, NULL);CHKERRQ(ierr); ierr = DMInterpolate(dmz, interpz, dmf);CHKERRQ(ierr); /* Smooth Xfine using two-step smoother, normal smoother plus Kaczmarz---moves back and forth from dmzoom to dmfine */ /* Compute residual Rfine */ /* Restrict Rfine to Rzoom_restricted */ #endif /* Scatter Rzoom_restricted -> Rcoarse_restricted */ if (XZ) {ierr = VecGetArray(XZ, &xzarray);CHKERRQ(ierr);} ierr = VecGetArray(XC, &xcarray);CHKERRQ(ierr); ierr = PetscSFReduceBegin(sfzr, MPIU_SCALAR, xzarray, xcarray, MPIU_SUM);CHKERRQ(ierr); ierr = PetscSFReduceEnd(sfzr, MPIU_SCALAR, xzarray, xcarray, MPIU_SUM);CHKERRQ(ierr); ierr = VecRestoreArray(XC, &xcarray);CHKERRQ(ierr); if (XZ) {ierr = VecRestoreArray(XZ, &xzarray);CHKERRQ(ierr);} if (dmz) {ierr = DMRestoreGlobalVector(dmz, &XZ);CHKERRQ(ierr);} /* Compute global residual Rcoarse */ /* TauCoarse = Rcoarse - Rcoarse_restricted */ ierr = PetscSFDestroy(&sfz);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfzr);CHKERRQ(ierr); ierr = DMDestroy(&dmz);CHKERRQ(ierr); } } } ierr = DMRestoreGlobalVector(dmc, &XC);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C EPSView - Prints the EPS data structure. Collective on EPS Input Parameters: + eps - the eigenproblem solver context - viewer - optional visualization context Options Database Key: . -eps_view - Calls EPSView() at end of EPSSolve() Note: The available visualization contexts include + PETSC_VIEWER_STDOUT_SELF - standard output (default) - PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first processor opens the file. All other processors send their data to the first processor to print. The user can open an alternative visualization context with PetscViewerASCIIOpen() - output to a specified file. Level: beginner .seealso: STView(), PetscViewerASCIIOpen() @*/ PetscErrorCode EPSView(EPS eps,PetscViewer viewer) { PetscErrorCode ierr; const char *type,*extr,*bal; char str[50]; PetscBool isascii,ispower,isexternal,istrivial; PetscFunctionBegin; PetscValidHeaderSpecific(eps,EPS_CLASSID,1); if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)eps)); PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(eps,1,viewer,2); #if defined(PETSC_USE_COMPLEX) #define HERM "hermitian" #else #define HERM "symmetric" #endif ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii); CHKERRQ(ierr); if (isascii) { ierr = PetscObjectPrintClassNamePrefixType((PetscObject)eps,viewer); CHKERRQ(ierr); if (eps->ops->view) { ierr = PetscViewerASCIIPushTab(viewer); CHKERRQ(ierr); ierr = (*eps->ops->view)(eps,viewer); CHKERRQ(ierr); ierr = PetscViewerASCIIPopTab(viewer); CHKERRQ(ierr); } if (eps->problem_type) { switch (eps->problem_type) { case EPS_HEP: type = HERM " eigenvalue problem"; break; case EPS_GHEP: type = "generalized " HERM " eigenvalue problem"; break; case EPS_NHEP: type = "non-" HERM " eigenvalue problem"; break; case EPS_GNHEP: type = "generalized non-" HERM " eigenvalue problem"; break; case EPS_PGNHEP: type = "generalized non-" HERM " eigenvalue problem with " HERM " positive definite B"; break; case EPS_GHIEP: type = "generalized " HERM "-indefinite eigenvalue problem"; break; default: SETERRQ(PetscObjectComm((PetscObject)eps),1,"Wrong value of eps->problem_type"); } } else type = "not yet set"; ierr = PetscViewerASCIIPrintf(viewer," problem type: %s\n",type); CHKERRQ(ierr); if (eps->extraction) { switch (eps->extraction) { case EPS_RITZ: extr = "Rayleigh-Ritz"; break; case EPS_HARMONIC: extr = "harmonic Ritz"; break; case EPS_HARMONIC_RELATIVE: extr = "relative harmonic Ritz"; break; case EPS_HARMONIC_RIGHT: extr = "right harmonic Ritz"; break; case EPS_HARMONIC_LARGEST: extr = "largest harmonic Ritz"; break; case EPS_REFINED: extr = "refined Ritz"; break; case EPS_REFINED_HARMONIC: extr = "refined harmonic Ritz"; break; default: SETERRQ(PetscObjectComm((PetscObject)eps),1,"Wrong value of eps->extraction"); } ierr = PetscViewerASCIIPrintf(viewer," extraction type: %s\n",extr); CHKERRQ(ierr); } if (!eps->ishermitian && eps->balance!=EPS_BALANCE_NONE) { switch (eps->balance) { case EPS_BALANCE_ONESIDE: bal = "one-sided Krylov"; break; case EPS_BALANCE_TWOSIDE: bal = "two-sided Krylov"; break; case EPS_BALANCE_USER: bal = "user-defined matrix"; break; default: SETERRQ(PetscObjectComm((PetscObject)eps),1,"Wrong value of eps->balance"); } ierr = PetscViewerASCIIPrintf(viewer," balancing enabled: %s",bal); CHKERRQ(ierr); if (eps->balance==EPS_BALANCE_ONESIDE || eps->balance==EPS_BALANCE_TWOSIDE) { ierr = PetscViewerASCIIPrintf(viewer,", with its=%D",eps->balance_its); CHKERRQ(ierr); } if (eps->balance==EPS_BALANCE_TWOSIDE && eps->balance_cutoff!=0.0) { ierr = PetscViewerASCIIPrintf(viewer," and cutoff=%g",(double)eps->balance_cutoff); CHKERRQ(ierr); } ierr = PetscViewerASCIIPrintf(viewer,"\n"); CHKERRQ(ierr); } ierr = PetscViewerASCIIPrintf(viewer," selected portion of the spectrum: "); CHKERRQ(ierr); ierr = SlepcSNPrintfScalar(str,50,eps->target,PETSC_FALSE); CHKERRQ(ierr); if (!eps->which) { ierr = PetscViewerASCIIPrintf(viewer,"not yet set\n"); CHKERRQ(ierr); } else switch (eps->which) { case EPS_WHICH_USER: ierr = PetscViewerASCIIPrintf(viewer,"user defined\n"); CHKERRQ(ierr); break; case EPS_TARGET_MAGNITUDE: ierr = PetscViewerASCIIPrintf(viewer,"closest to target: %s (in magnitude)\n",str); CHKERRQ(ierr); break; case EPS_TARGET_REAL: ierr = PetscViewerASCIIPrintf(viewer,"closest to target: %s (along the real axis)\n",str); CHKERRQ(ierr); break; case EPS_TARGET_IMAGINARY: ierr = PetscViewerASCIIPrintf(viewer,"closest to target: %s (along the imaginary axis)\n",str); CHKERRQ(ierr); break; case EPS_LARGEST_MAGNITUDE: ierr = PetscViewerASCIIPrintf(viewer,"largest eigenvalues in magnitude\n"); CHKERRQ(ierr); break; case EPS_SMALLEST_MAGNITUDE: ierr = PetscViewerASCIIPrintf(viewer,"smallest eigenvalues in magnitude\n"); CHKERRQ(ierr); break; case EPS_LARGEST_REAL: ierr = PetscViewerASCIIPrintf(viewer,"largest real parts\n"); CHKERRQ(ierr); break; case EPS_SMALLEST_REAL: ierr = PetscViewerASCIIPrintf(viewer,"smallest real parts\n"); CHKERRQ(ierr); break; case EPS_LARGEST_IMAGINARY: ierr = PetscViewerASCIIPrintf(viewer,"largest imaginary parts\n"); CHKERRQ(ierr); break; case EPS_SMALLEST_IMAGINARY: ierr = PetscViewerASCIIPrintf(viewer,"smallest imaginary parts\n"); CHKERRQ(ierr); break; case EPS_ALL: ierr = PetscViewerASCIIPrintf(viewer,"all eigenvalues in interval [%g,%g]\n",(double)eps->inta,(double)eps->intb); CHKERRQ(ierr); break; default: SETERRQ(PetscObjectComm((PetscObject)eps),1,"Wrong value of eps->which"); } if (eps->trueres) { ierr = PetscViewerASCIIPrintf(viewer," computing true residuals explicitly\n"); CHKERRQ(ierr); } if (eps->trackall) { ierr = PetscViewerASCIIPrintf(viewer," computing all residuals (for tracking convergence)\n"); CHKERRQ(ierr); } ierr = PetscViewerASCIIPrintf(viewer," number of eigenvalues (nev): %D\n",eps->nev); CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," number of column vectors (ncv): %D\n",eps->ncv); CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," maximum dimension of projected problem (mpd): %D\n",eps->mpd); CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," maximum number of iterations: %D\n",eps->max_it); CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," tolerance: %g\n",(double)eps->tol); CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," convergence test: "); CHKERRQ(ierr); switch (eps->conv) { case EPS_CONV_ABS: ierr = PetscViewerASCIIPrintf(viewer,"absolute\n"); CHKERRQ(ierr); break; case EPS_CONV_EIG: ierr = PetscViewerASCIIPrintf(viewer,"relative to the eigenvalue\n"); CHKERRQ(ierr); break; case EPS_CONV_NORM: ierr = PetscViewerASCIIPrintf(viewer,"relative to the eigenvalue and matrix norms\n"); CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," computed matrix norms: norm(A)=%g",(double)eps->nrma); CHKERRQ(ierr); if (eps->isgeneralized) { ierr = PetscViewerASCIIPrintf(viewer,", norm(B)=%g",(double)eps->nrmb); CHKERRQ(ierr); } ierr = PetscViewerASCIIPrintf(viewer,"\n"); CHKERRQ(ierr); break; case EPS_CONV_USER: ierr = PetscViewerASCIIPrintf(viewer,"user-defined\n"); CHKERRQ(ierr); break; } if (eps->nini) { ierr = PetscViewerASCIIPrintf(viewer," dimension of user-provided initial space: %D\n",PetscAbs(eps->nini)); CHKERRQ(ierr); } if (eps->nds) { ierr = PetscViewerASCIIPrintf(viewer," dimension of user-provided deflation space: %D\n",PetscAbs(eps->nds)); CHKERRQ(ierr); } } else { if (eps->ops->view) { ierr = (*eps->ops->view)(eps,viewer); CHKERRQ(ierr); } } ierr = PetscObjectTypeCompareAny((PetscObject)eps,&isexternal,EPSARPACK,EPSBLZPACK,EPSTRLAN,EPSBLOPEX,EPSPRIMME,""); CHKERRQ(ierr); if (!isexternal) { ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO); CHKERRQ(ierr); if (!eps->V) { ierr = EPSGetBV(eps,&eps->V); CHKERRQ(ierr); } ierr = BVView(eps->V,viewer); CHKERRQ(ierr); if (!eps->rg) { ierr = EPSGetRG(eps,&eps->rg); CHKERRQ(ierr); } ierr = RGIsTrivial(eps->rg,&istrivial); CHKERRQ(ierr); if (!istrivial) { ierr = RGView(eps->rg,viewer); CHKERRQ(ierr); } ierr = PetscObjectTypeCompare((PetscObject)eps,EPSPOWER,&ispower); CHKERRQ(ierr); if (!ispower) { if (!eps->ds) { ierr = EPSGetDS(eps,&eps->ds); CHKERRQ(ierr); } ierr = DSView(eps->ds,viewer); CHKERRQ(ierr); } ierr = PetscViewerPopFormat(viewer); CHKERRQ(ierr); } if (!eps->st) { ierr = EPSGetST(eps,&eps->st); CHKERRQ(ierr); } ierr = STView(eps->st,viewer); CHKERRQ(ierr); PetscFunctionReturn(0); }