xref: /petsc/src/binding/petsc4py/test/test_dmda.py (revision 7d766218e3bc62b9d20359dfd3a8f5ff55ad6b2a)
1from petsc4py import PETSc
2import unittest
3
4# --------------------------------------------------------------------
5
6
7class BaseTestDA:
8    COMM = PETSc.COMM_WORLD
9    SIZES = None
10    BOUNDARY = None
11    DOF = 1
12    STENCIL = PETSc.DMDA.StencilType.STAR
13    SWIDTH = 1
14
15    def setUp(self):
16        self.da = PETSc.DMDA().create(
17            dim=len(self.SIZES),
18            dof=self.DOF,
19            sizes=self.SIZES,
20            boundary_type=self.BOUNDARY,
21            stencil_type=self.STENCIL,
22            stencil_width=self.SWIDTH,
23            comm=self.COMM,
24        )
25
26    def tearDown(self):
27        self.da = None
28        PETSc.garbage_cleanup()
29
30    def testGetInfo(self):
31        dim = self.da.getDim()
32        dof = self.da.getDof()
33        sizes = self.da.getSizes()
34        boundary = self.da.getBoundaryType()
35        stencil_type = self.da.getStencilType()
36        stencil_width = self.da.getStencilWidth()
37        self.assertEqual(dim, len(self.SIZES))
38        self.assertEqual(dof, self.DOF)
39        self.assertEqual(sizes, tuple(self.SIZES))
40        self.assertEqual(boundary, self.BOUNDARY or (0,) * dim)
41        self.assertEqual(stencil_type, self.STENCIL)
42        self.assertEqual(stencil_width, self.SWIDTH)
43
44    def testRangesCorners(self):
45        dim = self.da.getDim()
46        ranges = self.da.getRanges()
47        starts, lsizes = self.da.getCorners()
48        self.assertEqual(dim, len(ranges))
49        self.assertEqual(dim, len(starts))
50        self.assertEqual(dim, len(lsizes))
51        for i in range(dim):
52            s, e = ranges[i]
53            self.assertEqual(s, starts[i])
54            self.assertEqual(e - s, lsizes[i])
55
56    def testGhostRangesCorners(self):
57        dim = self.da.getDim()
58        ranges = self.da.getGhostRanges()
59        starts, lsizes = self.da.getGhostCorners()
60        self.assertEqual(dim, len(ranges))
61        self.assertEqual(dim, len(starts))
62        self.assertEqual(dim, len(lsizes))
63        for i in range(dim):
64            s, e = ranges[i]
65            self.assertEqual(s, starts[i])
66            self.assertEqual(e - s, lsizes[i])
67
68    def testOwnershipRanges(self):
69        ownership_ranges = self.da.getOwnershipRanges()
70        procsizes = self.da.getProcSizes()
71        self.assertEqual(len(procsizes), len(ownership_ranges))
72        for i, m in enumerate(procsizes):
73            self.assertEqual(m, len(ownership_ranges[i]))
74
75    def testFieldName(self):
76        for i in range(self.da.getDof()):
77            self.da.setFieldName(i, 'field%d' % i)
78        for i in range(self.da.getDof()):
79            name = self.da.getFieldName(i)
80            self.assertEqual(name, 'field%d' % i)
81
82    def testCoordinates(self):
83        self.da.setUniformCoordinates(0, 1, 0, 1, 0, 1)
84        #
85        c = self.da.getCoordinates()
86        self.da.setCoordinates(c)
87        c.destroy()
88        cda = self.da.getCoordinateDM()
89        cda.destroy()
90        #
91        c = self.da.getCoordinates()
92        self.da.setCoordinates(c)
93        c.destroy()
94        gc = self.da.getCoordinatesLocal()
95        gc.destroy()
96
97    def testCreateVecMat(self):
98        vn = self.da.createNaturalVec()
99        vg = self.da.createGlobalVec()
100        vl = self.da.createLocalVec()
101        mat = self.da.createMat()
102        self.assertTrue(mat.getType() in ('aij', 'seqaij', 'mpiaij'))
103        vn.set(1.0)
104        self.da.naturalToGlobal(vn, vg)
105        self.assertEqual(vg.max()[1], 1.0)
106        self.assertEqual(vg.min()[1], 1.0)
107        self.da.globalToLocal(vg, vl)
108        self.assertEqual(vl.max()[1], 1.0)
109        self.assertTrue(vl.min()[1] in (1.0, 0.0))
110        vn.set(0.0)
111        self.da.globalToNatural(vg, vn)
112        self.assertEqual(vn.max()[1], 1.0)
113        self.assertEqual(vn.min()[1], 1.0)
114        vl2 = self.da.createLocalVec()
115        self.da.localToLocal(vl, vl2)
116        self.assertEqual(vl2.max()[1], 1.0)
117        self.assertTrue(vl2.min()[1] in (1.0, 0.0))
118        NONE = PETSc.DM.BoundaryType.NONE
119        btype = self.da.boundary_type
120        psize = self.da.proc_sizes
121        for b, p in zip(btype, psize):
122            if b != NONE and p == 1:
123                return
124        vg2 = self.da.createGlobalVec()
125        self.da.localToGlobal(vl2, vg2)
126
127    def testGetVec(self):
128        vg = self.da.getGlobalVec()
129        vl = self.da.getLocalVec()
130        try:
131            vg.set(1.0)
132            self.assertEqual(vg.max()[1], 1.0)
133            self.assertEqual(vg.min()[1], 1.0)
134            self.da.globalToLocal(vg, vl)
135            self.assertEqual(vl.max()[1], 1.0)
136            self.assertTrue(vl.min()[1] in (1.0, 0.0))
137            vl.set(2.0)
138            NONE = PETSc.DM.BoundaryType.NONE
139            btype = self.da.boundary_type
140            psize = self.da.proc_sizes
141            for b, p in zip(btype, psize):
142                if b != NONE and p == 1:
143                    return
144            self.da.localToGlobal(vl, vg)
145            self.assertEqual(vg.max()[1], 2.0)
146            self.assertTrue(vg.min()[1] in (2.0, 0.0))
147        finally:
148            self.da.restoreGlobalVec(vg)
149            self.da.restoreLocalVec(vl)
150            self.assertFalse(vg)
151            self.assertFalse(vl)
152
153        name = 'abcd'
154
155        vg = self.da.getGlobalVec(name)
156        vg.set(4.0)
157        self.da.restoreGlobalVec(vg, name)
158        self.assertFalse(vg)
159        vg = self.da.getGlobalVec()
160        vg.setRandom()
161        self.da.restoreGlobalVec(vg)
162        vg = self.da.getGlobalVec(name)
163        vg.shift(-4.0)
164        self.assertEqual(vg.max()[1], 0.0)
165        self.da.restoreGlobalVec(vg, name)
166
167        vl = self.da.getLocalVec(name)
168        vl.set(4.0)
169        self.da.restoreLocalVec(vl, name)
170        self.assertFalse(vl)
171        vl = self.da.getLocalVec()
172        vl.setRandom()
173        self.da.restoreLocalVec(vl)
174        vl = self.da.getLocalVec(name)
175        vl.shift(-4.0)
176        self.assertEqual(vl.max()[1], 0.0)
177        self.da.restoreLocalVec(vl, name)
178
179    def testGetOther(self):
180        _ = self.da.getAO()
181        _ = self.da.getLGMap()
182        _, _ = self.da.getScatter()
183
184    def testRefineCoarsen(self):
185        da = self.da
186        rda = da.refine()
187        self.assertEqual(da.getDim(), rda.getDim())
188        self.assertEqual(da.getDof(), rda.getDof())
189        if da.dim != 1:
190            self.assertEqual(da.getStencilType(), rda.getStencilType())
191        self.assertEqual(da.getStencilWidth(), rda.getStencilWidth())
192        cda = rda.coarsen()
193        self.assertEqual(rda.getDim(), cda.getDim())
194        self.assertEqual(rda.getDof(), cda.getDof())
195        for n1, n2 in zip(self.da.getSizes(), cda.getSizes()):
196            self.assertTrue(abs(n1 - n2) <= 1)
197
198    def testCoarsenRefine(self):
199        if PETSc.COMM_WORLD.getSize() > 6:
200            return
201        da = self.da
202        cda = self.da.coarsen()
203        self.assertEqual(da.getDim(), cda.getDim())
204        self.assertEqual(da.getDof(), cda.getDof())
205        if da.dim != 1:
206            self.assertEqual(da.getStencilType(), cda.getStencilType())
207        self.assertEqual(da.getStencilWidth(), cda.getStencilWidth())
208        rda = cda.refine()
209        for n1, n2 in zip(self.da.getSizes(), rda.getSizes()):
210            self.assertTrue(abs(n1 - n2) <= 1)
211
212    def testRefineHierarchy(self):
213        levels = self.da.refineHierarchy(2)
214        self.assertTrue(isinstance(levels, list))
215        self.assertEqual(len(levels), 2)
216        for item in levels:
217            self.assertTrue(isinstance(item, PETSc.DM))
218
219    def testCoarsenHierarchy(self):
220        if PETSc.COMM_WORLD.getSize() > 6:
221            return
222        levels = self.da.coarsenHierarchy(2)
223        self.assertTrue(isinstance(levels, list))
224        self.assertEqual(len(levels), 2)
225        for item in levels:
226            self.assertTrue(isinstance(item, PETSc.DM))
227
228    def testCreateInterpolation(self):
229        da = self.da
230        if da.dim == 1:
231            return
232        rda = da.refine()
233        _, _ = da.createInterpolation(rda)
234
235    def testCreateInjection(self):
236        if PETSc.COMM_WORLD.getSize() > 6:
237            return
238        da = self.da
239        if da.dim == 1:
240            return
241        rda = da.refine()
242        _ = da.createInjection(rda)
243
244    def testzeroRowsColumnsStencil(self):
245        da = self.da
246        A = da.createMatrix()
247        x = da.createGlobalVector()
248        x.set(2.0)
249        A.setDiagonal(x)
250        diag1 = x.duplicate()
251        A.getDiagonal(diag1)
252        if self.SIZES != 2:  # only coded test for 2D case
253            return
254        istart, iend, jstart, jend = da.getRanges()
255        self.assertTrue(x.equal(diag1))
256        zeroidx = []
257        for i in range(istart, iend):
258            for j in range(jstart, jend):
259                row = PETSc.Mat.Stencil()
260                row.index = (i, j)
261                zeroidx = zeroidx + [row]
262        diag2 = x.duplicate()
263        diag2.set(1.0)
264        A.zeroRowsColumnsStencil(zeroidx, 1.0, x, diag2)
265        ans = x.duplicate()
266        ans.set(2.0)
267        self.assertTrue(ans.equal(diag2))
268
269
270MIRROR = PETSc.DMDA.BoundaryType.MIRROR
271GHOSTED = PETSc.DMDA.BoundaryType.GHOSTED
272PERIODIC = PETSc.DMDA.BoundaryType.PERIODIC
273TWIST = PETSc.DMDA.BoundaryType.TWIST
274
275SCALE = 4
276
277
278class BaseTestDA_1D(BaseTestDA):
279    SIZES = [100 * SCALE]
280
281
282class BaseTestDA_2D(BaseTestDA):
283    SIZES = [9 * SCALE, 11 * SCALE]
284
285
286class BaseTestDA_3D(BaseTestDA):
287    SIZES = [6 * SCALE, 7 * SCALE, 8 * SCALE]
288
289
290# --------------------------------------------------------------------
291
292
293class TestDA_1D(BaseTestDA_1D, unittest.TestCase):
294    pass
295
296
297class TestDA_1D_W0(TestDA_1D):
298    SWIDTH = 0
299
300
301class TestDA_1D_W2(TestDA_1D):
302    SWIDTH = 2
303
304
305class TestDA_2D(BaseTestDA_2D, unittest.TestCase):
306    pass
307
308
309class TestDA_2D_W0(TestDA_2D):
310    SWIDTH = 0
311
312
313class TestDA_2D_W0_N2(TestDA_2D):
314    DOF = 2
315    SWIDTH = 0
316
317
318class TestDA_2D_W2(TestDA_2D):
319    SWIDTH = 2
320
321
322class TestDA_2D_W2_N2(TestDA_2D):
323    DOF = 2
324    SWIDTH = 2
325
326
327class TestDA_2D_PXY(TestDA_2D):
328    SIZES = [13 * SCALE, 17 * SCALE]
329    DOF = 2
330    SWIDTH = 5
331    BOUNDARY = (PERIODIC,) * 2
332
333
334class TestDA_2D_GXY(TestDA_2D):
335    SIZES = [13 * SCALE, 17 * SCALE]
336    DOF = 2
337    SWIDTH = 5
338    BOUNDARY = (GHOSTED,) * 2
339
340
341class TestDA_2D_TXY(TestDA_2D):
342    SIZES = [13 * SCALE, 17 * SCALE]
343    DOF = 2
344    SWIDTH = 5
345    BOUNDARY = (TWIST,) * 2
346
347
348class TestDA_3D(BaseTestDA_3D, unittest.TestCase):
349    pass
350
351
352class TestDA_3D_W0(TestDA_3D):
353    SWIDTH = 0
354
355
356class TestDA_3D_W0_N2(TestDA_3D):
357    DOF = 2
358    SWIDTH = 0
359
360
361class TestDA_3D_W2(TestDA_3D):
362    SWIDTH = 2
363
364
365class TestDA_3D_W2_N2(TestDA_3D):
366    DOF = 2
367    SWIDTH = 2
368
369
370class TestDA_3D_PXYZ(TestDA_3D):
371    SIZES = [11 * SCALE, 13 * SCALE, 17 * SCALE]
372    DOF = 2
373    SWIDTH = 3
374    BOUNDARY = (PERIODIC,) * 3
375
376
377class TestDA_3D_GXYZ(TestDA_3D):
378    SIZES = [11 * SCALE, 13 * SCALE, 17 * SCALE]
379    DOF = 2
380    SWIDTH = 3
381    BOUNDARY = (GHOSTED,) * 3
382
383
384class TestDA_3D_TXYZ(TestDA_3D):
385    SIZES = [11 * SCALE, 13 * SCALE, 17 * SCALE]
386    DOF = 2
387    SWIDTH = 3
388    BOUNDARY = (TWIST,) * 3
389
390
391# --------------------------------------------------------------------
392
393DIM = (
394    1,
395    2,
396    3,
397)
398DOF = (
399    None,
400    1,
401    2,
402    3,
403    4,
404    5,
405)
406BOUNDARY_TYPE = (
407    None,
408    'none',
409    (0,) * 3,
410    0,
411    'ghosted',
412    (GHOSTED,) * 3,
413    GHOSTED,
414    'periodic',
415    (PERIODIC,) * 3,
416    PERIODIC,
417    'twist',
418    (TWIST,) * 3,
419    TWIST,
420)
421STENCIL_TYPE = (None, 'star', 'box')
422STENCIL_WIDTH = (None, 0, 1, 2, 3)
423
424
425DIM = (1, 2, 3)
426DOF = (None, 2, 5)
427BOUNDARY_TYPE = (None, 'none', 'periodic', 'ghosted', 'twist')
428STENCIL_TYPE = (None, 'box')
429STENCIL_WIDTH = (None, 1, 2)
430
431
432class TestDACreate(unittest.TestCase):
433    pass
434
435
436counter = 0
437for dim in DIM:
438    for dof in DOF:
439        for boundary in BOUNDARY_TYPE:
440            if isinstance(boundary, tuple):
441                boundary = boundary[:dim]
442            for stencil in STENCIL_TYPE:
443                for width in STENCIL_WIDTH:
444                    kargs = {
445                        'sizes': [8 * SCALE] * dim,
446                        'dim': dim,
447                        'dof': dof,
448                        'boundary_type': boundary,
449                        'stencil_type': stencil,
450                        'stencil_width': width,
451                    }
452
453                    def testCreate(self, kargs=kargs):
454                        kargs = dict(kargs)
455                        da = PETSc.DMDA().create(**kargs)
456                        da.destroy()
457
458                    setattr(TestDACreate, 'testCreate%04d' % counter, testCreate)
459                    del testCreate, kargs
460                    counter += 1
461del counter, dim, dof, boundary, stencil, width
462
463
464class TestDADuplicate(unittest.TestCase):
465    pass
466
467
468counter = 0
469for dim in DIM:
470    for dof in DOF:
471        for boundary in BOUNDARY_TYPE:
472            if isinstance(boundary, tuple):
473                boundary = boundary[:dim]
474            for stencil in STENCIL_TYPE:
475                for width in STENCIL_WIDTH:
476                    kargs = {
477                        'dim': dim,
478                        'dof': dof,
479                        'boundary_type': boundary,
480                        'stencil_type': stencil,
481                        'stencil_width': width,
482                    }
483
484                    def testDuplicate(self, kargs=kargs):
485                        kargs = dict(kargs)
486                        dim = kargs.pop('dim')
487                        dof = kargs['dof']
488                        boundary = kargs['boundary_type']
489                        stencil = kargs['stencil_type']
490                        width = kargs['stencil_width']
491                        da = PETSc.DMDA().create([8 * SCALE] * dim)
492                        newda = da.duplicate(**kargs)
493                        self.assertEqual(newda.dim, da.dim)
494                        self.assertEqual(newda.sizes, da.sizes)
495                        self.assertEqual(newda.proc_sizes, da.proc_sizes)
496                        self.assertEqual(newda.ranges, da.ranges)
497                        self.assertEqual(newda.corners, da.corners)
498                        if (
499                            newda.boundary_type == da.boundary_type
500                            and newda.stencil_width == da.stencil_width
501                        ):
502                            self.assertEqual(newda.ghost_ranges, da.ghost_ranges)
503                            self.assertEqual(newda.ghost_corners, da.ghost_corners)
504                        if dof is None:
505                            dof = da.dof
506                        if boundary is None:
507                            boundary = da.boundary_type
508                        elif boundary == 'none':
509                            boundary = (0,) * dim
510                        elif boundary == 'mirror':
511                            boundary = (MIRROR,) * dim
512                        elif boundary == 'ghosted':
513                            boundary = (GHOSTED,) * dim
514                        elif boundary == 'periodic':
515                            boundary = (PERIODIC,) * dim
516                        elif boundary == 'twist':
517                            boundary = (TWIST,) * dim
518                        elif isinstance(boundary, int):
519                            boundary = (boundary,) * dim
520                        if stencil is None:
521                            stencil = da.stencil[0]
522                        if width is None:
523                            width = da.stencil_width
524                        self.assertEqual(newda.dof, dof)
525                        self.assertEqual(newda.boundary_type, boundary)
526                        if dim == 1:
527                            self.assertEqual(newda.stencil, (stencil, width))
528                        newda.destroy()
529                        da.destroy()
530
531                    setattr(
532                        TestDADuplicate, 'testDuplicate%04d' % counter, testDuplicate
533                    )
534                    del testDuplicate, kargs
535                    counter += 1
536del counter, dim, dof, boundary, stencil, width
537
538# --------------------------------------------------------------------
539
540if PETSc.COMM_WORLD.getSize() > 1:
541    del TestDA_1D_W0
542    del TestDA_2D_W0, TestDA_2D_W0_N2
543    del TestDA_3D_W0, TestDA_3D_W0_N2
544
545# --------------------------------------------------------------------
546
547if __name__ == '__main__':
548    unittest.main()
549
550# --------------------------------------------------------------------
551