diff --git a/cscs-checks/libraries/petsc/petsc_helloworld.py b/cscs-checks/libraries/petsc/petsc_helloworld.py index 8c427d4369..facad67730 100644 --- a/cscs-checks/libraries/petsc/petsc_helloworld.py +++ b/cscs-checks/libraries/petsc/petsc_helloworld.py @@ -1,24 +1,13 @@ -import filecmp -import os +import reframe as rfm import reframe.utility.sanity as sn -from reframe.core.pipeline import RegressionTest - -@sn.sanity_function -def sanity_filecmp(output, reference): - return sn.assert_true( - filecmp.cmp(output, reference, shallow=False), - msg="files are not the same: `%s', `%s'" % (output, reference) - ) - - -class PetscPoisson2DCheck(RegressionTest): - def __init__(self, variant, **kwargs): - super().__init__('petsc_2dpoisson_%s' % variant, - os.path.dirname(__file__), **kwargs) +@rfm.parameterized_test(['dynamic'], ['static']) +class PetscPoisson2DCheck(rfm.RegressionTest): + def __init__(self, variant): + super().__init__() self.descr = ('Compile/run PETSc 2D Poisson example with cray-petsc ' - '(%s linking case)') % variant + '(%s linking)') % variant self.valid_systems = ['daint:gpu', 'daint:mc', 'dom:gpu', 'dom:mc'] self.valid_prog_environs = ['PrgEnv-cray', 'PrgEnv-gnu', @@ -27,22 +16,16 @@ def __init__(self, variant, **kwargs): self.modules = ['cray-petsc'] self.num_tasks = 16 self.num_tasks_per_node = 8 - self.dynamic = True if variant == 'dynamic' else False - self.executable_opts = ['-da_grid_x 4', '-da_grid_y 4', '-mat_view', - '> petsc_poisson2d.out'] + self.build_system = 'SingleSource' + if variant == 'dynamic': + self.build_system.cflags = ['-dynamic'] - self.maintainers = ['WS', 'AJ'] - self.tags = {'production'} + self.executable_opts = ['-da_grid_x 4', '-da_grid_y 4', '-ksp_monitor'] - self.sanity_patterns = sanity_filecmp( - 'petsc_poisson2d.out', 'petsc_poisson2d.ref') + # Check the final residual norm for convergence + norm = sn.extractsingle(r'\s+\d+\s+KSP Residual norm\s+(?P\S+)', + self.stdout, 'norm', float, -1) + self.sanity_patterns = sn.assert_lt(norm, 1.0e-5) - def compile(self): - if self.dynamic: - self.current_environ.cxxflags = '-dynamic' - super().compile() - - -def _get_checks(**kwargs): - return [PetscPoisson2DCheck('dynamic', **kwargs), - PetscPoisson2DCheck('static', **kwargs)] + self.tags = {'production'} + self.maintainers = ['WS', 'AJ', 'TM'] diff --git a/cscs-checks/libraries/petsc/src/petsc_poisson2d.ref b/cscs-checks/libraries/petsc/src/petsc_poisson2d.ref deleted file mode 100644 index d51ffe0fe6..0000000000 --- a/cscs-checks/libraries/petsc/src/petsc_poisson2d.ref +++ /dev/null @@ -1,36 +0,0 @@ -Mat Object: 16 MPI processes - type: mpiaij -row 0: (0, 0.) (1, 0.) (4, 0.) -row 1: (0, 0.) (1, 0.) (2, 0.) (5, 0.) -row 2: (1, 0.) (2, 0.) (3, 0.) (6, 0.) -row 3: (2, 0.) (3, 0.) (7, 0.) -row 4: (0, 0.) (4, 0.) (5, 0.) (8, 0.) -row 5: (1, 0.) (4, 0.) (5, 0.) (6, 0.) (9, 0.) -row 6: (2, 0.) (5, 0.) (6, 0.) (7, 0.) (10, 0.) -row 7: (3, 0.) (6, 0.) (7, 0.) (11, 0.) -row 8: (4, 0.) (8, 0.) (9, 0.) (12, 0.) -row 9: (5, 0.) (8, 0.) (9, 0.) (10, 0.) (13, 0.) -row 10: (6, 0.) (9, 0.) (10, 0.) (11, 0.) (14, 0.) -row 11: (7, 0.) (10, 0.) (11, 0.) (15, 0.) -row 12: (8, 0.) (12, 0.) (13, 0.) -row 13: (9, 0.) (12, 0.) (13, 0.) (14, 0.) -row 14: (10, 0.) (13, 0.) (14, 0.) (15, 0.) -row 15: (11, 0.) (14, 0.) (15, 0.) -Mat Object: 16 MPI processes - type: mpiaij -row 0: (0, 2.) (1, -1.) (4, -1.) -row 1: (0, -1.) (1, 3.) (2, -1.) (5, -1.) -row 2: (1, -1.) (2, 3.) (3, -1.) (6, -1.) -row 3: (2, -1.) (3, 2.) (7, -1.) -row 4: (0, -1.) (4, 3.) (5, -1.) (8, -1.) -row 5: (1, -1.) (4, -1.) (5, 4.) (6, -1.) (9, -1.) -row 6: (2, -1.) (5, -1.) (6, 4.) (7, -1.) (10, -1.) -row 7: (3, -1.) (6, -1.) (7, 3.) (11, -1.) -row 8: (4, -1.) (8, 3.) (9, -1.) (12, -1.) -row 9: (5, -1.) (8, -1.) (9, 4.) (10, -1.) (13, -1.) -row 10: (6, -1.) (9, -1.) (10, 4.) (11, -1.) (14, -1.) -row 11: (7, -1.) (10, -1.) (11, 3.) (15, -1.) -row 12: (8, -1.) (12, 2.) (13, -1.) -row 13: (9, -1.) (12, -1.) (13, 3.) (14, -1.) -row 14: (10, -1.) (13, -1.) (14, 3.) (15, -1.) -row 15: (11, -1.) (14, -1.) (15, 2.) diff --git a/cscs-checks/libraries/petsc/src/poisson2d.c b/cscs-checks/libraries/petsc/src/poisson2d.c index 51d5f54a5a..d58415d508 100644 --- a/cscs-checks/libraries/petsc/src/poisson2d.c +++ b/cscs-checks/libraries/petsc/src/poisson2d.c @@ -11,11 +11,13 @@ Contributed by Michael Boghosian , 2008, based on petsc/src/ksp/ksp/examples/tutorials/ex29.c and ex32.c + Compare to ex66.c + Example of Usage: ./ex50 -da_grid_x 3 -da_grid_y 3 -pc_type mg -da_refine 3 -ksp_monitor -ksp_view -dm_view draw -draw_pause -1 ./ex50 -da_grid_x 100 -da_grid_y 100 -pc_type mg -pc_mg_levels 1 -mg_levels_0_pc_type ilu -mg_levels_0_pc_factor_levels 1 -ksp_monitor -ksp_view ./ex50 -da_grid_x 100 -da_grid_y 100 -pc_type mg -pc_mg_levels 1 -mg_levels_0_pc_type lu -mg_levels_0_pc_factor_shift_type NONZERO -ksp_monitor - mpiexec -n 4 ./ex50 -da_grid_x 3 -da_grid_y 3 -pc_type mg -da_refine 10 -ksp_monitor -ksp_view -log_summary + mpiexec -n 4 ./ex50 -da_grid_x 3 -da_grid_y 3 -pc_type mg -da_refine 10 -ksp_monitor -ksp_view -log_view */ static char help[] = "Solves 2D Poisson equation using multigrid.\n\n"; @@ -28,37 +30,28 @@ static char help[] = "Solves 2D Poisson equation using multigrid.\n\n"; extern PetscErrorCode ComputeJacobian(KSP,Mat,Mat,void*); extern PetscErrorCode ComputeRHS(KSP,Vec,void*); -extern PetscErrorCode ComputeTrueSolution(DM, Vec); -extern PetscErrorCode VecView_VTK(Vec, const char [], const char []); - -typedef enum {DIRICHLET, NEUMANN} BCType; typedef struct { PetscScalar uu, tt; - BCType bcType; } UserContext; -#undef __FUNCT__ -#define __FUNCT__ "main" int main(int argc,char **argv) { KSP ksp; DM da; UserContext user; - PetscInt bc; PetscErrorCode ierr; - PetscInitialize(&argc,&argv,(char*)0,help); + ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); - ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,-11,-11,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da);CHKERRQ(ierr); - ierr = KSPSetDM(ksp,(DM)da); + ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,11,11,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da);CHKERRQ(ierr); + ierr = DMSetFromOptions(da);CHKERRQ(ierr); + ierr = DMSetUp(da);CHKERRQ(ierr); + ierr = KSPSetDM(ksp,(DM)da);CHKERRQ(ierr); ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); user.uu = 1.0; user.tt = 1.0; - bc = (PetscInt)NEUMANN; /* Use Neumann Boundary Conditions */ - user.bcType = (BCType)bc; - ierr = KSPSetComputeRHS(ksp,ComputeRHS,&user);CHKERRQ(ierr); ierr = KSPSetComputeOperators(ksp,ComputeJacobian,&user);CHKERRQ(ierr); @@ -67,12 +60,10 @@ int main(int argc,char **argv) ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); - ierr = PetscFinalize();CHKERRQ(ierr); - return 0; + ierr = PetscFinalize(); + return ierr; } -#undef __FUNCT__ -#define __FUNCT__ "ComputeRHS" PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { UserContext *user = (UserContext*)ctx; @@ -81,6 +72,7 @@ PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) PetscScalar Hx,Hy,pi,uu,tt; PetscScalar **array; DM da; + MatNullSpace nullspace; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); @@ -91,7 +83,6 @@ PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) Hy = 1.0/(PetscReal)(N); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); /* Fine grid */ - /* printf(" M N: %d %d; xm ym: %d %d; xs ys: %d %d\n",M,N,xm,ym,xs,ys); */ ierr = DMDAVecGetArray(da, b, &array);CHKERRQ(ierr); for (j=ys; jbcType == NEUMANN) { - MatNullSpace nullspace; - - ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); - ierr = MatNullSpaceRemove(nullspace,b);CHKERRQ(ierr); - ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); - } + ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); + ierr = MatNullSpaceRemove(nullspace,b);CHKERRQ(ierr); + ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); PetscFunctionReturn(0); } -#undef __FUNCT__ -#define __FUNCT__ "ComputeJacobian" PetscErrorCode ComputeJacobian(KSP ksp,Mat J, Mat jac,void *ctx) { - UserContext *user = (UserContext*)ctx; PetscErrorCode ierr; PetscInt i, j, M, N, xm, ym, xs, ys, num, numi, numj; PetscScalar v[5], Hx, Hy, HydHx, HxdHy; MatStencil row, col[5]; DM da; + MatNullSpace nullspace; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); @@ -138,29 +123,26 @@ PetscErrorCode ComputeJacobian(KSP ksp,Mat J, Mat jac,void *ctx) row.i = i; row.j = j; if (i==0 || j==0 || i==M-1 || j==N-1) { - if (user->bcType == DIRICHLET) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Dirichlet boundary conditions not supported !\n"); - else if (user->bcType == NEUMANN) { - num=0; numi=0; numj=0; - if (j!=0) { - v[num] = -HxdHy; col[num].i = i; col[num].j = j-1; - num++; numj++; - } - if (i!=0) { - v[num] = -HydHx; col[num].i = i-1; col[num].j = j; - num++; numi++; - } - if (i!=M-1) { - v[num] = -HydHx; col[num].i = i+1; col[num].j = j; - num++; numi++; - } - if (j!=N-1) { - v[num] = -HxdHy; col[num].i = i; col[num].j = j+1; - num++; numj++; - } - v[num] = ((PetscReal)(numj)*HxdHy + (PetscReal)(numi)*HydHx); col[num].i = i; col[num].j = j; - num++; - ierr = MatSetValuesStencil(jac,1,&row,num,col,v,INSERT_VALUES);CHKERRQ(ierr); + num=0; numi=0; numj=0; + if (j!=0) { + v[num] = -HxdHy; col[num].i = i; col[num].j = j-1; + num++; numj++; + } + if (i!=0) { + v[num] = -HydHx; col[num].i = i-1; col[num].j = j; + num++; numi++; + } + if (i!=M-1) { + v[num] = -HydHx; col[num].i = i+1; col[num].j = j; + num++; numi++; + } + if (j!=N-1) { + v[num] = -HxdHy; col[num].i = i; col[num].j = j+1; + num++; numj++; } + v[num] = ((PetscReal)(numj)*HxdHy + (PetscReal)(numi)*HydHx); col[num].i = i; col[num].j = j; + num++; + ierr = MatSetValuesStencil(jac,1,&row,num,col,v,INSERT_VALUES);CHKERRQ(ierr); } else { v[0] = -HxdHy; col[0].i = i; col[0].j = j-1; v[1] = -HydHx; col[1].i = i-1; col[1].j = j; @@ -173,13 +155,31 @@ PetscErrorCode ComputeJacobian(KSP ksp,Mat J, Mat jac,void *ctx) } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); - if (user->bcType == NEUMANN) { - MatNullSpace nullspace; - ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); - ierr = MatSetNullSpace(jac,nullspace);CHKERRQ(ierr); - ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); - } + ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); + ierr = MatSetNullSpace(J,nullspace);CHKERRQ(ierr); + ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); PetscFunctionReturn(0); } + + +/*TEST + + build: + requires: !complex !single + + test: + args: -pc_type mg -pc_mg_type full -ksp_type cg -ksp_monitor_short -da_refine 3 -mg_coarse_pc_type svd -ksp_view + + test: + suffix: 2 + nsize: 4 + args: -pc_type mg -pc_mg_type full -ksp_type cg -ksp_monitor_short -da_refine 3 -mg_coarse_pc_type redundant -mg_coarse_redundant_pc_type svd -ksp_view + + test: + suffix: 3 + nsize: 2 + args: -pc_type mg -pc_mg_type full -ksp_monitor_short -da_refine 5 -mg_coarse_ksp_type cg -mg_coarse_ksp_converged_reason -mg_coarse_ksp_rtol 1e-2 -mg_coarse_ksp_max_it 5 -mg_coarse_pc_type none -pc_mg_levels 2 -ksp_type pipefgmres -ksp_pipefgmres_shift 1.5 + +TEST*/