1728cfed7Sksagiyamimport petsc4py 25808f684SSatish Balayfrom petsc4py import PETSc 35808f684SSatish Balayimport unittest 4728cfed7Sksagiyamimport os 5728cfed7Sksagiyamimport filecmp 65808f684SSatish Balayimport numpy as np 76f336411SStefano Zampiniimport importlib 85808f684SSatish Balay 95808f684SSatish Balay# -------------------------------------------------------------------- 105808f684SSatish Balay 11e77db20cSJoe WallworkERR_ARG_OUTOFRANGE = 63 125808f684SSatish Balay 135808f684SSatish Balay 146f336411SStefano Zampiniclass BaseTestPlex: 155808f684SSatish Balay COMM = PETSc.COMM_WORLD 165808f684SSatish Balay DIM = 1 175808f684SSatish Balay CELLS = [[0, 1], [1, 2]] 186f336411SStefano Zampini COORDS = [[0.0], [0.5], [1.0]] 195808f684SSatish Balay COMP = 1 205808f684SSatish Balay DOFS = [1, 0] 215808f684SSatish Balay 225808f684SSatish Balay def setUp(self): 236f336411SStefano Zampini self.plex = PETSc.DMPlex().createFromCellList( 246f336411SStefano Zampini self.DIM, self.CELLS, self.COORDS, comm=self.COMM 256f336411SStefano Zampini ) 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) 386f336411SStefano Zampini 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() 906f336411SStefano Zampini entity_dofs = [ 916f336411SStefano Zampini self.plex.getStratumSize('depth', d) * self.DOFS[d] 926f336411SStefano Zampini for d in range(self.DIM + 1) 936f336411SStefano Zampini ] 945808f684SSatish Balay self.assertEqual(sum(entity_dofs), size) 955808f684SSatish Balay 965808f684SSatish Balay def testSectionClosure(self): 975808f684SSatish Balay section = self.plex.createSection([self.COMP], [self.DOFS]) 985808f684SSatish Balay self.plex.setSection(section) 995808f684SSatish Balay vec = self.plex.createLocalVec() 1005808f684SSatish Balay pStart, pEnd = self.plex.getChart() 1015808f684SSatish Balay for p in range(pStart, pEnd): 1025808f684SSatish Balay for i in range(section.getDof(p)): 1035808f684SSatish Balay off = section.getOffset(p) 1045808f684SSatish Balay vec.setValue(off + i, p) 1055808f684SSatish Balay 1065808f684SSatish Balay for p in range(pStart, pEnd): 1075808f684SSatish Balay point_closure = self.plex.getTransitiveClosure(p)[0] 1085808f684SSatish Balay dof_closure = self.plex.vecGetClosure(section, vec, p) 1095808f684SSatish Balay for p in dof_closure: 1105808f684SSatish Balay self.assertIn(p, point_closure) 1115808f684SSatish Balay 1125808f684SSatish Balay def testBoundaryLabel(self): 113439f958dSVaclav Hapla pStart, pEnd = self.plex.getChart() 1146f336411SStefano Zampini if pEnd - pStart == 0: 1156f336411SStefano Zampini return 116439f958dSVaclav Hapla 1176f336411SStefano Zampini self.assertFalse(self.plex.hasLabel('boundary')) 1186f336411SStefano Zampini self.plex.markBoundaryFaces('boundary') 1196f336411SStefano Zampini self.assertTrue(self.plex.hasLabel('boundary')) 1205808f684SSatish Balay 1216f336411SStefano Zampini faces = self.plex.getStratumIS('boundary', 1) 1225808f684SSatish Balay for f in faces.getIndices(): 1235808f684SSatish Balay points, orient = self.plex.getTransitiveClosure(f, useCone=True) 1245808f684SSatish Balay for p in points: 1256f336411SStefano Zampini self.plex.setLabelValue('boundary', p, 1) 1265808f684SSatish Balay 1275808f684SSatish Balay for p in range(pStart, pEnd): 1286f336411SStefano Zampini if self.plex.getLabelValue('boundary', p) != 1: 1296f336411SStefano Zampini self.plex.setLabelValue('boundary', p, 2) 1305808f684SSatish Balay 1316f336411SStefano Zampini numBoundary = self.plex.getStratumSize('boundary', 1) 1326f336411SStefano Zampini numInterior = self.plex.getStratumSize('boundary', 2) 1335808f684SSatish Balay self.assertNotEqual(numBoundary, pEnd - pStart) 1345808f684SSatish Balay self.assertNotEqual(numInterior, pEnd - pStart) 1355808f684SSatish Balay self.assertEqual(numBoundary + numInterior, pEnd - pStart) 1365808f684SSatish Balay 137d6a8d7c6SJoe Wallwork def testMetric(self): 1386f336411SStefano Zampini if self.DIM == 1: 1396f336411SStefano Zampini return 140d6a8d7c6SJoe Wallwork self.plex.distribute() 1416f336411SStefano Zampini if self.CELLS is None and not self.plex.isSimplex(): 1426f336411SStefano Zampini return 143b59e092eSJoe Wallwork self.plex.orient() 144d6a8d7c6SJoe Wallwork 145d6a8d7c6SJoe Wallwork h_min = 1.0e-30 1466f336411SStefano Zampini h_max = 1.0e30 1476f336411SStefano Zampini a_max = 1.0e10 1485d6e921eSJoe Wallwork target = 8.0 149d6a8d7c6SJoe Wallwork p = 1.0 150358f35a7SJoe Wallwork beta = 1.3 151a5745b59SJoe Wallwork hausd = 0.01 1520e99b0e2SJoe Wallwork self.plex.metricSetUniform(False) 153d6a8d7c6SJoe Wallwork self.plex.metricSetIsotropic(False) 154d6a8d7c6SJoe Wallwork self.plex.metricSetRestrictAnisotropyFirst(False) 155358f35a7SJoe Wallwork self.plex.metricSetNoInsertion(False) 156358f35a7SJoe Wallwork self.plex.metricSetNoSwapping(False) 157358f35a7SJoe Wallwork self.plex.metricSetNoMovement(False) 1588d4b236aSJoe Wallwork self.plex.metricSetNoSurf(False) 159358f35a7SJoe Wallwork self.plex.metricSetVerbosity(-1) 160358f35a7SJoe Wallwork self.plex.metricSetNumIterations(3) 161d6a8d7c6SJoe Wallwork self.plex.metricSetMinimumMagnitude(h_min) 162d6a8d7c6SJoe Wallwork self.plex.metricSetMaximumMagnitude(h_max) 163d6a8d7c6SJoe Wallwork self.plex.metricSetMaximumAnisotropy(a_max) 164d6a8d7c6SJoe Wallwork self.plex.metricSetTargetComplexity(target) 165d6a8d7c6SJoe Wallwork self.plex.metricSetNormalizationOrder(p) 166358f35a7SJoe Wallwork self.plex.metricSetGradationFactor(beta) 167a5745b59SJoe Wallwork self.plex.metricSetHausdorffNumber(hausd) 168d6a8d7c6SJoe Wallwork 1690e99b0e2SJoe Wallwork self.assertFalse(self.plex.metricIsUniform()) 170d6a8d7c6SJoe Wallwork self.assertFalse(self.plex.metricIsIsotropic()) 171d6a8d7c6SJoe Wallwork self.assertFalse(self.plex.metricRestrictAnisotropyFirst()) 172358f35a7SJoe Wallwork self.assertFalse(self.plex.metricNoInsertion()) 173358f35a7SJoe Wallwork self.assertFalse(self.plex.metricNoSwapping()) 174358f35a7SJoe Wallwork self.assertFalse(self.plex.metricNoMovement()) 1758d4b236aSJoe Wallwork self.assertFalse(self.plex.metricNoSurf()) 1766f336411SStefano Zampini self.assertTrue(self.plex.metricGetVerbosity() == -1) 1776f336411SStefano Zampini self.assertTrue(self.plex.metricGetNumIterations() == 3) 1786f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMinimumMagnitude(), h_min)) 1796f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMaximumMagnitude(), h_max)) 1806f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMaximumAnisotropy(), a_max)) 1816f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetTargetComplexity(), target)) 1826f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetNormalizationOrder(), p)) 1836f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetGradationFactor(), beta)) 1846f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetHausdorffNumber(), hausd)) 185d6a8d7c6SJoe Wallwork 1865d6e921eSJoe Wallwork metric1 = self.plex.metricCreateUniform(0.5) 1875d6e921eSJoe Wallwork metric2 = self.plex.metricCreateUniform(1.0) 1885d6e921eSJoe Wallwork metric = self.plex.metricCreate() 1895d6e921eSJoe Wallwork det = self.plex.metricDeterminantCreate() 1905d6e921eSJoe Wallwork self.plex.metricAverage2(metric1, metric2, metric) 1915d6e921eSJoe Wallwork metric1.array[:] *= 1.5 1926f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric1.array)) 1935d6e921eSJoe Wallwork self.plex.metricIntersection2(metric1, metric2, metric) 1946f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric2.array)) 19555a74a43SLisandro Dalcin self.plex.metricEnforceSPD(metric, metric1, det[0]) 1966f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric1.array)) 1976f336411SStefano Zampini 1986f336411SStefano Zampini if self.DIM == 2 and PETSc.COMM_WORLD.getSize() > 6: 1996f336411SStefano Zampini # Error with 7 processes in 2D: normalization factor is -1 2006f336411SStefano Zampini return 2016f336411SStefano Zampini 2026f336411SStefano Zampini self.plex.metricNormalize( 2036f336411SStefano Zampini metric, metric1, det[0], restrictSizes=False, restrictAnisotropy=False 2046f336411SStefano Zampini ) 2055d6e921eSJoe Wallwork metric2.scale(pow(target, 2.0 / self.DIM)) 2066f336411SStefano Zampini self.assertTrue(np.allclose(metric1.array, metric2.array)) 2075808f684SSatish Balay 2085808f684SSatish Balay def testAdapt(self): 2096f336411SStefano Zampini if self.DIM == 1: 2106f336411SStefano Zampini return 2116f336411SStefano Zampini if self.DIM == 3 and PETSc.COMM_WORLD.getSize() > 4: 2126f336411SStefano Zampini # Error with 5 processes in 3D 2136f336411SStefano Zampini # ---------------------------- 2146f336411SStefano Zampini # Warning: MMG5_mmgIntextmet: Unable to diagonalize at least 1 metric. 2156f336411SStefano Zampini # Error: MMG3D_defsiz_ani: unable to intersect metrics at point 8. 2166f336411SStefano Zampini # Metric undefined. Exit program. 2176f336411SStefano Zampini # MMG remeshing problem. Exit program. 2186f336411SStefano Zampini return 219d03c5e66SJoe Wallwork self.plex.orient() 220d03c5e66SJoe Wallwork plex = self.plex.refine() 221d03c5e66SJoe Wallwork plex.distribute() 2226f336411SStefano Zampini if self.CELLS is None and not plex.isSimplex(): 2236f336411SStefano Zampini return 2246f336411SStefano Zampini if sum(self.DOFS) > 1: 2256f336411SStefano Zampini return 226d03c5e66SJoe Wallwork metric = plex.metricCreateUniform(9.0) 2275808f684SSatish Balay try: 2286f336411SStefano Zampini newplex = plex.adaptMetric(metric, '') 229*afa732d8SStefano Zampini plex.destroy() 2306f336411SStefano Zampini newplex.destroy() 2315808f684SSatish Balay except PETSc.Error as exc: 232*afa732d8SStefano Zampini plex.destroy() 2336f336411SStefano Zampini if exc.ierr != ERR_ARG_OUTOFRANGE: 2346f336411SStefano Zampini raise 2355808f684SSatish Balay 2365808f684SSatish Balay 2375808f684SSatish Balay# -------------------------------------------------------------------- 2385808f684SSatish Balay 2396f336411SStefano Zampini 2405808f684SSatish Balayclass BaseTestPlex_2D(BaseTestPlex): 2415808f684SSatish Balay DIM = 2 2426f336411SStefano Zampini CELLS = [ 2436f336411SStefano Zampini [0, 1, 3], 2446f336411SStefano Zampini [1, 3, 4], 2456f336411SStefano Zampini [1, 2, 4], 2466f336411SStefano Zampini [2, 4, 5], 2476f336411SStefano Zampini [3, 4, 6], 2486f336411SStefano Zampini [4, 6, 7], 2496f336411SStefano Zampini [4, 5, 7], 2506f336411SStefano Zampini [5, 7, 8], 2516f336411SStefano Zampini ] 2526f336411SStefano Zampini COORDS = [ 2536f336411SStefano Zampini [0.0, 0.0], 2546f336411SStefano Zampini [0.5, 0.0], 2556f336411SStefano Zampini [1.0, 0.0], 2566f336411SStefano Zampini [0.0, 0.5], 2576f336411SStefano Zampini [0.5, 0.5], 2586f336411SStefano Zampini [1.0, 0.5], 2596f336411SStefano Zampini [0.0, 1.0], 2606f336411SStefano Zampini [0.5, 1.0], 2616f336411SStefano Zampini [1.0, 1.0], 2626f336411SStefano Zampini ] 2635808f684SSatish Balay DOFS = [1, 0, 0] 2645808f684SSatish Balay 2656f336411SStefano Zampini 2665808f684SSatish Balayclass BaseTestPlex_3D(BaseTestPlex): 2675808f684SSatish Balay DIM = 3 2686f336411SStefano Zampini CELLS = [ 2696f336411SStefano Zampini [0, 2, 3, 7], 2706f336411SStefano Zampini [0, 2, 6, 7], 2716f336411SStefano Zampini [0, 4, 6, 7], 2726f336411SStefano Zampini [0, 1, 3, 7], 2736f336411SStefano Zampini [0, 1, 5, 7], 2746f336411SStefano Zampini [0, 4, 5, 7], 2756f336411SStefano Zampini ] 2766f336411SStefano Zampini COORDS = [ 2776f336411SStefano Zampini [0.0, 0.0, 0.0], 2786f336411SStefano Zampini [1.0, 0.0, 0.0], 2796f336411SStefano Zampini [0.0, 1.0, 0.0], 2806f336411SStefano Zampini [1.0, 1.0, 0.0], 2816f336411SStefano Zampini [0.0, 0.0, 1.0], 2826f336411SStefano Zampini [1.0, 0.0, 1.0], 2836f336411SStefano Zampini [0.0, 1.0, 1.0], 2846f336411SStefano Zampini [1.0, 1.0, 1.0], 2856f336411SStefano Zampini ] 2865808f684SSatish Balay DOFS = [1, 0, 0, 0] 2875808f684SSatish Balay 2886f336411SStefano Zampini 2895808f684SSatish Balay# -------------------------------------------------------------------- 2905808f684SSatish Balay 2916f336411SStefano Zampini 2925808f684SSatish Balayclass TestPlex_1D(BaseTestPlex, unittest.TestCase): 2935808f684SSatish Balay pass 2945808f684SSatish Balay 2954aa747acSUmberto Zerbinati 2966f336411SStefano Zampiniclass TestPlex_2D(BaseTestPlex_2D, unittest.TestCase): 2974aa747acSUmberto Zerbinati def testTransform(self): 2984aa747acSUmberto Zerbinati plex = self.plex 2994aa747acSUmberto Zerbinati cstart, cend = plex.getHeightStratum(0) 3004aa747acSUmberto Zerbinati tr = PETSc.DMPlexTransform().create(comm=PETSc.COMM_WORLD) 3014aa747acSUmberto Zerbinati tr.setType(PETSc.DMPlexTransformType.REFINEALFELD) 3024aa747acSUmberto Zerbinati tr.setDM(plex) 3034aa747acSUmberto Zerbinati tr.setUp() 3044aa747acSUmberto Zerbinati newplex = tr.apply(plex) 3054aa747acSUmberto Zerbinati tr.destroy() 3064aa747acSUmberto Zerbinati newcstart, newcend = newplex.getHeightStratum(0) 3074aa747acSUmberto Zerbinati newplex.destroy() 3084aa747acSUmberto Zerbinati self.assertTrue((newcend - newcstart) == 3 * (cend - cstart)) 3095808f684SSatish Balay 3106f336411SStefano Zampini 3115808f684SSatish Balayclass TestPlex_3D(BaseTestPlex_3D, unittest.TestCase): 3125808f684SSatish Balay pass 3135808f684SSatish Balay 3146f336411SStefano Zampini 3155808f684SSatish Balayclass TestPlex_2D_P3(BaseTestPlex_2D, unittest.TestCase): 3165808f684SSatish Balay DOFS = [1, 2, 1] 3175808f684SSatish Balay 3186f336411SStefano Zampini 3195808f684SSatish Balayclass TestPlex_3D_P3(BaseTestPlex_3D, unittest.TestCase): 3205808f684SSatish Balay DOFS = [1, 2, 1, 0] 3215808f684SSatish Balay 3226f336411SStefano Zampini 3235808f684SSatish Balayclass TestPlex_3D_P4(BaseTestPlex_3D, unittest.TestCase): 3245808f684SSatish Balay DOFS = [1, 3, 3, 1] 3255808f684SSatish Balay 3266f336411SStefano Zampini 3275808f684SSatish Balayclass TestPlex_2D_BoxTensor(BaseTestPlex_2D, unittest.TestCase): 3285808f684SSatish Balay CELLS = None 3295808f684SSatish Balay COORDS = None 3306f336411SStefano Zampini 3315808f684SSatish Balay def setUp(self): 3325808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3], simplex=False) 3335808f684SSatish Balay 3346f336411SStefano Zampini 3355808f684SSatish Balayclass TestPlex_3D_BoxTensor(BaseTestPlex_3D, unittest.TestCase): 3365808f684SSatish Balay CELLS = None 3375808f684SSatish Balay COORDS = None 3386f336411SStefano Zampini 3395808f684SSatish Balay def setUp(self): 3405808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3, 3], simplex=False) 3415808f684SSatish Balay 3426f336411SStefano Zampini 3436f336411SStefano Zampini# FIXME 3445808f684SSatish Balaytry: 3455808f684SSatish Balay raise PETSc.Error 3465808f684SSatish Balay PETSc.DMPlex().createBoxMesh([2, 2], simplex=True, comm=PETSc.COMM_SELF).destroy() 3475808f684SSatish Balayexcept PETSc.Error: 3485808f684SSatish Balay pass 3495808f684SSatish Balayelse: 3506f336411SStefano Zampini 3515808f684SSatish Balay class TestPlex_2D_Box(BaseTestPlex_2D, unittest.TestCase): 3525808f684SSatish Balay CELLS = None 3535808f684SSatish Balay COORDS = None 3546f336411SStefano Zampini 3555808f684SSatish Balay def setUp(self): 3565808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1], simplex=True) 3575808f684SSatish Balay 3585808f684SSatish Balay class TestPlex_2D_Boundary(BaseTestPlex_2D, unittest.TestCase): 3595808f684SSatish Balay CELLS = None 3605808f684SSatish Balay COORDS = None 3616f336411SStefano Zampini 3625808f684SSatish Balay def setUp(self): 3635808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 3646f336411SStefano Zampini boundary.createSquareBoundary([0.0, 0.0], [1.0, 1.0], [2, 2]) 3655808f684SSatish Balay boundary.setDimension(self.DIM - 1) 3665808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 3675808f684SSatish Balay 3685808f684SSatish Balay class TestPlex_3D_Box(BaseTestPlex_3D, unittest.TestCase): 3695808f684SSatish Balay CELLS = None 3705808f684SSatish Balay COORDS = None 3716f336411SStefano Zampini 3725808f684SSatish Balay def setUp(self): 3735808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1, 1], simplex=True) 3745808f684SSatish Balay 3755808f684SSatish Balay class TestPlex_3D_Boundary(BaseTestPlex_3D, unittest.TestCase): 3765808f684SSatish Balay CELLS = None 3775808f684SSatish Balay COORDS = None 3786f336411SStefano Zampini 3795808f684SSatish Balay def setUp(self): 3805808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 3816f336411SStefano Zampini boundary.createCubeBoundary([0.0, 0.0, 0.0], [1.0, 1.0, 1.0], [1, 1, 1]) 3825808f684SSatish Balay boundary.setDimension(self.DIM - 1) 3835808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 3845808f684SSatish Balay 3855808f684SSatish Balay# -------------------------------------------------------------------- 3865808f684SSatish Balay 387728cfed7SksagiyamPETSC_DIR = petsc4py.get_config()['PETSC_DIR'] 388728cfed7Sksagiyam 3896f336411SStefano Zampini 390728cfed7Sksagiyamdef check_dtype(method): 391728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 392728cfed7Sksagiyam if PETSc.ScalarType is PETSc.ComplexType: 3936f336411SStefano Zampini return None 394728cfed7Sksagiyam return method(self, *args, **kwargs) 3956f336411SStefano Zampini 396728cfed7Sksagiyam return wrapper 397728cfed7Sksagiyam 3986f336411SStefano Zampini 399728cfed7Sksagiyamdef check_package(method): 400728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 4016f336411SStefano Zampini if not PETSc.Sys.hasExternalPackage('hdf5'): 4026f336411SStefano Zampini return None 4036f336411SStefano Zampini if self.PARTITIONERTYPE != 'simple' and not PETSc.Sys.hasExternalPackage( 4046f336411SStefano Zampini self.PARTITIONERTYPE 4056f336411SStefano Zampini ): 4066f336411SStefano Zampini return None 407728cfed7Sksagiyam return method(self, *args, **kwargs) 4086f336411SStefano Zampini 409728cfed7Sksagiyam return wrapper 410728cfed7Sksagiyam 4116f336411SStefano Zampini 412728cfed7Sksagiyamdef check_nsize(method): 413728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 414728cfed7Sksagiyam if PETSc.COMM_WORLD.size != self.NSIZE: 4156f336411SStefano Zampini return None 416728cfed7Sksagiyam return method(self, *args, **kwargs) 4176f336411SStefano Zampini 418728cfed7Sksagiyam return wrapper 419728cfed7Sksagiyam 4206f336411SStefano Zampini 4216f336411SStefano Zampiniclass BaseTestPlexHDF5: 422728cfed7Sksagiyam NSIZE = 4 423728cfed7Sksagiyam NTIMES = 3 424728cfed7Sksagiyam 425728cfed7Sksagiyam def tearDown(self): 426728cfed7Sksagiyam if not PETSc.COMM_WORLD.rank: 427728cfed7Sksagiyam if os.path.exists(self.outfile()): 428728cfed7Sksagiyam os.remove(self.outfile()) 429728cfed7Sksagiyam if os.path.exists(self.tmp_output_file()): 430728cfed7Sksagiyam os.remove(self.tmp_output_file()) 431728cfed7Sksagiyam 432728cfed7Sksagiyam def _name(self): 4336f336411SStefano Zampini return f'{self.SUFFIX}_outformat-{self.OUTFORMAT}_{self.PARTITIONERTYPE}' 434728cfed7Sksagiyam 435728cfed7Sksagiyam def infile(self): 4366f336411SStefano Zampini return os.path.join( 4376f336411SStefano Zampini PETSC_DIR, 'share/petsc/datafiles/', 'meshes/blockcylinder-50.h5' 4386f336411SStefano Zampini ) 439728cfed7Sksagiyam 440728cfed7Sksagiyam def outfile(self): 4416f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.h5' % self._name()) 442728cfed7Sksagiyam 443728cfed7Sksagiyam def informat(self): 444728cfed7Sksagiyam return PETSc.Viewer.Format.HDF5_XDMF 445728cfed7Sksagiyam 446728cfed7Sksagiyam def outformat(self): 4476f336411SStefano Zampini d = { 4486f336411SStefano Zampini 'hdf5_petsc': PETSc.Viewer.Format.HDF5_PETSC, 4496f336411SStefano Zampini 'hdf5_xdmf': PETSc.Viewer.Format.HDF5_XDMF, 4506f336411SStefano Zampini } 451728cfed7Sksagiyam return d[self.OUTFORMAT] 452728cfed7Sksagiyam 453728cfed7Sksagiyam def partitionerType(self): 4546f336411SStefano Zampini d = { 4556f336411SStefano Zampini 'simple': PETSc.Partitioner.Type.SIMPLE, 4566f336411SStefano Zampini 'ptscotch': PETSc.Partitioner.Type.PTSCOTCH, 4576f336411SStefano Zampini 'parmetis': PETSc.Partitioner.Type.PARMETIS, 4586f336411SStefano Zampini } 459728cfed7Sksagiyam return d[self.PARTITIONERTYPE] 460728cfed7Sksagiyam 461728cfed7Sksagiyam def ref_output_file(self): 4626f336411SStefano Zampini return os.path.join( 4636f336411SStefano Zampini PETSC_DIR, 4646f336411SStefano Zampini 'src/dm/impls/plex/tutorials/', 4656f336411SStefano Zampini 'output/ex5_%s.out' % self._name(), 4666f336411SStefano Zampini ) 467728cfed7Sksagiyam 468728cfed7Sksagiyam def tmp_output_file(self): 4696f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.out' % self._name()) 470728cfed7Sksagiyam 471728cfed7Sksagiyam def outputText(self, msg, comm): 472728cfed7Sksagiyam if not comm.rank: 473728cfed7Sksagiyam with open(self.tmp_output_file(), 'a') as f: 474728cfed7Sksagiyam f.write(msg) 475728cfed7Sksagiyam 476728cfed7Sksagiyam def outputPlex(self, plex): 477*afa732d8SStefano Zampini txtvwr = PETSc.Viewer().createASCII( 478*afa732d8SStefano Zampini self.tmp_output_file(), mode='a', comm=plex.comm 479*afa732d8SStefano Zampini ) 480*afa732d8SStefano Zampini plex.view(viewer=txtvwr) 481*afa732d8SStefano Zampini txtvwr.destroy() 482728cfed7Sksagiyam 483728cfed7Sksagiyam @check_dtype 484728cfed7Sksagiyam @check_package 485728cfed7Sksagiyam @check_nsize 486728cfed7Sksagiyam def testViewLoadCycle(self): 487*afa732d8SStefano Zampini if importlib.util.find_spec('mpi4py') is None: 488*afa732d8SStefano Zampini self.skipTest('mpi4py') # throws special exception to signal test skip 489728cfed7Sksagiyam grank = PETSc.COMM_WORLD.rank 490728cfed7Sksagiyam for i in range(self.NTIMES): 491728cfed7Sksagiyam if i == 0: 492728cfed7Sksagiyam infname = self.infile() 493728cfed7Sksagiyam informt = self.informat() 494728cfed7Sksagiyam else: 495728cfed7Sksagiyam infname = self.outfile() 496728cfed7Sksagiyam informt = self.outformat() 497728cfed7Sksagiyam if self.HETEROGENEOUS: 4986f336411SStefano Zampini mycolor = grank > self.NTIMES - i 499728cfed7Sksagiyam else: 500728cfed7Sksagiyam mycolor = 0 501728cfed7Sksagiyam mpicomm = PETSc.COMM_WORLD.tompi4py() 502728cfed7Sksagiyam comm = PETSc.Comm(comm=mpicomm.Split(color=mycolor, key=grank)) 503728cfed7Sksagiyam if mycolor == 0: 5046f336411SStefano Zampini self.outputText('Begin cycle %d\n' % i, comm) 505728cfed7Sksagiyam plex = PETSc.DMPlex() 506728cfed7Sksagiyam vwr = PETSc.ViewerHDF5() 507728cfed7Sksagiyam # Create plex 508728cfed7Sksagiyam plex.create(comm=comm) 5096f336411SStefano Zampini plex.setName('DMPlex Object') 510728cfed7Sksagiyam # Load data from XDMF into dm in parallel 511728cfed7Sksagiyam vwr.create(infname, mode='r', comm=comm) 512728cfed7Sksagiyam vwr.pushFormat(format=informt) 513728cfed7Sksagiyam plex.load(viewer=vwr) 5146f336411SStefano Zampini plex.setOptionsPrefix('loaded_') 515e600fa54SMatthew G. Knepley plex.distributeSetDefault(False) 516728cfed7Sksagiyam plex.setFromOptions() 517728cfed7Sksagiyam vwr.popFormat() 518728cfed7Sksagiyam vwr.destroy() 519728cfed7Sksagiyam self.outputPlex(plex) 520728cfed7Sksagiyam # Test DM is indeed distributed 521728cfed7Sksagiyam flg = plex.isDistributed() 5226f336411SStefano Zampini self.outputText( 5236f336411SStefano Zampini 'Loaded mesh distributed? %s\n' % str(flg).upper(), comm 5246f336411SStefano Zampini ) 525728cfed7Sksagiyam # Interpolate 526728cfed7Sksagiyam plex.interpolate() 5276f336411SStefano Zampini plex.setOptionsPrefix('interpolated_') 528728cfed7Sksagiyam plex.setFromOptions() 529728cfed7Sksagiyam self.outputPlex(plex) 530728cfed7Sksagiyam # Redistribute 531728cfed7Sksagiyam part = plex.getPartitioner() 532728cfed7Sksagiyam part.setType(self.partitionerType()) 533*afa732d8SStefano Zampini sf = plex.distribute(overlap=0) 534*afa732d8SStefano Zampini if sf: 535*afa732d8SStefano Zampini sf.destroy() 5366f336411SStefano Zampini part.destroy() 5376f336411SStefano Zampini plex.setName('DMPlex Object') 5386f336411SStefano Zampini plex.setOptionsPrefix('redistributed_') 539728cfed7Sksagiyam plex.setFromOptions() 540728cfed7Sksagiyam self.outputPlex(plex) 541728cfed7Sksagiyam # Save redistributed dm to XDMF in parallel 542728cfed7Sksagiyam vwr.create(self.outfile(), mode='w', comm=comm) 543728cfed7Sksagiyam vwr.pushFormat(format=self.outformat()) 5446f336411SStefano Zampini plex.setName('DMPlex Object') 545728cfed7Sksagiyam plex.view(viewer=vwr) 546728cfed7Sksagiyam vwr.popFormat() 547728cfed7Sksagiyam vwr.destroy() 548728cfed7Sksagiyam # Destroy plex 549728cfed7Sksagiyam plex.destroy() 5506f336411SStefano Zampini self.outputText('End cycle %d\n--------\n' % i, comm) 551*afa732d8SStefano Zampini comm.tompi4py().Free() 552728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 553728cfed7Sksagiyam # Check that the output is identical to that of plex/tutorial/ex5.c. 5546f336411SStefano Zampini self.assertTrue( 5556f336411SStefano Zampini filecmp.cmp(self.tmp_output_file(), self.ref_output_file(), shallow=False), 5566f336411SStefano Zampini 'Contents of the files not the same.', 5576f336411SStefano Zampini ) 558728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 559728cfed7Sksagiyam 5606f336411SStefano Zampini 561728cfed7Sksagiyamclass BaseTestPlexHDF5Homogeneous(BaseTestPlexHDF5): 562728cfed7Sksagiyam """Test save on N / load on N.""" 5636f336411SStefano Zampini 564728cfed7Sksagiyam SUFFIX = 0 565728cfed7Sksagiyam HETEROGENEOUS = False 566728cfed7Sksagiyam 5676f336411SStefano Zampini 568728cfed7Sksagiyamclass BaseTestPlexHDF5Heterogeneous(BaseTestPlexHDF5): 569728cfed7Sksagiyam """Test save on N / load on M.""" 5706f336411SStefano Zampini 571728cfed7Sksagiyam SUFFIX = 1 572728cfed7Sksagiyam HETEROGENEOUS = True 573728cfed7Sksagiyam 5746f336411SStefano Zampini 5756f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHomogeneous( 5766f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 5776f336411SStefano Zampini): 5786f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 5796f336411SStefano Zampini PARTITIONERTYPE = 'simple' 5806f336411SStefano Zampini 581728cfed7Sksagiyam 582728cfed7Sksagiyam""" 583728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 584728cfed7Sksagiyamin a sequence in a single session. 585728cfed7Sksagiyam 586728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 587728cfed7Sksagiyam unittest.TestCase): 588728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 589728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 590728cfed7Sksagiyam""" 591728cfed7Sksagiyam 592728cfed7Sksagiyam 5936f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHomogeneous( 5946f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 5956f336411SStefano Zampini): 5966f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 5976f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 5986f336411SStefano Zampini 5996f336411SStefano Zampini 6006f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHomogeneous(BaseTestPlexHDF5Homogeneous, unittest.TestCase): 6016f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6026f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6036f336411SStefano Zampini 604728cfed7Sksagiyam 605728cfed7Sksagiyam""" 606728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 607728cfed7Sksagiyamin a sequence in a single session. 608728cfed7Sksagiyam 609728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 610728cfed7Sksagiyam unittest.TestCase): 611728cfed7Sksagiyam OUTFORMAT = "hdf5_xdmf" 612728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 613728cfed7Sksagiyam""" 614728cfed7Sksagiyam 615728cfed7Sksagiyam 6166f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHomogeneous( 6176f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 6186f336411SStefano Zampini): 6196f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6206f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6216f336411SStefano Zampini 6226f336411SStefano Zampini 6236f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHeterogeneous( 6246f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6256f336411SStefano Zampini): 6266f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6276f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6286f336411SStefano Zampini 629728cfed7Sksagiyam 630728cfed7Sksagiyam""" 631728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 632728cfed7Sksagiyamin a sequence in a single session. 633728cfed7Sksagiyam 634728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous, 635728cfed7Sksagiyam unittest.TestCase): 636728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 637728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 638728cfed7Sksagiyam""" 639728cfed7Sksagiyam 640728cfed7Sksagiyam 6416f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHeterogeneous( 6426f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6436f336411SStefano Zampini): 6446f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6456f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 646728cfed7Sksagiyam 647728cfed7Sksagiyam 6486f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHeterogeneous( 6496f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6506f336411SStefano Zampini): 6516f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6526f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6536f336411SStefano Zampini 6546f336411SStefano Zampini 6556f336411SStefano Zampiniclass TestPlexHDF5XDMFPTScotchHeterogeneous( 6566f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6576f336411SStefano Zampini): 6586f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6596f336411SStefano Zampini PARTITIONERTYPE = 'ptscotch' 6606f336411SStefano Zampini 6616f336411SStefano Zampini 6626f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHeterogeneous( 6636f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6646f336411SStefano Zampini): 6656f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6666f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6676f336411SStefano Zampini 668728cfed7Sksagiyam 669728cfed7Sksagiyam# -------------------------------------------------------------------- 670728cfed7Sksagiyam 6715808f684SSatish Balayif __name__ == '__main__': 6725808f684SSatish Balay unittest.main() 673