xref: /petsc/src/binding/petsc4py/test/test_dmplex.py (revision 4aa747ac54253f0a07d301d092ea5191d7898947)
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)
1905d6e921eSJoe Wallwork        self.plex.metricEnforceSPD(metric, metric1, det)
191d6a8d7c6SJoe Wallwork        assert np.allclose(metric.array, metric1.array)
1925d6e921eSJoe Wallwork        self.plex.metricNormalize(metric, metric1, det, 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):
235*4aa747acSUmberto Zerbinati
236*4aa747acSUmberto Zerbinati    def testTransform(self):
237*4aa747acSUmberto Zerbinati            plex = self.plex
238*4aa747acSUmberto Zerbinati            cstart, cend = plex.getHeightStratum(0)
239*4aa747acSUmberto Zerbinati            tr = PETSc.DMPlexTransform().create(comm=PETSc.COMM_WORLD)
240*4aa747acSUmberto Zerbinati            tr.setType(PETSc.DMPlexTransformType.REFINEALFELD)
241*4aa747acSUmberto Zerbinati            tr.setDM(plex)
242*4aa747acSUmberto Zerbinati            tr.setUp()
243*4aa747acSUmberto Zerbinati            newplex = tr.apply(plex)
244*4aa747acSUmberto Zerbinati            tr.destroy()
245*4aa747acSUmberto Zerbinati            newcstart, newcend = newplex.getHeightStratum(0)
246*4aa747acSUmberto Zerbinati            newplex.destroy()
247*4aa747acSUmberto 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