xref: /petsc/src/binding/petsc4py/test/test_dmplex.py (revision 55a74a43bb44613d95e937906bec3b8c3581b432)
1728cfed7Sksagiyamimport petsc4py
25808f684SSatish Balayfrom petsc4py import PETSc
35808f684SSatish Balayimport unittest
4728cfed7Sksagiyamimport os
5728cfed7Sksagiyamimport filecmp
65808f684SSatish Balayimport numpy as np
75808f684SSatish Balay
85808f684SSatish Balay# --------------------------------------------------------------------
95808f684SSatish Balay
10e77db20cSJoe WallworkERR_ARG_OUTOFRANGE = 63
115808f684SSatish Balay
125808f684SSatish Balayclass BaseTestPlex(object):
135808f684SSatish Balay
145808f684SSatish Balay    COMM = PETSc.COMM_WORLD
155808f684SSatish Balay    DIM = 1
165808f684SSatish Balay    CELLS = [[0, 1], [1, 2]]
175808f684SSatish Balay    COORDS = [[0.], [0.5], [1.]]
185808f684SSatish Balay    COMP = 1
195808f684SSatish Balay    DOFS = [1, 0]
205808f684SSatish Balay
215808f684SSatish Balay    def setUp(self):
225808f684SSatish Balay        self.plex = PETSc.DMPlex().createFromCellList(self.DIM,
235808f684SSatish Balay                                                      self.CELLS,
245808f684SSatish Balay                                                      self.COORDS,
255808f684SSatish Balay                                                      comm=self.COMM)
265808f684SSatish Balay
275808f684SSatish Balay    def tearDown(self):
285808f684SSatish Balay        self.plex.destroy()
295808f684SSatish Balay        self.plex = None
3062e5d2d2SJDBetteridge        PETSc.garbage_cleanup()
315808f684SSatish Balay
325808f684SSatish Balay    def testTopology(self):
333df08285SMatthew G. Knepley        rank = self.COMM.rank
345808f684SSatish Balay        dim = self.plex.getDimension()
355808f684SSatish Balay        pStart, pEnd = self.plex.getChart()
365808f684SSatish Balay        cStart, cEnd = self.plex.getHeightStratum(0)
375808f684SSatish Balay        vStart, vEnd = self.plex.getDepthStratum(0)
385808f684SSatish Balay        numDepths = self.plex.getLabelSize("depth")
395808f684SSatish Balay        coords_raw = self.plex.getCoordinates().getArray()
405808f684SSatish Balay        coords = np.reshape(coords_raw, (vEnd - vStart, dim))
415808f684SSatish Balay        self.assertEqual(dim, self.DIM)
425808f684SSatish Balay        self.assertEqual(numDepths, self.DIM+1)
433df08285SMatthew G. Knepley        if rank == 0 and self.CELLS is not None:
445808f684SSatish Balay            self.assertEqual(cEnd-cStart, len(self.CELLS))
453df08285SMatthew G. Knepley        if rank == 0 and self.COORDS is not None:
465808f684SSatish Balay            self.assertEqual(vEnd-vStart, len(self.COORDS))
475808f684SSatish Balay            self.assertTrue((coords == self.COORDS).all())
485808f684SSatish Balay
495808f684SSatish Balay    def testClosure(self):
505808f684SSatish Balay        pStart, pEnd = self.plex.getChart()
515808f684SSatish Balay        for p in range(pStart, pEnd):
525808f684SSatish Balay            closure = self.plex.getTransitiveClosure(p)[0]
535808f684SSatish Balay            for c in closure:
545808f684SSatish Balay                cone = self.plex.getCone(c)
555808f684SSatish Balay                self.assertEqual(self.plex.getConeSize(c), len(cone))
565808f684SSatish Balay                for i in cone:
575808f684SSatish Balay                    self.assertIn(i, closure)
585808f684SSatish Balay            star = self.plex.getTransitiveClosure(p, useCone=False)[0]
595808f684SSatish Balay            for s in star:
605808f684SSatish Balay                support = self.plex.getSupport(s)
615808f684SSatish Balay                self.assertEqual(self.plex.getSupportSize(s), len(support))
625808f684SSatish Balay                for i in support:
635808f684SSatish Balay                    self.assertIn(i, star)
645808f684SSatish Balay
655808f684SSatish Balay    def testAdjacency(self):
665808f684SSatish Balay        PETSc.DMPlex.setAdjacencyUseAnchors(self.plex, False)
675808f684SSatish Balay        flag = PETSc.DMPlex.getAdjacencyUseAnchors(self.plex)
685808f684SSatish Balay        self.assertFalse(flag)
695808f684SSatish Balay        PETSc.DMPlex.setAdjacencyUseAnchors(self.plex, True)
705808f684SSatish Balay        flag = PETSc.DMPlex.getAdjacencyUseAnchors(self.plex)
715808f684SSatish Balay        self.assertTrue(flag)
725808f684SSatish Balay        PETSc.DMPlex.setBasicAdjacency(self.plex, False, False)
735808f684SSatish Balay        flagA, flagB = PETSc.DMPlex.getBasicAdjacency(self.plex)
745808f684SSatish Balay        self.assertFalse(flagA)
755808f684SSatish Balay        self.assertFalse(flagB)
765808f684SSatish Balay        PETSc.DMPlex.setBasicAdjacency(self.plex, True, True)
775808f684SSatish Balay        flagA, flagB = PETSc.DMPlex.getBasicAdjacency(self.plex)
785808f684SSatish Balay        self.assertTrue(flagA)
795808f684SSatish Balay        self.assertTrue(flagB)
805808f684SSatish Balay        pStart, pEnd = self.plex.getChart()
815808f684SSatish Balay        for p in range(pStart, pEnd):
825808f684SSatish Balay            adjacency = self.plex.getAdjacency(p)
835808f684SSatish Balay            self.assertTrue(p in adjacency)
845808f684SSatish Balay            self.assertTrue(len(adjacency) > 1)
855808f684SSatish Balay
865808f684SSatish Balay    def testSectionDofs(self):
875808f684SSatish Balay        self.plex.setNumFields(1)
885808f684SSatish Balay        section = self.plex.createSection([self.COMP], [self.DOFS])
895808f684SSatish Balay        size = section.getStorageSize()
905808f684SSatish Balay        entity_dofs = [self.plex.getStratumSize("depth", d) *
915808f684SSatish Balay                       self.DOFS[d] for d in range(self.DIM+1)]
925808f684SSatish Balay        self.assertEqual(sum(entity_dofs), size)
935808f684SSatish Balay
945808f684SSatish Balay    def testSectionClosure(self):
955808f684SSatish Balay        section = self.plex.createSection([self.COMP], [self.DOFS])
965808f684SSatish Balay        self.plex.setSection(section)
975808f684SSatish Balay        vec = self.plex.createLocalVec()
985808f684SSatish Balay        pStart, pEnd = self.plex.getChart()
995808f684SSatish Balay        for p in range(pStart, pEnd):
1005808f684SSatish Balay            for i in range(section.getDof(p)):
1015808f684SSatish Balay                off = section.getOffset(p)
1025808f684SSatish Balay                vec.setValue(off+i, p)
1035808f684SSatish Balay
1045808f684SSatish Balay        for p in range(pStart, pEnd):
1055808f684SSatish Balay            point_closure = self.plex.getTransitiveClosure(p)[0]
1065808f684SSatish Balay            dof_closure = self.plex.vecGetClosure(section, vec, p)
1075808f684SSatish Balay            for p in dof_closure:
1085808f684SSatish Balay                self.assertIn(p, point_closure)
1095808f684SSatish Balay
1105808f684SSatish Balay    def testBoundaryLabel(self):
111439f958dSVaclav Hapla        pStart, pEnd = self.plex.getChart()
112439f958dSVaclav Hapla        if (pEnd - pStart == 0): return
113439f958dSVaclav Hapla
1145808f684SSatish Balay        self.assertFalse(self.plex.hasLabel("boundary"))
1155808f684SSatish Balay        self.plex.markBoundaryFaces("boundary")
1165808f684SSatish Balay        self.assertTrue(self.plex.hasLabel("boundary"))
1175808f684SSatish Balay
1185808f684SSatish Balay        faces = self.plex.getStratumIS("boundary", 1)
1195808f684SSatish Balay        for f in faces.getIndices():
1205808f684SSatish Balay            points, orient = self.plex.getTransitiveClosure(f, useCone=True)
1215808f684SSatish Balay            for p in points:
1225808f684SSatish Balay                self.plex.setLabelValue("boundary", p, 1)
1235808f684SSatish Balay
1245808f684SSatish Balay        for p in range(pStart, pEnd):
1255808f684SSatish Balay            if self.plex.getLabelValue("boundary", p) != 1:
1265808f684SSatish Balay                self.plex.setLabelValue("boundary", p, 2)
1275808f684SSatish Balay
1285808f684SSatish Balay        numBoundary = self.plex.getStratumSize("boundary", 1)
1295808f684SSatish Balay        numInterior = self.plex.getStratumSize("boundary", 2)
1305808f684SSatish Balay        self.assertNotEqual(numBoundary, pEnd - pStart)
1315808f684SSatish Balay        self.assertNotEqual(numInterior, pEnd - pStart)
1325808f684SSatish Balay        self.assertEqual(numBoundary + numInterior, pEnd - pStart)
1335808f684SSatish Balay
134d6a8d7c6SJoe Wallwork    def testMetric(self):
135d6a8d7c6SJoe Wallwork        if self.DIM == 1: return
136d6a8d7c6SJoe Wallwork        self.plex.distribute()
137d6a8d7c6SJoe Wallwork        if self.CELLS is None and not self.plex.isSimplex(): return
138b59e092eSJoe Wallwork        self.plex.orient()
139d6a8d7c6SJoe Wallwork
140d6a8d7c6SJoe Wallwork        h_min = 1.0e-30
141d6a8d7c6SJoe Wallwork        h_max = 1.0e+30
142d6a8d7c6SJoe Wallwork        a_max = 1.0e+10
1435d6e921eSJoe Wallwork        target = 8.0
144d6a8d7c6SJoe Wallwork        p = 1.0
145358f35a7SJoe Wallwork        beta = 1.3
146a5745b59SJoe Wallwork        hausd = 0.01
1470e99b0e2SJoe Wallwork        self.plex.metricSetUniform(False)
148d6a8d7c6SJoe Wallwork        self.plex.metricSetIsotropic(False)
149d6a8d7c6SJoe Wallwork        self.plex.metricSetRestrictAnisotropyFirst(False)
150358f35a7SJoe Wallwork        self.plex.metricSetNoInsertion(False)
151358f35a7SJoe Wallwork        self.plex.metricSetNoSwapping(False)
152358f35a7SJoe Wallwork        self.plex.metricSetNoMovement(False)
1538d4b236aSJoe Wallwork        self.plex.metricSetNoSurf(False)
154358f35a7SJoe Wallwork        self.plex.metricSetVerbosity(-1)
155358f35a7SJoe Wallwork        self.plex.metricSetNumIterations(3)
156d6a8d7c6SJoe Wallwork        self.plex.metricSetMinimumMagnitude(h_min)
157d6a8d7c6SJoe Wallwork        self.plex.metricSetMaximumMagnitude(h_max)
158d6a8d7c6SJoe Wallwork        self.plex.metricSetMaximumAnisotropy(a_max)
159d6a8d7c6SJoe Wallwork        self.plex.metricSetTargetComplexity(target)
160d6a8d7c6SJoe Wallwork        self.plex.metricSetNormalizationOrder(p)
161358f35a7SJoe Wallwork        self.plex.metricSetGradationFactor(beta)
162a5745b59SJoe Wallwork        self.plex.metricSetHausdorffNumber(hausd)
163d6a8d7c6SJoe Wallwork
1640e99b0e2SJoe Wallwork        self.assertFalse(self.plex.metricIsUniform())
165d6a8d7c6SJoe Wallwork        self.assertFalse(self.plex.metricIsIsotropic())
166d6a8d7c6SJoe Wallwork        self.assertFalse(self.plex.metricRestrictAnisotropyFirst())
167358f35a7SJoe Wallwork        self.assertFalse(self.plex.metricNoInsertion())
168358f35a7SJoe Wallwork        self.assertFalse(self.plex.metricNoSwapping())
169358f35a7SJoe Wallwork        self.assertFalse(self.plex.metricNoMovement())
1708d4b236aSJoe Wallwork        self.assertFalse(self.plex.metricNoSurf())
171358f35a7SJoe Wallwork        assert self.plex.metricGetVerbosity() == -1
172358f35a7SJoe Wallwork        assert self.plex.metricGetNumIterations() == 3
1731a514187SJoe Wallwork        assert np.isclose(self.plex.metricGetMinimumMagnitude(), h_min)
1741a514187SJoe Wallwork        assert np.isclose(self.plex.metricGetMaximumMagnitude(), h_max)
1751a514187SJoe Wallwork        assert np.isclose(self.plex.metricGetMaximumAnisotropy(), a_max)
1761a514187SJoe Wallwork        assert np.isclose(self.plex.metricGetTargetComplexity(), target)
1771a514187SJoe Wallwork        assert np.isclose(self.plex.metricGetNormalizationOrder(), p)
178358f35a7SJoe Wallwork        assert np.isclose(self.plex.metricGetGradationFactor(), beta)
179a5745b59SJoe Wallwork        assert np.isclose(self.plex.metricGetHausdorffNumber(), hausd)
180d6a8d7c6SJoe Wallwork
1815d6e921eSJoe Wallwork        metric1 = self.plex.metricCreateUniform(0.5)
1825d6e921eSJoe Wallwork        metric2 = self.plex.metricCreateUniform(1.0)
1835d6e921eSJoe Wallwork        metric = self.plex.metricCreate()
1845d6e921eSJoe Wallwork        det = self.plex.metricDeterminantCreate()
1855d6e921eSJoe Wallwork        self.plex.metricAverage2(metric1, metric2, metric)
1865d6e921eSJoe Wallwork        metric1.array[:] *= 1.5
1875d6e921eSJoe Wallwork        assert np.allclose(metric.array, metric1.array)
1885d6e921eSJoe Wallwork        self.plex.metricIntersection2(metric1, metric2, metric)
189d6a8d7c6SJoe Wallwork        assert np.allclose(metric.array, metric2.array)
190*55a74a43SLisandro Dalcin        self.plex.metricEnforceSPD(metric, metric1, det[0])
191d6a8d7c6SJoe Wallwork        assert np.allclose(metric.array, metric1.array)
192*55a74a43SLisandro Dalcin        self.plex.metricNormalize(metric, metric1, det[0], restrictSizes=False, restrictAnisotropy=False)
1935d6e921eSJoe Wallwork        metric2.scale(pow(target, 2.0/self.DIM))
1945d6e921eSJoe Wallwork        assert np.allclose(metric1.array, metric2.array)
1955808f684SSatish Balay
1965808f684SSatish Balay    def testAdapt(self):
1971a514187SJoe Wallwork        if self.DIM == 1: return
198d03c5e66SJoe Wallwork        self.plex.orient()
199d03c5e66SJoe Wallwork        plex = self.plex.refine()
200d03c5e66SJoe Wallwork        plex.distribute()
201d03c5e66SJoe Wallwork        if self.CELLS is None and not plex.isSimplex(): return
2021a514187SJoe Wallwork        if sum(self.DOFS) > 1: return
203d03c5e66SJoe Wallwork        metric = plex.metricCreateUniform(9.0)
2045808f684SSatish Balay        try:
205d03c5e66SJoe Wallwork            newplex = plex.adaptMetric(metric,"")
2065808f684SSatish Balay        except PETSc.Error as exc:
207e77db20cSJoe Wallwork            if exc.ierr != ERR_ARG_OUTOFRANGE: raise
2085808f684SSatish Balay
2095808f684SSatish Balay
2105808f684SSatish Balay# --------------------------------------------------------------------
2115808f684SSatish Balay
2125808f684SSatish Balayclass BaseTestPlex_2D(BaseTestPlex):
2135808f684SSatish Balay    DIM = 2
2145808f684SSatish Balay    CELLS = [[0, 1, 3], [1, 3, 4], [1, 2, 4], [2, 4, 5],
2155808f684SSatish Balay             [3, 4, 6], [4, 6, 7], [4, 5, 7], [5, 7, 8]]
2165808f684SSatish Balay    COORDS = [[0.0, 0.0], [0.5, 0.0], [1.0, 0.0],
2175808f684SSatish Balay              [0.0, 0.5], [0.5, 0.5], [1.0, 0.5],
2185808f684SSatish Balay              [0.0, 1.0], [0.5, 1.0], [1.0, 1.0]]
2195808f684SSatish Balay    DOFS = [1, 0, 0]
2205808f684SSatish Balay
2215808f684SSatish Balayclass BaseTestPlex_3D(BaseTestPlex):
2225808f684SSatish Balay    DIM = 3
2235808f684SSatish Balay    CELLS = [[0, 2, 3, 7], [0, 2, 6, 7], [0, 4, 6, 7],
2245808f684SSatish Balay             [0, 1, 3, 7], [0, 1, 5, 7], [0, 4, 5, 7]]
2255808f684SSatish Balay    COORDS = [[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [1., 1., 0.],
2265808f684SSatish Balay              [0., 0., 1.], [1., 0., 1.], [0., 1., 1.], [1., 1., 1.]]
2275808f684SSatish Balay    DOFS = [1, 0, 0, 0]
2285808f684SSatish Balay
2295808f684SSatish Balay# --------------------------------------------------------------------
2305808f684SSatish Balay
2315808f684SSatish Balayclass TestPlex_1D(BaseTestPlex, unittest.TestCase):
2325808f684SSatish Balay    pass
2335808f684SSatish Balay
2345808f684SSatish Balayclass TestPlex_2D(BaseTestPlex_2D, unittest.TestCase):
2354aa747acSUmberto Zerbinati
2364aa747acSUmberto Zerbinati    def testTransform(self):
2374aa747acSUmberto Zerbinati            plex = self.plex
2384aa747acSUmberto Zerbinati            cstart, cend = plex.getHeightStratum(0)
2394aa747acSUmberto Zerbinati            tr = PETSc.DMPlexTransform().create(comm=PETSc.COMM_WORLD)
2404aa747acSUmberto Zerbinati            tr.setType(PETSc.DMPlexTransformType.REFINEALFELD)
2414aa747acSUmberto Zerbinati            tr.setDM(plex)
2424aa747acSUmberto Zerbinati            tr.setUp()
2434aa747acSUmberto Zerbinati            newplex = tr.apply(plex)
2444aa747acSUmberto Zerbinati            tr.destroy()
2454aa747acSUmberto Zerbinati            newcstart, newcend = newplex.getHeightStratum(0)
2464aa747acSUmberto Zerbinati            newplex.destroy()
2474aa747acSUmberto Zerbinati            self.assertTrue((newcend-newcstart) == 3*(cend-cstart))
2485808f684SSatish Balay
2495808f684SSatish Balayclass TestPlex_3D(BaseTestPlex_3D, unittest.TestCase):
2505808f684SSatish Balay    pass
2515808f684SSatish Balay
2525808f684SSatish Balayclass TestPlex_2D_P3(BaseTestPlex_2D, unittest.TestCase):
2535808f684SSatish Balay    DOFS = [1, 2, 1]
2545808f684SSatish Balay
2555808f684SSatish Balayclass TestPlex_3D_P3(BaseTestPlex_3D, unittest.TestCase):
2565808f684SSatish Balay    DOFS = [1, 2, 1, 0]
2575808f684SSatish Balay
2585808f684SSatish Balayclass TestPlex_3D_P4(BaseTestPlex_3D, unittest.TestCase):
2595808f684SSatish Balay    DOFS = [1, 3, 3, 1]
2605808f684SSatish Balay
2615808f684SSatish Balayclass TestPlex_2D_BoxTensor(BaseTestPlex_2D, unittest.TestCase):
2625808f684SSatish Balay    CELLS = None
2635808f684SSatish Balay    COORDS = None
2645808f684SSatish Balay    def setUp(self):
2655808f684SSatish Balay        self.plex = PETSc.DMPlex().createBoxMesh([3,3], simplex=False)
2665808f684SSatish Balay
2675808f684SSatish Balayclass TestPlex_3D_BoxTensor(BaseTestPlex_3D, unittest.TestCase):
2685808f684SSatish Balay    CELLS = None
2695808f684SSatish Balay    COORDS = None
2705808f684SSatish Balay    def setUp(self):
2715808f684SSatish Balay        self.plex = PETSc.DMPlex().createBoxMesh([3,3,3], simplex=False)
2725808f684SSatish Balay
2735808f684SSatish Balaytry:
2745808f684SSatish Balay    raise PETSc.Error
2755808f684SSatish Balay    PETSc.DMPlex().createBoxMesh([2,2], simplex=True, comm=PETSc.COMM_SELF).destroy()
2765808f684SSatish Balayexcept PETSc.Error:
2775808f684SSatish Balay    pass
2785808f684SSatish Balayelse:
2795808f684SSatish Balay    class TestPlex_2D_Box(BaseTestPlex_2D, unittest.TestCase):
2805808f684SSatish Balay        CELLS = None
2815808f684SSatish Balay        COORDS = None
2825808f684SSatish Balay        def setUp(self):
2835808f684SSatish Balay            self.plex = PETSc.DMPlex().createBoxMesh([1,1], simplex=True)
2845808f684SSatish Balay
2855808f684SSatish Balay    class TestPlex_2D_Boundary(BaseTestPlex_2D, unittest.TestCase):
2865808f684SSatish Balay        CELLS = None
2875808f684SSatish Balay        COORDS = None
2885808f684SSatish Balay        def setUp(self):
2895808f684SSatish Balay            boundary = PETSc.DMPlex().create(self.COMM)
2905808f684SSatish Balay            boundary.createSquareBoundary([0., 0.], [1., 1.], [2, 2])
2915808f684SSatish Balay            boundary.setDimension(self.DIM-1)
2925808f684SSatish Balay            self.plex = PETSc.DMPlex().generate(boundary)
2935808f684SSatish Balay
2945808f684SSatish Balay    class TestPlex_3D_Box(BaseTestPlex_3D, unittest.TestCase):
2955808f684SSatish Balay        CELLS = None
2965808f684SSatish Balay        COORDS = None
2975808f684SSatish Balay        def setUp(self):
2985808f684SSatish Balay            self.plex = PETSc.DMPlex().createBoxMesh([1,1,1], simplex=True)
2995808f684SSatish Balay
3005808f684SSatish Balay    class TestPlex_3D_Boundary(BaseTestPlex_3D, unittest.TestCase):
3015808f684SSatish Balay        CELLS = None
3025808f684SSatish Balay        COORDS = None
3035808f684SSatish Balay        def setUp(self):
3045808f684SSatish Balay            boundary = PETSc.DMPlex().create(self.COMM)
3055808f684SSatish Balay            boundary.createCubeBoundary([0., 0., 0.], [1., 1., 1.], [1, 1, 1])
3065808f684SSatish Balay            boundary.setDimension(self.DIM-1)
3075808f684SSatish Balay            self.plex = PETSc.DMPlex().generate(boundary)
3085808f684SSatish Balay
3095808f684SSatish Balay# --------------------------------------------------------------------
3105808f684SSatish Balay
311728cfed7SksagiyamPETSC_DIR = petsc4py.get_config()['PETSC_DIR']
312728cfed7Sksagiyam
313728cfed7Sksagiyamdef check_dtype(method):
314728cfed7Sksagiyam    def wrapper(self, *args, **kwargs):
315728cfed7Sksagiyam        if PETSc.ScalarType is PETSc.ComplexType:
316728cfed7Sksagiyam            return
317728cfed7Sksagiyam        else:
318728cfed7Sksagiyam            return method(self, *args, **kwargs)
319728cfed7Sksagiyam    return wrapper
320728cfed7Sksagiyam
321728cfed7Sksagiyamdef check_package(method):
322728cfed7Sksagiyam    def wrapper(self, *args, **kwargs):
323728cfed7Sksagiyam        if not PETSc.Sys.hasExternalPackage("hdf5"):
324728cfed7Sksagiyam            return
325728cfed7Sksagiyam        elif self.PARTITIONERTYPE != "simple" and \
326728cfed7Sksagiyam           not PETSc.Sys.hasExternalPackage(self.PARTITIONERTYPE):
327728cfed7Sksagiyam            return
328728cfed7Sksagiyam        else:
329728cfed7Sksagiyam            return method(self, *args, **kwargs)
330728cfed7Sksagiyam    return wrapper
331728cfed7Sksagiyam
332728cfed7Sksagiyamdef check_nsize(method):
333728cfed7Sksagiyam    def wrapper(self, *args, **kwargs):
334728cfed7Sksagiyam        if PETSc.COMM_WORLD.size != self.NSIZE:
335728cfed7Sksagiyam            return
336728cfed7Sksagiyam        else:
337728cfed7Sksagiyam            return method(self, *args, **kwargs)
338728cfed7Sksagiyam    return wrapper
339728cfed7Sksagiyam
340728cfed7Sksagiyamclass BaseTestPlexHDF5(object):
341728cfed7Sksagiyam    NSIZE = 4
342728cfed7Sksagiyam    NTIMES = 3
343728cfed7Sksagiyam
344728cfed7Sksagiyam    def setUp(self):
345728cfed7Sksagiyam        self.txtvwr = PETSc.Viewer()
346728cfed7Sksagiyam
347728cfed7Sksagiyam    def tearDown(self):
348728cfed7Sksagiyam        if not PETSc.COMM_WORLD.rank:
349728cfed7Sksagiyam            if os.path.exists(self.outfile()):
350728cfed7Sksagiyam                os.remove(self.outfile())
351728cfed7Sksagiyam            if os.path.exists(self.tmp_output_file()):
352728cfed7Sksagiyam                os.remove(self.tmp_output_file())
353728cfed7Sksagiyam        self.txtvwr = None
354728cfed7Sksagiyam
355728cfed7Sksagiyam    def _name(self):
356728cfed7Sksagiyam        return "%s_outformat-%s_%s" % (self.SUFFIX,
357728cfed7Sksagiyam                                       self.OUTFORMAT,
358728cfed7Sksagiyam                                       self.PARTITIONERTYPE)
359728cfed7Sksagiyam
360728cfed7Sksagiyam    def infile(self):
361728cfed7Sksagiyam        return os.path.join(PETSC_DIR, "share/petsc/datafiles/",
362728cfed7Sksagiyam                            "meshes/blockcylinder-50.h5")
363728cfed7Sksagiyam
364728cfed7Sksagiyam    def outfile(self):
365728cfed7Sksagiyam        return os.path.join("./temp_test_dmplex_%s.h5" % self._name())
366728cfed7Sksagiyam
367728cfed7Sksagiyam    def informat(self):
368728cfed7Sksagiyam        return PETSc.Viewer.Format.HDF5_XDMF
369728cfed7Sksagiyam
370728cfed7Sksagiyam    def outformat(self):
371728cfed7Sksagiyam        d = {"hdf5_petsc": PETSc.Viewer.Format.HDF5_PETSC,
372728cfed7Sksagiyam             "hdf5_xdmf": PETSc.Viewer.Format.HDF5_XDMF}
373728cfed7Sksagiyam        return d[self.OUTFORMAT]
374728cfed7Sksagiyam
375728cfed7Sksagiyam    def partitionerType(self):
376728cfed7Sksagiyam        d = {"simple": PETSc.Partitioner.Type.SIMPLE,
377728cfed7Sksagiyam             "ptscotch": PETSc.Partitioner.Type.PTSCOTCH,
378728cfed7Sksagiyam             "parmetis": PETSc.Partitioner.Type.PARMETIS}
379728cfed7Sksagiyam        return d[self.PARTITIONERTYPE]
380728cfed7Sksagiyam
381728cfed7Sksagiyam    def ref_output_file(self):
382728cfed7Sksagiyam        return os.path.join(PETSC_DIR, "src/dm/impls/plex/tutorials/",
383728cfed7Sksagiyam                            "output/ex5_%s.out" % self._name())
384728cfed7Sksagiyam
385728cfed7Sksagiyam    def tmp_output_file(self):
386728cfed7Sksagiyam        return os.path.join("./temp_test_dmplex_%s.out" % self._name())
387728cfed7Sksagiyam
388728cfed7Sksagiyam    def outputText(self, msg, comm):
389728cfed7Sksagiyam        if not comm.rank:
390728cfed7Sksagiyam            with open(self.tmp_output_file(), 'a') as f:
391728cfed7Sksagiyam                f.write(msg)
392728cfed7Sksagiyam
393728cfed7Sksagiyam    def outputPlex(self, plex):
394728cfed7Sksagiyam        self.txtvwr.createASCII(self.tmp_output_file(),
395728cfed7Sksagiyam                                mode='a', comm=plex.comm)
396728cfed7Sksagiyam        plex.view(viewer=self.txtvwr)
397728cfed7Sksagiyam        self.txtvwr.destroy()
398728cfed7Sksagiyam
399728cfed7Sksagiyam    @check_dtype
400728cfed7Sksagiyam    @check_package
401728cfed7Sksagiyam    @check_nsize
402728cfed7Sksagiyam    def testViewLoadCycle(self):
403728cfed7Sksagiyam        grank = PETSc.COMM_WORLD.rank
404728cfed7Sksagiyam        for i in range(self.NTIMES):
405728cfed7Sksagiyam            if i == 0:
406728cfed7Sksagiyam                infname = self.infile()
407728cfed7Sksagiyam                informt = self.informat()
408728cfed7Sksagiyam            else:
409728cfed7Sksagiyam                infname = self.outfile()
410728cfed7Sksagiyam                informt = self.outformat()
411728cfed7Sksagiyam            if self.HETEROGENEOUS:
412728cfed7Sksagiyam                mycolor = (grank > self.NTIMES - i)
413728cfed7Sksagiyam            else:
414728cfed7Sksagiyam                mycolor = 0
415f89ec98fSSatish Balay            try:
416f89ec98fSSatish Balay                import mpi4py
417f89ec98fSSatish Balay            except ImportError:
418f89ec98fSSatish Balay                self.skipTest('mpi4py') # throws special exception to signal test skip
419728cfed7Sksagiyam            mpicomm = PETSc.COMM_WORLD.tompi4py()
420728cfed7Sksagiyam            comm = PETSc.Comm(comm=mpicomm.Split(color=mycolor, key=grank))
421728cfed7Sksagiyam            if mycolor == 0:
422728cfed7Sksagiyam                self.outputText("Begin cycle %d\n" % i, comm)
423728cfed7Sksagiyam                plex = PETSc.DMPlex()
424728cfed7Sksagiyam                vwr = PETSc.ViewerHDF5()
425728cfed7Sksagiyam                # Create plex
426728cfed7Sksagiyam                plex.create(comm=comm)
427728cfed7Sksagiyam                plex.setName("DMPlex Object")
428728cfed7Sksagiyam                # Load data from XDMF into dm in parallel
429728cfed7Sksagiyam                vwr.create(infname, mode='r', comm=comm)
430728cfed7Sksagiyam                vwr.pushFormat(format=informt)
431728cfed7Sksagiyam                plex.load(viewer=vwr)
432728cfed7Sksagiyam                plex.setOptionsPrefix("loaded_")
433e600fa54SMatthew G. Knepley                plex.distributeSetDefault(False)
434728cfed7Sksagiyam                plex.setFromOptions()
435728cfed7Sksagiyam                vwr.popFormat()
436728cfed7Sksagiyam                vwr.destroy()
437728cfed7Sksagiyam                self.outputPlex(plex)
438728cfed7Sksagiyam                # Test DM is indeed distributed
439728cfed7Sksagiyam                flg = plex.isDistributed()
440728cfed7Sksagiyam                self.outputText("Loaded mesh distributed? %s\n" %
441728cfed7Sksagiyam                                str(flg).upper(), comm)
442728cfed7Sksagiyam                # Interpolate
443728cfed7Sksagiyam                plex.interpolate()
444728cfed7Sksagiyam                plex.setOptionsPrefix("interpolated_")
445728cfed7Sksagiyam                plex.setFromOptions()
446728cfed7Sksagiyam                self.outputPlex(plex)
447728cfed7Sksagiyam                # Redistribute
448728cfed7Sksagiyam                part = plex.getPartitioner()
449728cfed7Sksagiyam                part.setType(self.partitionerType())
450728cfed7Sksagiyam                _ = plex.distribute(overlap=0)
451ffa8c570SMatthew G. Knepley                plex.setName("DMPlex Object")
452728cfed7Sksagiyam                plex.setOptionsPrefix("redistributed_")
453728cfed7Sksagiyam                plex.setFromOptions()
454728cfed7Sksagiyam                self.outputPlex(plex)
455728cfed7Sksagiyam                # Save redistributed dm to XDMF in parallel
456728cfed7Sksagiyam                vwr.create(self.outfile(), mode='w', comm=comm)
457728cfed7Sksagiyam                vwr.pushFormat(format=self.outformat())
458cd7e8a5eSksagiyam                plex.setName("DMPlex Object")
459728cfed7Sksagiyam                plex.view(viewer=vwr)
460728cfed7Sksagiyam                vwr.popFormat()
461728cfed7Sksagiyam                vwr.destroy()
462728cfed7Sksagiyam                # Destroy plex
463728cfed7Sksagiyam                plex.destroy()
464728cfed7Sksagiyam                self.outputText("End   cycle %d\n--------\n" % i, comm)
465728cfed7Sksagiyam            PETSc.COMM_WORLD.Barrier()
466728cfed7Sksagiyam        # Check that the output is identical to that of plex/tutorial/ex5.c.
467728cfed7Sksagiyam        self.assertTrue(filecmp.cmp(self.tmp_output_file(),
468728cfed7Sksagiyam                                    self.ref_output_file(), shallow=False),
469728cfed7Sksagiyam                        'Contents of the files not the same.')
470728cfed7Sksagiyam        PETSc.COMM_WORLD.Barrier()
471728cfed7Sksagiyam
472728cfed7Sksagiyamclass BaseTestPlexHDF5Homogeneous(BaseTestPlexHDF5):
473728cfed7Sksagiyam    """Test save on N / load on N."""
474728cfed7Sksagiyam    SUFFIX = 0
475728cfed7Sksagiyam    HETEROGENEOUS = False
476728cfed7Sksagiyam
477728cfed7Sksagiyamclass BaseTestPlexHDF5Heterogeneous(BaseTestPlexHDF5):
478728cfed7Sksagiyam    """Test save on N / load on M."""
479728cfed7Sksagiyam    SUFFIX = 1
480728cfed7Sksagiyam    HETEROGENEOUS = True
481728cfed7Sksagiyam
482728cfed7Sksagiyamclass TestPlexHDF5PETSCSimpleHomogeneous(BaseTestPlexHDF5Homogeneous,
483728cfed7Sksagiyam                                         unittest.TestCase):
484728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
485728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
486728cfed7Sksagiyam
487728cfed7Sksagiyam"""
488728cfed7SksagiyamSkipping. PTScotch produces different distributions when run
489728cfed7Sksagiyamin a sequence in a single session.
490728cfed7Sksagiyam
491728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous,
492728cfed7Sksagiyam                                           unittest.TestCase):
493728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
494728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
495728cfed7Sksagiyam"""
496728cfed7Sksagiyam
497728cfed7Sksagiyamclass TestPlexHDF5PETSCParmetisHomogeneous(BaseTestPlexHDF5Homogeneous,
498728cfed7Sksagiyam                                           unittest.TestCase):
499728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
500728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
501728cfed7Sksagiyam
502728cfed7Sksagiyamclass TestPlexHDF5XDMFSimpleHomogeneous(BaseTestPlexHDF5Homogeneous,
503728cfed7Sksagiyam                                        unittest.TestCase):
504728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
505728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
506728cfed7Sksagiyam
507728cfed7Sksagiyam"""
508728cfed7SksagiyamSkipping. PTScotch produces different distributions when run
509728cfed7Sksagiyamin a sequence in a single session.
510728cfed7Sksagiyam
511728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous,
512728cfed7Sksagiyam                                          unittest.TestCase):
513728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
514728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
515728cfed7Sksagiyam"""
516728cfed7Sksagiyam
517728cfed7Sksagiyamclass TestPlexHDF5XDMFParmetisHomogeneous(BaseTestPlexHDF5Homogeneous,
518728cfed7Sksagiyam                                          unittest.TestCase):
519728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
520728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
521728cfed7Sksagiyam
522728cfed7Sksagiyamclass TestPlexHDF5PETSCSimpleHeterogeneous(BaseTestPlexHDF5Heterogeneous,
523728cfed7Sksagiyam                                           unittest.TestCase):
524728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
525728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
526728cfed7Sksagiyam
527728cfed7Sksagiyam"""
528728cfed7SksagiyamSkipping. PTScotch produces different distributions when run
529728cfed7Sksagiyamin a sequence in a single session.
530728cfed7Sksagiyam
531728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous,
532728cfed7Sksagiyam                                             unittest.TestCase):
533728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
534728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
535728cfed7Sksagiyam"""
536728cfed7Sksagiyam
537728cfed7Sksagiyamclass TestPlexHDF5PETSCParmetisHeterogeneous(BaseTestPlexHDF5Heterogeneous,
538728cfed7Sksagiyam                                             unittest.TestCase):
539728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
540728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
541728cfed7Sksagiyam
542728cfed7Sksagiyamclass TestPlexHDF5XDMFSimpleHeterogeneous(BaseTestPlexHDF5Heterogeneous,
543728cfed7Sksagiyam                                          unittest.TestCase):
544728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
545728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
546728cfed7Sksagiyam
547728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous,
548728cfed7Sksagiyam                                            unittest.TestCase):
549728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
550728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
551728cfed7Sksagiyam
552728cfed7Sksagiyamclass TestPlexHDF5XDMFParmetisHeterogeneous(BaseTestPlexHDF5Heterogeneous,
553728cfed7Sksagiyam                                            unittest.TestCase):
554728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
555728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
556728cfed7Sksagiyam
557728cfed7Sksagiyam# --------------------------------------------------------------------
558728cfed7Sksagiyam
5595808f684SSatish Balayif __name__ == '__main__':
5605808f684SSatish Balay    unittest.main()
561