PETSC_EXTERN void PETSC_STDCALL pcmggetgalerkin_(PC pc,PetscBool *galerkin, int *__ierr ){ *__ierr = PCMGGetGalerkin( (PC)PetscToPointer((pc) ),galerkin); }
PetscErrorCode efs_setup(efs *slv, int offset[], int stride[]) { PetscErrorCode ierr; PetscInt xs, ys, zs, xm, ym, zm; PCType pc_type; if (efs_log(slv, EFS_LOG_STATUS)) { ierr = ef_io_print(slv->comm, "Setting up electric field solver");CHKERRQ(ierr); } slv->ts = 0; if (efs_log(slv, EFS_LOG_RESIDUAL)) { ierr = PetscOptionsSetValue("-ksp_monitor_short", NULL);CHKERRQ(ierr); } ierr = DMDASetFieldName(slv->dm, 0,"potential");CHKERRQ(ierr); if (slv->grid.nd == 2) { ierr = DMDAGetCorners(slv->dm, &xs, &ys, 0, &xm, &ym, 0);CHKERRQ(ierr); slv->dmap = ef_dmap_create_2d(xs - offset[0], ys - offset[1], xm, ym, stride); } else if (slv->grid.nd == 3) { ierr = DMDAGetCorners(slv->dm, &xs, &ys, &zs, &xm, &ym, &zm);CHKERRQ(ierr); slv->dmap = ef_dmap_create_3d(xs - offset[0], ys - offset[1], zs - offset[2], xm, ym, zm, stride); } else { SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Unsupported dimmension: %d", slv->grid.nd); } ierr = ef_callback_create(&slv->callback);CHKERRQ(ierr); ierr = KSPCreate(slv->comm, &slv->ksp);CHKERRQ(ierr); if (efs_log(slv, EFS_LOG_EIGS)) { ierr = KSPSetComputeEigenvalues(slv->ksp, PETSC_TRUE);CHKERRQ(ierr); } ierr = KSPSetDM(slv->ksp, slv->dm);CHKERRQ(ierr); ierr = KSPGetPC(slv->ksp, &slv->pc);CHKERRQ(ierr); ierr = PCSetType(slv->pc, PCMG);CHKERRQ(ierr); if (slv->options.galerkin) { ierr = PCMGSetGalerkin(slv->pc, PETSC_TRUE);CHKERRQ(ierr); } else { ierr = PCMGSetGalerkin(slv->pc, PETSC_FALSE);CHKERRQ(ierr); } ierr = KSPSetComputeOperators(slv->ksp, slv->callback->matrix, slv);CHKERRQ(ierr); ierr = KSPSetComputeRHS(slv->ksp, slv->callback->rhs, slv);CHKERRQ(ierr); ierr = KSPSetComputeInitialGuess(slv->ksp, slv->callback->guess, slv);CHKERRQ(ierr); ierr = KSPSetFromOptions(slv->ksp);CHKERRQ(ierr); ierr = PCGetType(slv->pc, &pc_type);CHKERRQ(ierr); ierr = PCMGGetLevels(slv->pc, &slv->options.levels);CHKERRQ(ierr); if (slv->options.levels < 1) slv->options.levels++; ierr = PCMGGetGalerkin(slv->pc, &slv->options.galerkin);CHKERRQ(ierr); if (strcmp(pc_type, PCGAMG) == 0 || strcmp(pc_type, PCHYPRE) == 0) slv->options.galerkin = 1; if (!slv->options.galerkin) { slv->levels = (ef_level*) malloc(slv->options.levels*sizeof(ef_level)); // setup callback for transforming rhs on coarse levels } else { slv->levels = (ef_level*) malloc(sizeof(ef_level)); } ierr = ef_fd_create(&slv->fd, EF_FD_STANDARD_O2);CHKERRQ(ierr); ierr = ef_operator_create(&slv->op, slv->levels, slv->fd, slv->grid.nd);CHKERRQ(ierr); ierr = ef_boundary_create(&slv->boundary, slv->levels, slv->options.levels, slv->dmap, &slv->state, slv->fd);CHKERRQ(ierr); slv->op->axisymmetric = slv->options.axisymmetric; slv->boundary->axisymmetric = slv->options.axisymmetric; ierr = DMSetMatType(slv->dm, MATAIJ);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slv->dm, &slv->levels[0].eps);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slv->dm, &slv->levels[0].g);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slv->dm, &slv->levels[0].ag);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slv->dm, &slv->levels[0].gcomp);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slv->dm, &slv->levels[0].scale);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slv->dm, &slv->levels[0].nscale);CHKERRQ(ierr); ierr = VecSet(slv->levels[0].g, 0);CHKERRQ(ierr); ierr = VecSet(slv->levels[0].gcomp, 1);CHKERRQ(ierr); ierr = VecSet(slv->levels[0].scale, 1);CHKERRQ(ierr); ierr = VecSet(slv->levels[0].nscale, 1);CHKERRQ(ierr); ierr = DMCoarsenHookAdd(slv->dm, slv->callback->coarsen, slv->callback->restrct, slv);CHKERRQ(ierr); return 0; }
/*@C DMMGSetKSP - Sets the linear solver object that will use the grid hierarchy Collective on DMMG Input Parameter: + dmmg - the context . func - function to compute linear system matrix on each grid level - rhs - function to compute right hand side on each level (need only work on the finest grid if you do not use grid sequencing) Level: advanced Notes: For linear problems my be called more than once, reevaluates the matrices if it is called more than once. Call DMMGSolve() directly several times to solve with the same matrix but different right hand sides. .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), DMMGSetMatType() @*/ PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetKSP(DMMG *dmmg,PetscErrorCode (*rhs)(DMMG,Vec),PetscErrorCode (*func)(DMMG,Mat,Mat)) { PetscErrorCode ierr; PetscInt i,nlevels = dmmg[0]->nlevels,level; PetscTruth ismg,galerkin=PETSC_FALSE; PC pc; KSP lksp; PetscFunctionBegin; if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG"); if (!dmmg[0]->ksp) { /* create solvers for each level if they don't already exist*/ for (i=0; i<nlevels; i++) { ierr = KSPCreate(dmmg[i]->comm,&dmmg[i]->ksp);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)dmmg[i]->ksp,PETSC_NULL,nlevels-i);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(dmmg[i]->ksp,dmmg[i]->prefix);CHKERRQ(ierr); ierr = DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);CHKERRQ(ierr); ierr = KSPSetFromOptions(dmmg[i]->ksp);CHKERRQ(ierr); /* if the multigrid is being run with Galerkin then these matrices do not need to be created except on the finest level we do not take advantage of this because it may be that Galerkin has not yet been selected for the KSP object These are also used if grid sequencing is selected for the linear problem. We should probably turn off grid sequencing for the linear problem */ if (!dmmg[i]->B) { ierr = DMGetMatrix(dmmg[i]->dm,dmmg[nlevels-1]->mtype,&dmmg[i]->B);CHKERRQ(ierr); } if (!dmmg[i]->J) { dmmg[i]->J = dmmg[i]->B; ierr = PetscObjectReference((PetscObject) dmmg[i]->J);CHKERRQ(ierr); } dmmg[i]->solve = DMMGSolveKSP; dmmg[i]->rhs = rhs; } } /* evalute matrix on each level */ ierr = KSPGetPC(dmmg[nlevels-1]->ksp,&pc);CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)pc,PCMG,&ismg);CHKERRQ(ierr); if (ismg) { ierr = PCMGGetGalerkin(pc,&galerkin);CHKERRQ(ierr); } if (func) { if (galerkin) { ierr = (*func)(dmmg[nlevels-1],dmmg[nlevels-1]->J,dmmg[nlevels-1]->B);CHKERRQ(ierr); } else { for (i=0; i<nlevels; i++) { ierr = (*func)(dmmg[i],dmmg[i]->J,dmmg[i]->B);CHKERRQ(ierr); } } } for (i=0; i<nlevels-1; i++) { ierr = KSPSetOptionsPrefix(dmmg[i]->ksp,"dmmg_");CHKERRQ(ierr); } for (level=0; level<nlevels; level++) { ierr = KSPSetOperators(dmmg[level]->ksp,dmmg[level]->J,dmmg[level]->B,SAME_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPGetPC(dmmg[level]->ksp,&pc);CHKERRQ(ierr); if (ismg) { for (i=0; i<=level; i++) { ierr = PCMGGetSmoother(pc,i,&lksp);CHKERRQ(ierr); ierr = KSPSetOperators(lksp,dmmg[i]->J,dmmg[i]->B,SAME_NONZERO_PATTERN);CHKERRQ(ierr); } } } PetscFunctionReturn(0); }