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, '') 229afa732d8SStefano Zampini plex.destroy() 2306f336411SStefano Zampini newplex.destroy() 2315808f684SSatish Balay except PETSc.Error as exc: 232afa732d8SStefano Zampini plex.destroy() 2336f336411SStefano Zampini if exc.ierr != ERR_ARG_OUTOFRANGE: 2346f336411SStefano Zampini raise 2355808f684SSatish Balay 236*c039638dSMatthew G. Knepley def testNatural(self): 237*c039638dSMatthew G. Knepley dim = self.plex.getDimension() 238*c039638dSMatthew G. Knepley ct = self.plex.getCellType(0) 239*c039638dSMatthew G. Knepley fe = PETSc.FE().createByCell(dim, 1, ct) 240*c039638dSMatthew G. Knepley self.plex.setField(0, fe) 241*c039638dSMatthew G. Knepley self.plex.createDS() 242*c039638dSMatthew G. Knepley self.plex.setUseNatural(True) 243*c039638dSMatthew G. Knepley self.plex.distribute() 244*c039638dSMatthew G. Knepley self.plex.view() 245*c039638dSMatthew G. Knepley gv = self.plex.createGlobalVec() 246*c039638dSMatthew G. Knepley nv = self.plex.createNaturalVec() 247*c039638dSMatthew G. Knepley self.plex.globalToNaturalBegin(gv, nv) 248*c039638dSMatthew G. Knepley self.plex.globalToNaturalEnd(gv, nv) 249*c039638dSMatthew G. Knepley self.plex.naturalToGlobalBegin(nv, gv) 250*c039638dSMatthew G. Knepley self.plex.naturalToGlobalEnd(nv, gv) 2515808f684SSatish Balay 2525808f684SSatish Balay# -------------------------------------------------------------------- 2535808f684SSatish Balay 2546f336411SStefano Zampini 2555808f684SSatish Balayclass BaseTestPlex_2D(BaseTestPlex): 2565808f684SSatish Balay DIM = 2 2576f336411SStefano Zampini CELLS = [ 2586f336411SStefano Zampini [0, 1, 3], 2596f336411SStefano Zampini [1, 3, 4], 2606f336411SStefano Zampini [1, 2, 4], 2616f336411SStefano Zampini [2, 4, 5], 2626f336411SStefano Zampini [3, 4, 6], 2636f336411SStefano Zampini [4, 6, 7], 2646f336411SStefano Zampini [4, 5, 7], 2656f336411SStefano Zampini [5, 7, 8], 2666f336411SStefano Zampini ] 2676f336411SStefano Zampini COORDS = [ 2686f336411SStefano Zampini [0.0, 0.0], 2696f336411SStefano Zampini [0.5, 0.0], 2706f336411SStefano Zampini [1.0, 0.0], 2716f336411SStefano Zampini [0.0, 0.5], 2726f336411SStefano Zampini [0.5, 0.5], 2736f336411SStefano Zampini [1.0, 0.5], 2746f336411SStefano Zampini [0.0, 1.0], 2756f336411SStefano Zampini [0.5, 1.0], 2766f336411SStefano Zampini [1.0, 1.0], 2776f336411SStefano Zampini ] 2785808f684SSatish Balay DOFS = [1, 0, 0] 2795808f684SSatish Balay 2806f336411SStefano Zampini 2815808f684SSatish Balayclass BaseTestPlex_3D(BaseTestPlex): 2825808f684SSatish Balay DIM = 3 2836f336411SStefano Zampini CELLS = [ 2846f336411SStefano Zampini [0, 2, 3, 7], 2856f336411SStefano Zampini [0, 2, 6, 7], 2866f336411SStefano Zampini [0, 4, 6, 7], 2876f336411SStefano Zampini [0, 1, 3, 7], 2886f336411SStefano Zampini [0, 1, 5, 7], 2896f336411SStefano Zampini [0, 4, 5, 7], 2906f336411SStefano Zampini ] 2916f336411SStefano Zampini COORDS = [ 2926f336411SStefano Zampini [0.0, 0.0, 0.0], 2936f336411SStefano Zampini [1.0, 0.0, 0.0], 2946f336411SStefano Zampini [0.0, 1.0, 0.0], 2956f336411SStefano Zampini [1.0, 1.0, 0.0], 2966f336411SStefano Zampini [0.0, 0.0, 1.0], 2976f336411SStefano Zampini [1.0, 0.0, 1.0], 2986f336411SStefano Zampini [0.0, 1.0, 1.0], 2996f336411SStefano Zampini [1.0, 1.0, 1.0], 3006f336411SStefano Zampini ] 3015808f684SSatish Balay DOFS = [1, 0, 0, 0] 3025808f684SSatish Balay 3036f336411SStefano Zampini 3045808f684SSatish Balay# -------------------------------------------------------------------- 3055808f684SSatish Balay 3066f336411SStefano Zampini 3075808f684SSatish Balayclass TestPlex_1D(BaseTestPlex, unittest.TestCase): 3085808f684SSatish Balay pass 3095808f684SSatish Balay 3104aa747acSUmberto Zerbinati 3116f336411SStefano Zampiniclass TestPlex_2D(BaseTestPlex_2D, unittest.TestCase): 3124aa747acSUmberto Zerbinati def testTransform(self): 3134aa747acSUmberto Zerbinati plex = self.plex 3144aa747acSUmberto Zerbinati cstart, cend = plex.getHeightStratum(0) 3154aa747acSUmberto Zerbinati tr = PETSc.DMPlexTransform().create(comm=PETSc.COMM_WORLD) 3164aa747acSUmberto Zerbinati tr.setType(PETSc.DMPlexTransformType.REFINEALFELD) 3174aa747acSUmberto Zerbinati tr.setDM(plex) 3184aa747acSUmberto Zerbinati tr.setUp() 3194aa747acSUmberto Zerbinati newplex = tr.apply(plex) 3204aa747acSUmberto Zerbinati tr.destroy() 3214aa747acSUmberto Zerbinati newcstart, newcend = newplex.getHeightStratum(0) 3224aa747acSUmberto Zerbinati newplex.destroy() 3234aa747acSUmberto Zerbinati self.assertTrue((newcend - newcstart) == 3 * (cend - cstart)) 3245808f684SSatish Balay 3256f336411SStefano Zampini 3265808f684SSatish Balayclass TestPlex_3D(BaseTestPlex_3D, unittest.TestCase): 3275808f684SSatish Balay pass 3285808f684SSatish Balay 3296f336411SStefano Zampini 3305808f684SSatish Balayclass TestPlex_2D_P3(BaseTestPlex_2D, unittest.TestCase): 3315808f684SSatish Balay DOFS = [1, 2, 1] 3325808f684SSatish Balay 3336f336411SStefano Zampini 3345808f684SSatish Balayclass TestPlex_3D_P3(BaseTestPlex_3D, unittest.TestCase): 3355808f684SSatish Balay DOFS = [1, 2, 1, 0] 3365808f684SSatish Balay 3376f336411SStefano Zampini 3385808f684SSatish Balayclass TestPlex_3D_P4(BaseTestPlex_3D, unittest.TestCase): 3395808f684SSatish Balay DOFS = [1, 3, 3, 1] 3405808f684SSatish Balay 3416f336411SStefano Zampini 3425808f684SSatish Balayclass TestPlex_2D_BoxTensor(BaseTestPlex_2D, unittest.TestCase): 3435808f684SSatish Balay CELLS = None 3445808f684SSatish Balay COORDS = None 3456f336411SStefano Zampini 3465808f684SSatish Balay def setUp(self): 3475808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3], simplex=False) 3485808f684SSatish Balay 3496f336411SStefano Zampini 3505808f684SSatish Balayclass TestPlex_3D_BoxTensor(BaseTestPlex_3D, unittest.TestCase): 3515808f684SSatish Balay CELLS = None 3525808f684SSatish Balay COORDS = None 3536f336411SStefano Zampini 3545808f684SSatish Balay def setUp(self): 3555808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3, 3], simplex=False) 3565808f684SSatish Balay 3576f336411SStefano Zampini 3586f336411SStefano Zampini# FIXME 3595808f684SSatish Balaytry: 3605808f684SSatish Balay raise PETSc.Error 3615808f684SSatish Balay PETSc.DMPlex().createBoxMesh([2, 2], simplex=True, comm=PETSc.COMM_SELF).destroy() 3625808f684SSatish Balayexcept PETSc.Error: 3635808f684SSatish Balay pass 3645808f684SSatish Balayelse: 3656f336411SStefano Zampini 3665808f684SSatish Balay class TestPlex_2D_Box(BaseTestPlex_2D, unittest.TestCase): 3675808f684SSatish Balay CELLS = None 3685808f684SSatish Balay COORDS = None 3696f336411SStefano Zampini 3705808f684SSatish Balay def setUp(self): 3715808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1], simplex=True) 3725808f684SSatish Balay 3735808f684SSatish Balay class TestPlex_2D_Boundary(BaseTestPlex_2D, unittest.TestCase): 3745808f684SSatish Balay CELLS = None 3755808f684SSatish Balay COORDS = None 3766f336411SStefano Zampini 3775808f684SSatish Balay def setUp(self): 3785808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 3796f336411SStefano Zampini boundary.createSquareBoundary([0.0, 0.0], [1.0, 1.0], [2, 2]) 3805808f684SSatish Balay boundary.setDimension(self.DIM - 1) 3815808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 3825808f684SSatish Balay 3835808f684SSatish Balay class TestPlex_3D_Box(BaseTestPlex_3D, unittest.TestCase): 3845808f684SSatish Balay CELLS = None 3855808f684SSatish Balay COORDS = None 3866f336411SStefano Zampini 3875808f684SSatish Balay def setUp(self): 3885808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1, 1], simplex=True) 3895808f684SSatish Balay 3905808f684SSatish Balay class TestPlex_3D_Boundary(BaseTestPlex_3D, unittest.TestCase): 3915808f684SSatish Balay CELLS = None 3925808f684SSatish Balay COORDS = None 3936f336411SStefano Zampini 3945808f684SSatish Balay def setUp(self): 3955808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 3966f336411SStefano Zampini boundary.createCubeBoundary([0.0, 0.0, 0.0], [1.0, 1.0, 1.0], [1, 1, 1]) 3975808f684SSatish Balay boundary.setDimension(self.DIM - 1) 3985808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 3995808f684SSatish Balay 4005808f684SSatish Balay# -------------------------------------------------------------------- 4015808f684SSatish Balay 402728cfed7SksagiyamPETSC_DIR = petsc4py.get_config()['PETSC_DIR'] 403728cfed7Sksagiyam 4046f336411SStefano Zampini 405728cfed7Sksagiyamdef check_dtype(method): 406728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 407728cfed7Sksagiyam if PETSc.ScalarType is PETSc.ComplexType: 4086f336411SStefano Zampini return None 409728cfed7Sksagiyam return method(self, *args, **kwargs) 4106f336411SStefano Zampini 411728cfed7Sksagiyam return wrapper 412728cfed7Sksagiyam 4136f336411SStefano Zampini 414728cfed7Sksagiyamdef check_package(method): 415728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 4166f336411SStefano Zampini if not PETSc.Sys.hasExternalPackage('hdf5'): 4176f336411SStefano Zampini return None 4186f336411SStefano Zampini if self.PARTITIONERTYPE != 'simple' and not PETSc.Sys.hasExternalPackage( 4196f336411SStefano Zampini self.PARTITIONERTYPE 4206f336411SStefano Zampini ): 4216f336411SStefano Zampini return None 422728cfed7Sksagiyam return method(self, *args, **kwargs) 4236f336411SStefano Zampini 424728cfed7Sksagiyam return wrapper 425728cfed7Sksagiyam 4266f336411SStefano Zampini 427728cfed7Sksagiyamdef check_nsize(method): 428728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 429728cfed7Sksagiyam if PETSc.COMM_WORLD.size != self.NSIZE: 4306f336411SStefano Zampini return None 431728cfed7Sksagiyam return method(self, *args, **kwargs) 4326f336411SStefano Zampini 433728cfed7Sksagiyam return wrapper 434728cfed7Sksagiyam 4356f336411SStefano Zampini 4366f336411SStefano Zampiniclass BaseTestPlexHDF5: 437728cfed7Sksagiyam NSIZE = 4 438728cfed7Sksagiyam NTIMES = 3 439728cfed7Sksagiyam 440728cfed7Sksagiyam def tearDown(self): 441728cfed7Sksagiyam if not PETSc.COMM_WORLD.rank: 442728cfed7Sksagiyam if os.path.exists(self.outfile()): 443728cfed7Sksagiyam os.remove(self.outfile()) 444728cfed7Sksagiyam if os.path.exists(self.tmp_output_file()): 445728cfed7Sksagiyam os.remove(self.tmp_output_file()) 446728cfed7Sksagiyam 447728cfed7Sksagiyam def _name(self): 4486f336411SStefano Zampini return f'{self.SUFFIX}_outformat-{self.OUTFORMAT}_{self.PARTITIONERTYPE}' 449728cfed7Sksagiyam 450728cfed7Sksagiyam def infile(self): 4516f336411SStefano Zampini return os.path.join( 4526f336411SStefano Zampini PETSC_DIR, 'share/petsc/datafiles/', 'meshes/blockcylinder-50.h5' 4536f336411SStefano Zampini ) 454728cfed7Sksagiyam 455728cfed7Sksagiyam def outfile(self): 4566f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.h5' % self._name()) 457728cfed7Sksagiyam 458728cfed7Sksagiyam def informat(self): 459728cfed7Sksagiyam return PETSc.Viewer.Format.HDF5_XDMF 460728cfed7Sksagiyam 461728cfed7Sksagiyam def outformat(self): 4626f336411SStefano Zampini d = { 4636f336411SStefano Zampini 'hdf5_petsc': PETSc.Viewer.Format.HDF5_PETSC, 4646f336411SStefano Zampini 'hdf5_xdmf': PETSc.Viewer.Format.HDF5_XDMF, 4656f336411SStefano Zampini } 466728cfed7Sksagiyam return d[self.OUTFORMAT] 467728cfed7Sksagiyam 468728cfed7Sksagiyam def partitionerType(self): 4696f336411SStefano Zampini d = { 4706f336411SStefano Zampini 'simple': PETSc.Partitioner.Type.SIMPLE, 4716f336411SStefano Zampini 'ptscotch': PETSc.Partitioner.Type.PTSCOTCH, 4726f336411SStefano Zampini 'parmetis': PETSc.Partitioner.Type.PARMETIS, 4736f336411SStefano Zampini } 474728cfed7Sksagiyam return d[self.PARTITIONERTYPE] 475728cfed7Sksagiyam 476728cfed7Sksagiyam def ref_output_file(self): 4776f336411SStefano Zampini return os.path.join( 4786f336411SStefano Zampini PETSC_DIR, 4796f336411SStefano Zampini 'src/dm/impls/plex/tutorials/', 4806f336411SStefano Zampini 'output/ex5_%s.out' % self._name(), 4816f336411SStefano Zampini ) 482728cfed7Sksagiyam 483728cfed7Sksagiyam def tmp_output_file(self): 4846f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.out' % self._name()) 485728cfed7Sksagiyam 486728cfed7Sksagiyam def outputText(self, msg, comm): 487728cfed7Sksagiyam if not comm.rank: 488728cfed7Sksagiyam with open(self.tmp_output_file(), 'a') as f: 489728cfed7Sksagiyam f.write(msg) 490728cfed7Sksagiyam 491728cfed7Sksagiyam def outputPlex(self, plex): 492afa732d8SStefano Zampini txtvwr = PETSc.Viewer().createASCII( 493afa732d8SStefano Zampini self.tmp_output_file(), mode='a', comm=plex.comm 494afa732d8SStefano Zampini ) 495afa732d8SStefano Zampini plex.view(viewer=txtvwr) 496afa732d8SStefano Zampini txtvwr.destroy() 497728cfed7Sksagiyam 498728cfed7Sksagiyam @check_dtype 499728cfed7Sksagiyam @check_package 500728cfed7Sksagiyam @check_nsize 501728cfed7Sksagiyam def testViewLoadCycle(self): 502afa732d8SStefano Zampini if importlib.util.find_spec('mpi4py') is None: 503afa732d8SStefano Zampini self.skipTest('mpi4py') # throws special exception to signal test skip 504728cfed7Sksagiyam grank = PETSc.COMM_WORLD.rank 505728cfed7Sksagiyam for i in range(self.NTIMES): 506728cfed7Sksagiyam if i == 0: 507728cfed7Sksagiyam infname = self.infile() 508728cfed7Sksagiyam informt = self.informat() 509728cfed7Sksagiyam else: 510728cfed7Sksagiyam infname = self.outfile() 511728cfed7Sksagiyam informt = self.outformat() 512728cfed7Sksagiyam if self.HETEROGENEOUS: 5136f336411SStefano Zampini mycolor = grank > self.NTIMES - i 514728cfed7Sksagiyam else: 515728cfed7Sksagiyam mycolor = 0 516728cfed7Sksagiyam mpicomm = PETSc.COMM_WORLD.tompi4py() 517728cfed7Sksagiyam comm = PETSc.Comm(comm=mpicomm.Split(color=mycolor, key=grank)) 518728cfed7Sksagiyam if mycolor == 0: 5196f336411SStefano Zampini self.outputText('Begin cycle %d\n' % i, comm) 520728cfed7Sksagiyam plex = PETSc.DMPlex() 521728cfed7Sksagiyam vwr = PETSc.ViewerHDF5() 522728cfed7Sksagiyam # Create plex 523728cfed7Sksagiyam plex.create(comm=comm) 5246f336411SStefano Zampini plex.setName('DMPlex Object') 525728cfed7Sksagiyam # Load data from XDMF into dm in parallel 526728cfed7Sksagiyam vwr.create(infname, mode='r', comm=comm) 527728cfed7Sksagiyam vwr.pushFormat(format=informt) 528728cfed7Sksagiyam plex.load(viewer=vwr) 5296f336411SStefano Zampini plex.setOptionsPrefix('loaded_') 530e600fa54SMatthew G. Knepley plex.distributeSetDefault(False) 531728cfed7Sksagiyam plex.setFromOptions() 532728cfed7Sksagiyam vwr.popFormat() 533728cfed7Sksagiyam vwr.destroy() 534728cfed7Sksagiyam self.outputPlex(plex) 535728cfed7Sksagiyam # Test DM is indeed distributed 536728cfed7Sksagiyam flg = plex.isDistributed() 5376f336411SStefano Zampini self.outputText( 5386f336411SStefano Zampini 'Loaded mesh distributed? %s\n' % str(flg).upper(), comm 5396f336411SStefano Zampini ) 540728cfed7Sksagiyam # Interpolate 541728cfed7Sksagiyam plex.interpolate() 5426f336411SStefano Zampini plex.setOptionsPrefix('interpolated_') 543728cfed7Sksagiyam plex.setFromOptions() 544728cfed7Sksagiyam self.outputPlex(plex) 545728cfed7Sksagiyam # Redistribute 546728cfed7Sksagiyam part = plex.getPartitioner() 547728cfed7Sksagiyam part.setType(self.partitionerType()) 548afa732d8SStefano Zampini sf = plex.distribute(overlap=0) 549afa732d8SStefano Zampini if sf: 550afa732d8SStefano Zampini sf.destroy() 5516f336411SStefano Zampini part.destroy() 5526f336411SStefano Zampini plex.setName('DMPlex Object') 5536f336411SStefano Zampini plex.setOptionsPrefix('redistributed_') 554728cfed7Sksagiyam plex.setFromOptions() 555728cfed7Sksagiyam self.outputPlex(plex) 556728cfed7Sksagiyam # Save redistributed dm to XDMF in parallel 557728cfed7Sksagiyam vwr.create(self.outfile(), mode='w', comm=comm) 558728cfed7Sksagiyam vwr.pushFormat(format=self.outformat()) 5596f336411SStefano Zampini plex.setName('DMPlex Object') 560728cfed7Sksagiyam plex.view(viewer=vwr) 561728cfed7Sksagiyam vwr.popFormat() 562728cfed7Sksagiyam vwr.destroy() 563728cfed7Sksagiyam # Destroy plex 564728cfed7Sksagiyam plex.destroy() 5656f336411SStefano Zampini self.outputText('End cycle %d\n--------\n' % i, comm) 566afa732d8SStefano Zampini comm.tompi4py().Free() 567728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 568728cfed7Sksagiyam # Check that the output is identical to that of plex/tutorial/ex5.c. 5696f336411SStefano Zampini self.assertTrue( 5706f336411SStefano Zampini filecmp.cmp(self.tmp_output_file(), self.ref_output_file(), shallow=False), 571690e8b0dSJames Wright f'Contents of the files not the same. Reference file: {self.ref_output_file()}', 5726f336411SStefano Zampini ) 573728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 574728cfed7Sksagiyam 5756f336411SStefano Zampini 576728cfed7Sksagiyamclass BaseTestPlexHDF5Homogeneous(BaseTestPlexHDF5): 577728cfed7Sksagiyam """Test save on N / load on N.""" 5786f336411SStefano Zampini 579728cfed7Sksagiyam SUFFIX = 0 580728cfed7Sksagiyam HETEROGENEOUS = False 581728cfed7Sksagiyam 5826f336411SStefano Zampini 583728cfed7Sksagiyamclass BaseTestPlexHDF5Heterogeneous(BaseTestPlexHDF5): 584728cfed7Sksagiyam """Test save on N / load on M.""" 5856f336411SStefano Zampini 586728cfed7Sksagiyam SUFFIX = 1 587728cfed7Sksagiyam HETEROGENEOUS = True 588728cfed7Sksagiyam 5896f336411SStefano Zampini 5906f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHomogeneous( 5916f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 5926f336411SStefano Zampini): 5936f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 5946f336411SStefano Zampini PARTITIONERTYPE = 'simple' 5956f336411SStefano Zampini 596728cfed7Sksagiyam 597728cfed7Sksagiyam""" 598728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 599728cfed7Sksagiyamin a sequence in a single session. 600728cfed7Sksagiyam 601728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 602728cfed7Sksagiyam unittest.TestCase): 603728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 604728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 605728cfed7Sksagiyam""" 606728cfed7Sksagiyam 607728cfed7Sksagiyam 6086f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHomogeneous( 6096f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 6106f336411SStefano Zampini): 6116f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6126f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6136f336411SStefano Zampini 6146f336411SStefano Zampini 6156f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHomogeneous(BaseTestPlexHDF5Homogeneous, unittest.TestCase): 6166f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6176f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6186f336411SStefano Zampini 619728cfed7Sksagiyam 620728cfed7Sksagiyam""" 621728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 622728cfed7Sksagiyamin a sequence in a single session. 623728cfed7Sksagiyam 624728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 625728cfed7Sksagiyam unittest.TestCase): 626728cfed7Sksagiyam OUTFORMAT = "hdf5_xdmf" 627728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 628728cfed7Sksagiyam""" 629728cfed7Sksagiyam 630728cfed7Sksagiyam 6316f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHomogeneous( 6326f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 6336f336411SStefano Zampini): 6346f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6356f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6366f336411SStefano Zampini 6376f336411SStefano Zampini 6386f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHeterogeneous( 6396f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6406f336411SStefano Zampini): 6416f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6426f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6436f336411SStefano Zampini 644728cfed7Sksagiyam 645728cfed7Sksagiyam""" 646728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 647728cfed7Sksagiyamin a sequence in a single session. 648728cfed7Sksagiyam 649728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous, 650728cfed7Sksagiyam unittest.TestCase): 651728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 652728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 653728cfed7Sksagiyam""" 654728cfed7Sksagiyam 655728cfed7Sksagiyam 6566f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHeterogeneous( 6576f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6586f336411SStefano Zampini): 6596f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6606f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 661728cfed7Sksagiyam 662728cfed7Sksagiyam 6636f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHeterogeneous( 6646f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6656f336411SStefano Zampini): 6666f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6676f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6686f336411SStefano Zampini 6696f336411SStefano Zampini 6706f336411SStefano Zampiniclass TestPlexHDF5XDMFPTScotchHeterogeneous( 6716f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6726f336411SStefano Zampini): 6736f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6746f336411SStefano Zampini PARTITIONERTYPE = 'ptscotch' 6756f336411SStefano Zampini 6766f336411SStefano Zampini 6776f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHeterogeneous( 6786f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6796f336411SStefano Zampini): 6806f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6816f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6826f336411SStefano Zampini 683728cfed7Sksagiyam 684728cfed7Sksagiyam# -------------------------------------------------------------------- 685728cfed7Sksagiyam 6865808f684SSatish Balayif __name__ == '__main__': 6875808f684SSatish Balay unittest.main() 688