xref: /petsc/src/binding/petsc4py/test/test_dmplex.py (revision 62e5d2d2208a68fdbd23dac44110783534664de8)
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
30*62e5d2d2SJDBetteridge        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):
2355808f684SSatish Balay    pass
2365808f684SSatish Balay
2375808f684SSatish Balayclass TestPlex_3D(BaseTestPlex_3D, unittest.TestCase):
2385808f684SSatish Balay    pass
2395808f684SSatish Balay
2405808f684SSatish Balayclass TestPlex_2D_P3(BaseTestPlex_2D, unittest.TestCase):
2415808f684SSatish Balay    DOFS = [1, 2, 1]
2425808f684SSatish Balay
2435808f684SSatish Balayclass TestPlex_3D_P3(BaseTestPlex_3D, unittest.TestCase):
2445808f684SSatish Balay    DOFS = [1, 2, 1, 0]
2455808f684SSatish Balay
2465808f684SSatish Balayclass TestPlex_3D_P4(BaseTestPlex_3D, unittest.TestCase):
2475808f684SSatish Balay    DOFS = [1, 3, 3, 1]
2485808f684SSatish Balay
2495808f684SSatish Balayclass TestPlex_2D_BoxTensor(BaseTestPlex_2D, unittest.TestCase):
2505808f684SSatish Balay    CELLS = None
2515808f684SSatish Balay    COORDS = None
2525808f684SSatish Balay    def setUp(self):
2535808f684SSatish Balay        self.plex = PETSc.DMPlex().createBoxMesh([3,3], simplex=False)
2545808f684SSatish Balay
2555808f684SSatish Balayclass TestPlex_3D_BoxTensor(BaseTestPlex_3D, unittest.TestCase):
2565808f684SSatish Balay    CELLS = None
2575808f684SSatish Balay    COORDS = None
2585808f684SSatish Balay    def setUp(self):
2595808f684SSatish Balay        self.plex = PETSc.DMPlex().createBoxMesh([3,3,3], simplex=False)
2605808f684SSatish Balay
2615808f684SSatish Balaytry:
2625808f684SSatish Balay    raise PETSc.Error
2635808f684SSatish Balay    PETSc.DMPlex().createBoxMesh([2,2], simplex=True, comm=PETSc.COMM_SELF).destroy()
2645808f684SSatish Balayexcept PETSc.Error:
2655808f684SSatish Balay    pass
2665808f684SSatish Balayelse:
2675808f684SSatish Balay    class TestPlex_2D_Box(BaseTestPlex_2D, unittest.TestCase):
2685808f684SSatish Balay        CELLS = None
2695808f684SSatish Balay        COORDS = None
2705808f684SSatish Balay        def setUp(self):
2715808f684SSatish Balay            self.plex = PETSc.DMPlex().createBoxMesh([1,1], simplex=True)
2725808f684SSatish Balay
2735808f684SSatish Balay    class TestPlex_2D_Boundary(BaseTestPlex_2D, unittest.TestCase):
2745808f684SSatish Balay        CELLS = None
2755808f684SSatish Balay        COORDS = None
2765808f684SSatish Balay        def setUp(self):
2775808f684SSatish Balay            boundary = PETSc.DMPlex().create(self.COMM)
2785808f684SSatish Balay            boundary.createSquareBoundary([0., 0.], [1., 1.], [2, 2])
2795808f684SSatish Balay            boundary.setDimension(self.DIM-1)
2805808f684SSatish Balay            self.plex = PETSc.DMPlex().generate(boundary)
2815808f684SSatish Balay
2825808f684SSatish Balay    class TestPlex_3D_Box(BaseTestPlex_3D, unittest.TestCase):
2835808f684SSatish Balay        CELLS = None
2845808f684SSatish Balay        COORDS = None
2855808f684SSatish Balay        def setUp(self):
2865808f684SSatish Balay            self.plex = PETSc.DMPlex().createBoxMesh([1,1,1], simplex=True)
2875808f684SSatish Balay
2885808f684SSatish Balay    class TestPlex_3D_Boundary(BaseTestPlex_3D, unittest.TestCase):
2895808f684SSatish Balay        CELLS = None
2905808f684SSatish Balay        COORDS = None
2915808f684SSatish Balay        def setUp(self):
2925808f684SSatish Balay            boundary = PETSc.DMPlex().create(self.COMM)
2935808f684SSatish Balay            boundary.createCubeBoundary([0., 0., 0.], [1., 1., 1.], [1, 1, 1])
2945808f684SSatish Balay            boundary.setDimension(self.DIM-1)
2955808f684SSatish Balay            self.plex = PETSc.DMPlex().generate(boundary)
2965808f684SSatish Balay
2975808f684SSatish Balay# --------------------------------------------------------------------
2985808f684SSatish Balay
299728cfed7SksagiyamPETSC_DIR = petsc4py.get_config()['PETSC_DIR']
300728cfed7Sksagiyam
301728cfed7Sksagiyamdef check_dtype(method):
302728cfed7Sksagiyam    def wrapper(self, *args, **kwargs):
303728cfed7Sksagiyam        if PETSc.ScalarType is PETSc.ComplexType:
304728cfed7Sksagiyam            return
305728cfed7Sksagiyam        else:
306728cfed7Sksagiyam            return method(self, *args, **kwargs)
307728cfed7Sksagiyam    return wrapper
308728cfed7Sksagiyam
309728cfed7Sksagiyamdef check_package(method):
310728cfed7Sksagiyam    def wrapper(self, *args, **kwargs):
311728cfed7Sksagiyam        if not PETSc.Sys.hasExternalPackage("hdf5"):
312728cfed7Sksagiyam            return
313728cfed7Sksagiyam        elif self.PARTITIONERTYPE != "simple" and \
314728cfed7Sksagiyam           not PETSc.Sys.hasExternalPackage(self.PARTITIONERTYPE):
315728cfed7Sksagiyam            return
316728cfed7Sksagiyam        else:
317728cfed7Sksagiyam            return method(self, *args, **kwargs)
318728cfed7Sksagiyam    return wrapper
319728cfed7Sksagiyam
320728cfed7Sksagiyamdef check_nsize(method):
321728cfed7Sksagiyam    def wrapper(self, *args, **kwargs):
322728cfed7Sksagiyam        if PETSc.COMM_WORLD.size != self.NSIZE:
323728cfed7Sksagiyam            return
324728cfed7Sksagiyam        else:
325728cfed7Sksagiyam            return method(self, *args, **kwargs)
326728cfed7Sksagiyam    return wrapper
327728cfed7Sksagiyam
328728cfed7Sksagiyamclass BaseTestPlexHDF5(object):
329728cfed7Sksagiyam    NSIZE = 4
330728cfed7Sksagiyam    NTIMES = 3
331728cfed7Sksagiyam
332728cfed7Sksagiyam    def setUp(self):
333728cfed7Sksagiyam        self.txtvwr = PETSc.Viewer()
334728cfed7Sksagiyam
335728cfed7Sksagiyam    def tearDown(self):
336728cfed7Sksagiyam        if not PETSc.COMM_WORLD.rank:
337728cfed7Sksagiyam            if os.path.exists(self.outfile()):
338728cfed7Sksagiyam                os.remove(self.outfile())
339728cfed7Sksagiyam            if os.path.exists(self.tmp_output_file()):
340728cfed7Sksagiyam                os.remove(self.tmp_output_file())
341728cfed7Sksagiyam        self.txtvwr = None
342728cfed7Sksagiyam
343728cfed7Sksagiyam    def _name(self):
344728cfed7Sksagiyam        return "%s_outformat-%s_%s" % (self.SUFFIX,
345728cfed7Sksagiyam                                       self.OUTFORMAT,
346728cfed7Sksagiyam                                       self.PARTITIONERTYPE)
347728cfed7Sksagiyam
348728cfed7Sksagiyam    def infile(self):
349728cfed7Sksagiyam        return os.path.join(PETSC_DIR, "share/petsc/datafiles/",
350728cfed7Sksagiyam                            "meshes/blockcylinder-50.h5")
351728cfed7Sksagiyam
352728cfed7Sksagiyam    def outfile(self):
353728cfed7Sksagiyam        return os.path.join("./temp_test_dmplex_%s.h5" % self._name())
354728cfed7Sksagiyam
355728cfed7Sksagiyam    def informat(self):
356728cfed7Sksagiyam        return PETSc.Viewer.Format.HDF5_XDMF
357728cfed7Sksagiyam
358728cfed7Sksagiyam    def outformat(self):
359728cfed7Sksagiyam        d = {"hdf5_petsc": PETSc.Viewer.Format.HDF5_PETSC,
360728cfed7Sksagiyam             "hdf5_xdmf": PETSc.Viewer.Format.HDF5_XDMF}
361728cfed7Sksagiyam        return d[self.OUTFORMAT]
362728cfed7Sksagiyam
363728cfed7Sksagiyam    def partitionerType(self):
364728cfed7Sksagiyam        d = {"simple": PETSc.Partitioner.Type.SIMPLE,
365728cfed7Sksagiyam             "ptscotch": PETSc.Partitioner.Type.PTSCOTCH,
366728cfed7Sksagiyam             "parmetis": PETSc.Partitioner.Type.PARMETIS}
367728cfed7Sksagiyam        return d[self.PARTITIONERTYPE]
368728cfed7Sksagiyam
369728cfed7Sksagiyam    def ref_output_file(self):
370728cfed7Sksagiyam        return os.path.join(PETSC_DIR, "src/dm/impls/plex/tutorials/",
371728cfed7Sksagiyam                            "output/ex5_%s.out" % self._name())
372728cfed7Sksagiyam
373728cfed7Sksagiyam    def tmp_output_file(self):
374728cfed7Sksagiyam        return os.path.join("./temp_test_dmplex_%s.out" % self._name())
375728cfed7Sksagiyam
376728cfed7Sksagiyam    def outputText(self, msg, comm):
377728cfed7Sksagiyam        if not comm.rank:
378728cfed7Sksagiyam            with open(self.tmp_output_file(), 'a') as f:
379728cfed7Sksagiyam                f.write(msg)
380728cfed7Sksagiyam
381728cfed7Sksagiyam    def outputPlex(self, plex):
382728cfed7Sksagiyam        self.txtvwr.createASCII(self.tmp_output_file(),
383728cfed7Sksagiyam                                mode='a', comm=plex.comm)
384728cfed7Sksagiyam        plex.view(viewer=self.txtvwr)
385728cfed7Sksagiyam        self.txtvwr.destroy()
386728cfed7Sksagiyam
387728cfed7Sksagiyam    @check_dtype
388728cfed7Sksagiyam    @check_package
389728cfed7Sksagiyam    @check_nsize
390728cfed7Sksagiyam    def testViewLoadCycle(self):
391728cfed7Sksagiyam        grank = PETSc.COMM_WORLD.rank
392728cfed7Sksagiyam        for i in range(self.NTIMES):
393728cfed7Sksagiyam            if i == 0:
394728cfed7Sksagiyam                infname = self.infile()
395728cfed7Sksagiyam                informt = self.informat()
396728cfed7Sksagiyam            else:
397728cfed7Sksagiyam                infname = self.outfile()
398728cfed7Sksagiyam                informt = self.outformat()
399728cfed7Sksagiyam            if self.HETEROGENEOUS:
400728cfed7Sksagiyam                mycolor = (grank > self.NTIMES - i)
401728cfed7Sksagiyam            else:
402728cfed7Sksagiyam                mycolor = 0
403f89ec98fSSatish Balay            try:
404f89ec98fSSatish Balay                import mpi4py
405f89ec98fSSatish Balay            except ImportError:
406f89ec98fSSatish Balay                self.skipTest('mpi4py') # throws special exception to signal test skip
407728cfed7Sksagiyam            mpicomm = PETSc.COMM_WORLD.tompi4py()
408728cfed7Sksagiyam            comm = PETSc.Comm(comm=mpicomm.Split(color=mycolor, key=grank))
409728cfed7Sksagiyam            if mycolor == 0:
410728cfed7Sksagiyam                self.outputText("Begin cycle %d\n" % i, comm)
411728cfed7Sksagiyam                plex = PETSc.DMPlex()
412728cfed7Sksagiyam                vwr = PETSc.ViewerHDF5()
413728cfed7Sksagiyam                # Create plex
414728cfed7Sksagiyam                plex.create(comm=comm)
415728cfed7Sksagiyam                plex.setName("DMPlex Object")
416728cfed7Sksagiyam                # Load data from XDMF into dm in parallel
417728cfed7Sksagiyam                vwr.create(infname, mode='r', comm=comm)
418728cfed7Sksagiyam                vwr.pushFormat(format=informt)
419728cfed7Sksagiyam                plex.load(viewer=vwr)
420728cfed7Sksagiyam                plex.setOptionsPrefix("loaded_")
421e600fa54SMatthew G. Knepley                plex.distributeSetDefault(False)
422728cfed7Sksagiyam                plex.setFromOptions()
423728cfed7Sksagiyam                vwr.popFormat()
424728cfed7Sksagiyam                vwr.destroy()
425728cfed7Sksagiyam                self.outputPlex(plex)
426728cfed7Sksagiyam                # Test DM is indeed distributed
427728cfed7Sksagiyam                flg = plex.isDistributed()
428728cfed7Sksagiyam                self.outputText("Loaded mesh distributed? %s\n" %
429728cfed7Sksagiyam                                str(flg).upper(), comm)
430728cfed7Sksagiyam                # Interpolate
431728cfed7Sksagiyam                plex.interpolate()
432728cfed7Sksagiyam                plex.setOptionsPrefix("interpolated_")
433728cfed7Sksagiyam                plex.setFromOptions()
434728cfed7Sksagiyam                self.outputPlex(plex)
435728cfed7Sksagiyam                # Redistribute
436728cfed7Sksagiyam                part = plex.getPartitioner()
437728cfed7Sksagiyam                part.setType(self.partitionerType())
438728cfed7Sksagiyam                _ = plex.distribute(overlap=0)
439ffa8c570SMatthew G. Knepley                plex.setName("DMPlex Object")
440728cfed7Sksagiyam                plex.setOptionsPrefix("redistributed_")
441728cfed7Sksagiyam                plex.setFromOptions()
442728cfed7Sksagiyam                self.outputPlex(plex)
443728cfed7Sksagiyam                # Save redistributed dm to XDMF in parallel
444728cfed7Sksagiyam                vwr.create(self.outfile(), mode='w', comm=comm)
445728cfed7Sksagiyam                vwr.pushFormat(format=self.outformat())
446cd7e8a5eSksagiyam                plex.setName("DMPlex Object")
447728cfed7Sksagiyam                plex.view(viewer=vwr)
448728cfed7Sksagiyam                vwr.popFormat()
449728cfed7Sksagiyam                vwr.destroy()
450728cfed7Sksagiyam                # Destroy plex
451728cfed7Sksagiyam                plex.destroy()
452728cfed7Sksagiyam                self.outputText("End   cycle %d\n--------\n" % i, comm)
453728cfed7Sksagiyam            PETSc.COMM_WORLD.Barrier()
454728cfed7Sksagiyam        # Check that the output is identical to that of plex/tutorial/ex5.c.
455728cfed7Sksagiyam        self.assertTrue(filecmp.cmp(self.tmp_output_file(),
456728cfed7Sksagiyam                                    self.ref_output_file(), shallow=False),
457728cfed7Sksagiyam                        'Contents of the files not the same.')
458728cfed7Sksagiyam        PETSc.COMM_WORLD.Barrier()
459728cfed7Sksagiyam
460728cfed7Sksagiyamclass BaseTestPlexHDF5Homogeneous(BaseTestPlexHDF5):
461728cfed7Sksagiyam    """Test save on N / load on N."""
462728cfed7Sksagiyam    SUFFIX = 0
463728cfed7Sksagiyam    HETEROGENEOUS = False
464728cfed7Sksagiyam
465728cfed7Sksagiyamclass BaseTestPlexHDF5Heterogeneous(BaseTestPlexHDF5):
466728cfed7Sksagiyam    """Test save on N / load on M."""
467728cfed7Sksagiyam    SUFFIX = 1
468728cfed7Sksagiyam    HETEROGENEOUS = True
469728cfed7Sksagiyam
470728cfed7Sksagiyamclass TestPlexHDF5PETSCSimpleHomogeneous(BaseTestPlexHDF5Homogeneous,
471728cfed7Sksagiyam                                         unittest.TestCase):
472728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
473728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
474728cfed7Sksagiyam
475728cfed7Sksagiyam"""
476728cfed7SksagiyamSkipping. PTScotch produces different distributions when run
477728cfed7Sksagiyamin a sequence in a single session.
478728cfed7Sksagiyam
479728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous,
480728cfed7Sksagiyam                                           unittest.TestCase):
481728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
482728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
483728cfed7Sksagiyam"""
484728cfed7Sksagiyam
485728cfed7Sksagiyamclass TestPlexHDF5PETSCParmetisHomogeneous(BaseTestPlexHDF5Homogeneous,
486728cfed7Sksagiyam                                           unittest.TestCase):
487728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
488728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
489728cfed7Sksagiyam
490728cfed7Sksagiyamclass TestPlexHDF5XDMFSimpleHomogeneous(BaseTestPlexHDF5Homogeneous,
491728cfed7Sksagiyam                                        unittest.TestCase):
492728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
493728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
494728cfed7Sksagiyam
495728cfed7Sksagiyam"""
496728cfed7SksagiyamSkipping. PTScotch produces different distributions when run
497728cfed7Sksagiyamin a sequence in a single session.
498728cfed7Sksagiyam
499728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous,
500728cfed7Sksagiyam                                          unittest.TestCase):
501728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
502728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
503728cfed7Sksagiyam"""
504728cfed7Sksagiyam
505728cfed7Sksagiyamclass TestPlexHDF5XDMFParmetisHomogeneous(BaseTestPlexHDF5Homogeneous,
506728cfed7Sksagiyam                                          unittest.TestCase):
507728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
508728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
509728cfed7Sksagiyam
510728cfed7Sksagiyamclass TestPlexHDF5PETSCSimpleHeterogeneous(BaseTestPlexHDF5Heterogeneous,
511728cfed7Sksagiyam                                           unittest.TestCase):
512728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
513728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
514728cfed7Sksagiyam
515728cfed7Sksagiyam"""
516728cfed7SksagiyamSkipping. PTScotch produces different distributions when run
517728cfed7Sksagiyamin a sequence in a single session.
518728cfed7Sksagiyam
519728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous,
520728cfed7Sksagiyam                                             unittest.TestCase):
521728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
522728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
523728cfed7Sksagiyam"""
524728cfed7Sksagiyam
525728cfed7Sksagiyamclass TestPlexHDF5PETSCParmetisHeterogeneous(BaseTestPlexHDF5Heterogeneous,
526728cfed7Sksagiyam                                             unittest.TestCase):
527728cfed7Sksagiyam    OUTFORMAT = "hdf5_petsc"
528728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
529728cfed7Sksagiyam
530728cfed7Sksagiyamclass TestPlexHDF5XDMFSimpleHeterogeneous(BaseTestPlexHDF5Heterogeneous,
531728cfed7Sksagiyam                                          unittest.TestCase):
532728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
533728cfed7Sksagiyam    PARTITIONERTYPE = "simple"
534728cfed7Sksagiyam
535728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous,
536728cfed7Sksagiyam                                            unittest.TestCase):
537728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
538728cfed7Sksagiyam    PARTITIONERTYPE = "ptscotch"
539728cfed7Sksagiyam
540728cfed7Sksagiyamclass TestPlexHDF5XDMFParmetisHeterogeneous(BaseTestPlexHDF5Heterogeneous,
541728cfed7Sksagiyam                                            unittest.TestCase):
542728cfed7Sksagiyam    OUTFORMAT = "hdf5_xdmf"
543728cfed7Sksagiyam    PARTITIONERTYPE = "parmetis"
544728cfed7Sksagiyam
545728cfed7Sksagiyam# --------------------------------------------------------------------
546728cfed7Sksagiyam
5475808f684SSatish Balayif __name__ == '__main__':
5485808f684SSatish Balay    unittest.main()
549