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 137*71f1c950SStefano Zampini def testLocalSubmesh(self): 138*71f1c950SStefano Zampini for ovl in [0, 1, 2]: 139*71f1c950SStefano Zampini plex = self.plex.refine() 140*71f1c950SStefano Zampini sf = plex.distribute(overlap=ovl) 141*71f1c950SStefano Zampini if sf: 142*71f1c950SStefano Zampini sf.destroy() 143*71f1c950SStefano Zampini gis = plex.getCellNumbering() 144*71f1c950SStefano Zampini 145*71f1c950SStefano Zampini for ignore in [True, False]: 146*71f1c950SStefano Zampini locplex, _ = plex.filter(comm=PETSc.COMM_SELF, ignoreHalo=ignore) 147*71f1c950SStefano Zampini lis = locplex.getCellNumbering() 148*71f1c950SStefano Zampini if ignore: 149*71f1c950SStefano Zampini self.assertEqual( 150*71f1c950SStefano Zampini lis.getLocalSize(), len(np.where(gis.getIndices() > -1)[0]) 151*71f1c950SStefano Zampini ) 152*71f1c950SStefano Zampini else: 153*71f1c950SStefano Zampini self.assertEqual(lis.getLocalSize(), gis.getLocalSize()) 154*71f1c950SStefano Zampini lis.destroy() 155*71f1c950SStefano Zampini locplex.destroy() 156*71f1c950SStefano Zampini gis.destroy() 157*71f1c950SStefano Zampini plex.destroy() 158*71f1c950SStefano Zampini 159d6a8d7c6SJoe Wallwork def testMetric(self): 1606f336411SStefano Zampini if self.DIM == 1: 1616f336411SStefano Zampini return 162d6a8d7c6SJoe Wallwork self.plex.distribute() 1636f336411SStefano Zampini if self.CELLS is None and not self.plex.isSimplex(): 1646f336411SStefano Zampini return 165b59e092eSJoe Wallwork self.plex.orient() 166d6a8d7c6SJoe Wallwork 167d6a8d7c6SJoe Wallwork h_min = 1.0e-30 1686f336411SStefano Zampini h_max = 1.0e30 1696f336411SStefano Zampini a_max = 1.0e10 1705d6e921eSJoe Wallwork target = 8.0 171d6a8d7c6SJoe Wallwork p = 1.0 172358f35a7SJoe Wallwork beta = 1.3 173a5745b59SJoe Wallwork hausd = 0.01 1740e99b0e2SJoe Wallwork self.plex.metricSetUniform(False) 175d6a8d7c6SJoe Wallwork self.plex.metricSetIsotropic(False) 176d6a8d7c6SJoe Wallwork self.plex.metricSetRestrictAnisotropyFirst(False) 177358f35a7SJoe Wallwork self.plex.metricSetNoInsertion(False) 178358f35a7SJoe Wallwork self.plex.metricSetNoSwapping(False) 179358f35a7SJoe Wallwork self.plex.metricSetNoMovement(False) 1808d4b236aSJoe Wallwork self.plex.metricSetNoSurf(False) 181358f35a7SJoe Wallwork self.plex.metricSetVerbosity(-1) 182358f35a7SJoe Wallwork self.plex.metricSetNumIterations(3) 183d6a8d7c6SJoe Wallwork self.plex.metricSetMinimumMagnitude(h_min) 184d6a8d7c6SJoe Wallwork self.plex.metricSetMaximumMagnitude(h_max) 185d6a8d7c6SJoe Wallwork self.plex.metricSetMaximumAnisotropy(a_max) 186d6a8d7c6SJoe Wallwork self.plex.metricSetTargetComplexity(target) 187d6a8d7c6SJoe Wallwork self.plex.metricSetNormalizationOrder(p) 188358f35a7SJoe Wallwork self.plex.metricSetGradationFactor(beta) 189a5745b59SJoe Wallwork self.plex.metricSetHausdorffNumber(hausd) 190d6a8d7c6SJoe Wallwork 1910e99b0e2SJoe Wallwork self.assertFalse(self.plex.metricIsUniform()) 192d6a8d7c6SJoe Wallwork self.assertFalse(self.plex.metricIsIsotropic()) 193d6a8d7c6SJoe Wallwork self.assertFalse(self.plex.metricRestrictAnisotropyFirst()) 194358f35a7SJoe Wallwork self.assertFalse(self.plex.metricNoInsertion()) 195358f35a7SJoe Wallwork self.assertFalse(self.plex.metricNoSwapping()) 196358f35a7SJoe Wallwork self.assertFalse(self.plex.metricNoMovement()) 1978d4b236aSJoe Wallwork self.assertFalse(self.plex.metricNoSurf()) 1986f336411SStefano Zampini self.assertTrue(self.plex.metricGetVerbosity() == -1) 1996f336411SStefano Zampini self.assertTrue(self.plex.metricGetNumIterations() == 3) 2006f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMinimumMagnitude(), h_min)) 2016f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMaximumMagnitude(), h_max)) 2026f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMaximumAnisotropy(), a_max)) 2036f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetTargetComplexity(), target)) 2046f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetNormalizationOrder(), p)) 2056f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetGradationFactor(), beta)) 2066f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetHausdorffNumber(), hausd)) 207d6a8d7c6SJoe Wallwork 2085d6e921eSJoe Wallwork metric1 = self.plex.metricCreateUniform(0.5) 2095d6e921eSJoe Wallwork metric2 = self.plex.metricCreateUniform(1.0) 2105d6e921eSJoe Wallwork metric = self.plex.metricCreate() 2115d6e921eSJoe Wallwork det = self.plex.metricDeterminantCreate() 2125d6e921eSJoe Wallwork self.plex.metricAverage2(metric1, metric2, metric) 2135d6e921eSJoe Wallwork metric1.array[:] *= 1.5 2146f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric1.array)) 2155d6e921eSJoe Wallwork self.plex.metricIntersection2(metric1, metric2, metric) 2166f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric2.array)) 21755a74a43SLisandro Dalcin self.plex.metricEnforceSPD(metric, metric1, det[0]) 2186f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric1.array)) 2196f336411SStefano Zampini 2206f336411SStefano Zampini if self.DIM == 2 and PETSc.COMM_WORLD.getSize() > 6: 2216f336411SStefano Zampini # Error with 7 processes in 2D: normalization factor is -1 2226f336411SStefano Zampini return 2236f336411SStefano Zampini 2246f336411SStefano Zampini self.plex.metricNormalize( 2256f336411SStefano Zampini metric, metric1, det[0], restrictSizes=False, restrictAnisotropy=False 2266f336411SStefano Zampini ) 2275d6e921eSJoe Wallwork metric2.scale(pow(target, 2.0 / self.DIM)) 2286f336411SStefano Zampini self.assertTrue(np.allclose(metric1.array, metric2.array)) 2295808f684SSatish Balay 2305808f684SSatish Balay def testAdapt(self): 2316f336411SStefano Zampini if self.DIM == 1: 2326f336411SStefano Zampini return 2336f336411SStefano Zampini if self.DIM == 3 and PETSc.COMM_WORLD.getSize() > 4: 2346f336411SStefano Zampini # Error with 5 processes in 3D 2356f336411SStefano Zampini # ---------------------------- 2366f336411SStefano Zampini # Warning: MMG5_mmgIntextmet: Unable to diagonalize at least 1 metric. 2376f336411SStefano Zampini # Error: MMG3D_defsiz_ani: unable to intersect metrics at point 8. 2386f336411SStefano Zampini # Metric undefined. Exit program. 2396f336411SStefano Zampini # MMG remeshing problem. Exit program. 2406f336411SStefano Zampini return 241d03c5e66SJoe Wallwork self.plex.orient() 242d03c5e66SJoe Wallwork plex = self.plex.refine() 243d03c5e66SJoe Wallwork plex.distribute() 2446f336411SStefano Zampini if self.CELLS is None and not plex.isSimplex(): 2456f336411SStefano Zampini return 2466f336411SStefano Zampini if sum(self.DOFS) > 1: 2476f336411SStefano Zampini return 248d03c5e66SJoe Wallwork metric = plex.metricCreateUniform(9.0) 2495808f684SSatish Balay try: 2506f336411SStefano Zampini newplex = plex.adaptMetric(metric, '') 251afa732d8SStefano Zampini plex.destroy() 2526f336411SStefano Zampini newplex.destroy() 2535808f684SSatish Balay except PETSc.Error as exc: 254afa732d8SStefano Zampini plex.destroy() 2556f336411SStefano Zampini if exc.ierr != ERR_ARG_OUTOFRANGE: 2566f336411SStefano Zampini raise 2575808f684SSatish Balay 258c039638dSMatthew G. Knepley def testNatural(self): 259c039638dSMatthew G. Knepley dim = self.plex.getDimension() 260c039638dSMatthew G. Knepley ct = self.plex.getCellType(0) 261c039638dSMatthew G. Knepley fe = PETSc.FE().createByCell(dim, 1, ct) 262c039638dSMatthew G. Knepley self.plex.setField(0, fe) 263c039638dSMatthew G. Knepley self.plex.createDS() 264c039638dSMatthew G. Knepley self.plex.setUseNatural(True) 265c039638dSMatthew G. Knepley self.plex.distribute() 266c039638dSMatthew G. Knepley self.plex.view() 267c039638dSMatthew G. Knepley gv = self.plex.createGlobalVec() 268c039638dSMatthew G. Knepley nv = self.plex.createNaturalVec() 269c039638dSMatthew G. Knepley self.plex.globalToNaturalBegin(gv, nv) 270c039638dSMatthew G. Knepley self.plex.globalToNaturalEnd(gv, nv) 271c039638dSMatthew G. Knepley self.plex.naturalToGlobalBegin(nv, gv) 272c039638dSMatthew G. Knepley self.plex.naturalToGlobalEnd(nv, gv) 2735808f684SSatish Balay 2745808f684SSatish Balay# -------------------------------------------------------------------- 2755808f684SSatish Balay 2766f336411SStefano Zampini 2775808f684SSatish Balayclass BaseTestPlex_2D(BaseTestPlex): 2785808f684SSatish Balay DIM = 2 2796f336411SStefano Zampini CELLS = [ 2806f336411SStefano Zampini [0, 1, 3], 2816f336411SStefano Zampini [1, 3, 4], 2826f336411SStefano Zampini [1, 2, 4], 2836f336411SStefano Zampini [2, 4, 5], 2846f336411SStefano Zampini [3, 4, 6], 2856f336411SStefano Zampini [4, 6, 7], 2866f336411SStefano Zampini [4, 5, 7], 2876f336411SStefano Zampini [5, 7, 8], 2886f336411SStefano Zampini ] 2896f336411SStefano Zampini COORDS = [ 2906f336411SStefano Zampini [0.0, 0.0], 2916f336411SStefano Zampini [0.5, 0.0], 2926f336411SStefano Zampini [1.0, 0.0], 2936f336411SStefano Zampini [0.0, 0.5], 2946f336411SStefano Zampini [0.5, 0.5], 2956f336411SStefano Zampini [1.0, 0.5], 2966f336411SStefano Zampini [0.0, 1.0], 2976f336411SStefano Zampini [0.5, 1.0], 2986f336411SStefano Zampini [1.0, 1.0], 2996f336411SStefano Zampini ] 3005808f684SSatish Balay DOFS = [1, 0, 0] 3015808f684SSatish Balay 3026f336411SStefano Zampini 3035808f684SSatish Balayclass BaseTestPlex_3D(BaseTestPlex): 3045808f684SSatish Balay DIM = 3 3056f336411SStefano Zampini CELLS = [ 3066f336411SStefano Zampini [0, 2, 3, 7], 3076f336411SStefano Zampini [0, 2, 6, 7], 3086f336411SStefano Zampini [0, 4, 6, 7], 3096f336411SStefano Zampini [0, 1, 3, 7], 3106f336411SStefano Zampini [0, 1, 5, 7], 3116f336411SStefano Zampini [0, 4, 5, 7], 3126f336411SStefano Zampini ] 3136f336411SStefano Zampini COORDS = [ 3146f336411SStefano Zampini [0.0, 0.0, 0.0], 3156f336411SStefano Zampini [1.0, 0.0, 0.0], 3166f336411SStefano Zampini [0.0, 1.0, 0.0], 3176f336411SStefano Zampini [1.0, 1.0, 0.0], 3186f336411SStefano Zampini [0.0, 0.0, 1.0], 3196f336411SStefano Zampini [1.0, 0.0, 1.0], 3206f336411SStefano Zampini [0.0, 1.0, 1.0], 3216f336411SStefano Zampini [1.0, 1.0, 1.0], 3226f336411SStefano Zampini ] 3235808f684SSatish Balay DOFS = [1, 0, 0, 0] 3245808f684SSatish Balay 3256f336411SStefano Zampini 3265808f684SSatish Balay# -------------------------------------------------------------------- 3275808f684SSatish Balay 3286f336411SStefano Zampini 3295808f684SSatish Balayclass TestPlex_1D(BaseTestPlex, unittest.TestCase): 3305808f684SSatish Balay pass 3315808f684SSatish Balay 3324aa747acSUmberto Zerbinati 3336f336411SStefano Zampiniclass TestPlex_2D(BaseTestPlex_2D, unittest.TestCase): 3344aa747acSUmberto Zerbinati def testTransform(self): 3354aa747acSUmberto Zerbinati plex = self.plex 3364aa747acSUmberto Zerbinati cstart, cend = plex.getHeightStratum(0) 3374aa747acSUmberto Zerbinati tr = PETSc.DMPlexTransform().create(comm=PETSc.COMM_WORLD) 3384aa747acSUmberto Zerbinati tr.setType(PETSc.DMPlexTransformType.REFINEALFELD) 3394aa747acSUmberto Zerbinati tr.setDM(plex) 3404aa747acSUmberto Zerbinati tr.setUp() 3414aa747acSUmberto Zerbinati newplex = tr.apply(plex) 3424aa747acSUmberto Zerbinati tr.destroy() 3434aa747acSUmberto Zerbinati newcstart, newcend = newplex.getHeightStratum(0) 3444aa747acSUmberto Zerbinati newplex.destroy() 3454aa747acSUmberto Zerbinati self.assertTrue((newcend - newcstart) == 3 * (cend - cstart)) 3465808f684SSatish Balay 3476f336411SStefano Zampini 3485808f684SSatish Balayclass TestPlex_3D(BaseTestPlex_3D, unittest.TestCase): 3495808f684SSatish Balay pass 3505808f684SSatish Balay 3516f336411SStefano Zampini 3525808f684SSatish Balayclass TestPlex_2D_P3(BaseTestPlex_2D, unittest.TestCase): 3535808f684SSatish Balay DOFS = [1, 2, 1] 3545808f684SSatish Balay 3556f336411SStefano Zampini 3565808f684SSatish Balayclass TestPlex_3D_P3(BaseTestPlex_3D, unittest.TestCase): 3575808f684SSatish Balay DOFS = [1, 2, 1, 0] 3585808f684SSatish Balay 3596f336411SStefano Zampini 3605808f684SSatish Balayclass TestPlex_3D_P4(BaseTestPlex_3D, unittest.TestCase): 3615808f684SSatish Balay DOFS = [1, 3, 3, 1] 3625808f684SSatish Balay 3636f336411SStefano Zampini 3645808f684SSatish Balayclass TestPlex_2D_BoxTensor(BaseTestPlex_2D, unittest.TestCase): 3655808f684SSatish Balay CELLS = None 3665808f684SSatish Balay COORDS = None 3676f336411SStefano Zampini 3685808f684SSatish Balay def setUp(self): 3695808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3], simplex=False) 3705808f684SSatish Balay 3716f336411SStefano Zampini 3725808f684SSatish Balayclass TestPlex_3D_BoxTensor(BaseTestPlex_3D, unittest.TestCase): 3735808f684SSatish Balay CELLS = None 3745808f684SSatish Balay COORDS = None 3756f336411SStefano Zampini 3765808f684SSatish Balay def setUp(self): 3775808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3, 3], simplex=False) 3785808f684SSatish Balay 3796f336411SStefano Zampini 3806f336411SStefano Zampini# FIXME 3815808f684SSatish Balaytry: 3825808f684SSatish Balay raise PETSc.Error 3835808f684SSatish Balay PETSc.DMPlex().createBoxMesh([2, 2], simplex=True, comm=PETSc.COMM_SELF).destroy() 3845808f684SSatish Balayexcept PETSc.Error: 3855808f684SSatish Balay pass 3865808f684SSatish Balayelse: 3876f336411SStefano Zampini 3885808f684SSatish Balay class TestPlex_2D_Box(BaseTestPlex_2D, unittest.TestCase): 3895808f684SSatish Balay CELLS = None 3905808f684SSatish Balay COORDS = None 3916f336411SStefano Zampini 3925808f684SSatish Balay def setUp(self): 3935808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1], simplex=True) 3945808f684SSatish Balay 3955808f684SSatish Balay class TestPlex_2D_Boundary(BaseTestPlex_2D, unittest.TestCase): 3965808f684SSatish Balay CELLS = None 3975808f684SSatish Balay COORDS = None 3986f336411SStefano Zampini 3995808f684SSatish Balay def setUp(self): 4005808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 4016f336411SStefano Zampini boundary.createSquareBoundary([0.0, 0.0], [1.0, 1.0], [2, 2]) 4025808f684SSatish Balay boundary.setDimension(self.DIM - 1) 4035808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 4045808f684SSatish Balay 4055808f684SSatish Balay class TestPlex_3D_Box(BaseTestPlex_3D, unittest.TestCase): 4065808f684SSatish Balay CELLS = None 4075808f684SSatish Balay COORDS = None 4086f336411SStefano Zampini 4095808f684SSatish Balay def setUp(self): 4105808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1, 1], simplex=True) 4115808f684SSatish Balay 4125808f684SSatish Balay class TestPlex_3D_Boundary(BaseTestPlex_3D, unittest.TestCase): 4135808f684SSatish Balay CELLS = None 4145808f684SSatish Balay COORDS = None 4156f336411SStefano Zampini 4165808f684SSatish Balay def setUp(self): 4175808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 4186f336411SStefano Zampini boundary.createCubeBoundary([0.0, 0.0, 0.0], [1.0, 1.0, 1.0], [1, 1, 1]) 4195808f684SSatish Balay boundary.setDimension(self.DIM - 1) 4205808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 4215808f684SSatish Balay 4225808f684SSatish Balay# -------------------------------------------------------------------- 4235808f684SSatish Balay 424728cfed7SksagiyamPETSC_DIR = petsc4py.get_config()['PETSC_DIR'] 425728cfed7Sksagiyam 4266f336411SStefano Zampini 427728cfed7Sksagiyamdef check_dtype(method): 428728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 429728cfed7Sksagiyam if PETSc.ScalarType is PETSc.ComplexType: 4306f336411SStefano Zampini return None 431728cfed7Sksagiyam return method(self, *args, **kwargs) 4326f336411SStefano Zampini 433728cfed7Sksagiyam return wrapper 434728cfed7Sksagiyam 4356f336411SStefano Zampini 436728cfed7Sksagiyamdef check_package(method): 437728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 4386f336411SStefano Zampini if not PETSc.Sys.hasExternalPackage('hdf5'): 4396f336411SStefano Zampini return None 4406f336411SStefano Zampini if self.PARTITIONERTYPE != 'simple' and not PETSc.Sys.hasExternalPackage( 4416f336411SStefano Zampini self.PARTITIONERTYPE 4426f336411SStefano Zampini ): 4436f336411SStefano Zampini return None 444728cfed7Sksagiyam return method(self, *args, **kwargs) 4456f336411SStefano Zampini 446728cfed7Sksagiyam return wrapper 447728cfed7Sksagiyam 4486f336411SStefano Zampini 449728cfed7Sksagiyamdef check_nsize(method): 450728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 451728cfed7Sksagiyam if PETSc.COMM_WORLD.size != self.NSIZE: 4526f336411SStefano Zampini return None 453728cfed7Sksagiyam return method(self, *args, **kwargs) 4546f336411SStefano Zampini 455728cfed7Sksagiyam return wrapper 456728cfed7Sksagiyam 4576f336411SStefano Zampini 4586f336411SStefano Zampiniclass BaseTestPlexHDF5: 459728cfed7Sksagiyam NSIZE = 4 460728cfed7Sksagiyam NTIMES = 3 461728cfed7Sksagiyam 462728cfed7Sksagiyam def tearDown(self): 463728cfed7Sksagiyam if not PETSc.COMM_WORLD.rank: 464728cfed7Sksagiyam if os.path.exists(self.outfile()): 465728cfed7Sksagiyam os.remove(self.outfile()) 466728cfed7Sksagiyam if os.path.exists(self.tmp_output_file()): 467728cfed7Sksagiyam os.remove(self.tmp_output_file()) 468728cfed7Sksagiyam 469728cfed7Sksagiyam def _name(self): 4706f336411SStefano Zampini return f'{self.SUFFIX}_outformat-{self.OUTFORMAT}_{self.PARTITIONERTYPE}' 471728cfed7Sksagiyam 472728cfed7Sksagiyam def infile(self): 4736f336411SStefano Zampini return os.path.join( 4746f336411SStefano Zampini PETSC_DIR, 'share/petsc/datafiles/', 'meshes/blockcylinder-50.h5' 4756f336411SStefano Zampini ) 476728cfed7Sksagiyam 477728cfed7Sksagiyam def outfile(self): 4786f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.h5' % self._name()) 479728cfed7Sksagiyam 480728cfed7Sksagiyam def informat(self): 481728cfed7Sksagiyam return PETSc.Viewer.Format.HDF5_XDMF 482728cfed7Sksagiyam 483728cfed7Sksagiyam def outformat(self): 4846f336411SStefano Zampini d = { 4856f336411SStefano Zampini 'hdf5_petsc': PETSc.Viewer.Format.HDF5_PETSC, 4866f336411SStefano Zampini 'hdf5_xdmf': PETSc.Viewer.Format.HDF5_XDMF, 4876f336411SStefano Zampini } 488728cfed7Sksagiyam return d[self.OUTFORMAT] 489728cfed7Sksagiyam 490728cfed7Sksagiyam def partitionerType(self): 4916f336411SStefano Zampini d = { 4926f336411SStefano Zampini 'simple': PETSc.Partitioner.Type.SIMPLE, 4936f336411SStefano Zampini 'ptscotch': PETSc.Partitioner.Type.PTSCOTCH, 4946f336411SStefano Zampini 'parmetis': PETSc.Partitioner.Type.PARMETIS, 4956f336411SStefano Zampini } 496728cfed7Sksagiyam return d[self.PARTITIONERTYPE] 497728cfed7Sksagiyam 498728cfed7Sksagiyam def ref_output_file(self): 4996f336411SStefano Zampini return os.path.join( 5006f336411SStefano Zampini PETSC_DIR, 5016f336411SStefano Zampini 'src/dm/impls/plex/tutorials/', 5026f336411SStefano Zampini 'output/ex5_%s.out' % self._name(), 5036f336411SStefano Zampini ) 504728cfed7Sksagiyam 505728cfed7Sksagiyam def tmp_output_file(self): 5066f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.out' % self._name()) 507728cfed7Sksagiyam 508728cfed7Sksagiyam def outputText(self, msg, comm): 509728cfed7Sksagiyam if not comm.rank: 510728cfed7Sksagiyam with open(self.tmp_output_file(), 'a') as f: 511728cfed7Sksagiyam f.write(msg) 512728cfed7Sksagiyam 513728cfed7Sksagiyam def outputPlex(self, plex): 514afa732d8SStefano Zampini txtvwr = PETSc.Viewer().createASCII( 515afa732d8SStefano Zampini self.tmp_output_file(), mode='a', comm=plex.comm 516afa732d8SStefano Zampini ) 517afa732d8SStefano Zampini plex.view(viewer=txtvwr) 518afa732d8SStefano Zampini txtvwr.destroy() 519728cfed7Sksagiyam 520728cfed7Sksagiyam @check_dtype 521728cfed7Sksagiyam @check_package 522728cfed7Sksagiyam @check_nsize 523728cfed7Sksagiyam def testViewLoadCycle(self): 524afa732d8SStefano Zampini if importlib.util.find_spec('mpi4py') is None: 525afa732d8SStefano Zampini self.skipTest('mpi4py') # throws special exception to signal test skip 526728cfed7Sksagiyam grank = PETSc.COMM_WORLD.rank 527728cfed7Sksagiyam for i in range(self.NTIMES): 528728cfed7Sksagiyam if i == 0: 529728cfed7Sksagiyam infname = self.infile() 530728cfed7Sksagiyam informt = self.informat() 531728cfed7Sksagiyam else: 532728cfed7Sksagiyam infname = self.outfile() 533728cfed7Sksagiyam informt = self.outformat() 534728cfed7Sksagiyam if self.HETEROGENEOUS: 5356f336411SStefano Zampini mycolor = grank > self.NTIMES - i 536728cfed7Sksagiyam else: 537728cfed7Sksagiyam mycolor = 0 538728cfed7Sksagiyam mpicomm = PETSc.COMM_WORLD.tompi4py() 539728cfed7Sksagiyam comm = PETSc.Comm(comm=mpicomm.Split(color=mycolor, key=grank)) 540728cfed7Sksagiyam if mycolor == 0: 5416f336411SStefano Zampini self.outputText('Begin cycle %d\n' % i, comm) 542728cfed7Sksagiyam plex = PETSc.DMPlex() 543728cfed7Sksagiyam vwr = PETSc.ViewerHDF5() 544728cfed7Sksagiyam # Create plex 545728cfed7Sksagiyam plex.create(comm=comm) 5466f336411SStefano Zampini plex.setName('DMPlex Object') 547728cfed7Sksagiyam # Load data from XDMF into dm in parallel 548728cfed7Sksagiyam vwr.create(infname, mode='r', comm=comm) 549728cfed7Sksagiyam vwr.pushFormat(format=informt) 550728cfed7Sksagiyam plex.load(viewer=vwr) 5516f336411SStefano Zampini plex.setOptionsPrefix('loaded_') 552e600fa54SMatthew G. Knepley plex.distributeSetDefault(False) 553728cfed7Sksagiyam plex.setFromOptions() 554728cfed7Sksagiyam vwr.popFormat() 555728cfed7Sksagiyam vwr.destroy() 556728cfed7Sksagiyam self.outputPlex(plex) 557728cfed7Sksagiyam # Test DM is indeed distributed 558728cfed7Sksagiyam flg = plex.isDistributed() 5596f336411SStefano Zampini self.outputText( 5606f336411SStefano Zampini 'Loaded mesh distributed? %s\n' % str(flg).upper(), comm 5616f336411SStefano Zampini ) 562728cfed7Sksagiyam # Interpolate 563728cfed7Sksagiyam plex.interpolate() 5646f336411SStefano Zampini plex.setOptionsPrefix('interpolated_') 565728cfed7Sksagiyam plex.setFromOptions() 566728cfed7Sksagiyam self.outputPlex(plex) 567728cfed7Sksagiyam # Redistribute 568728cfed7Sksagiyam part = plex.getPartitioner() 569728cfed7Sksagiyam part.setType(self.partitionerType()) 570afa732d8SStefano Zampini sf = plex.distribute(overlap=0) 571afa732d8SStefano Zampini if sf: 572afa732d8SStefano Zampini sf.destroy() 5736f336411SStefano Zampini part.destroy() 5746f336411SStefano Zampini plex.setName('DMPlex Object') 5756f336411SStefano Zampini plex.setOptionsPrefix('redistributed_') 576728cfed7Sksagiyam plex.setFromOptions() 577728cfed7Sksagiyam self.outputPlex(plex) 578728cfed7Sksagiyam # Save redistributed dm to XDMF in parallel 579728cfed7Sksagiyam vwr.create(self.outfile(), mode='w', comm=comm) 580728cfed7Sksagiyam vwr.pushFormat(format=self.outformat()) 5816f336411SStefano Zampini plex.setName('DMPlex Object') 582728cfed7Sksagiyam plex.view(viewer=vwr) 583728cfed7Sksagiyam vwr.popFormat() 584728cfed7Sksagiyam vwr.destroy() 585728cfed7Sksagiyam # Destroy plex 586728cfed7Sksagiyam plex.destroy() 5876f336411SStefano Zampini self.outputText('End cycle %d\n--------\n' % i, comm) 588afa732d8SStefano Zampini comm.tompi4py().Free() 589728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 590728cfed7Sksagiyam # Check that the output is identical to that of plex/tutorial/ex5.c. 5916f336411SStefano Zampini self.assertTrue( 5926f336411SStefano Zampini filecmp.cmp(self.tmp_output_file(), self.ref_output_file(), shallow=False), 593690e8b0dSJames Wright f'Contents of the files not the same. Reference file: {self.ref_output_file()}', 5946f336411SStefano Zampini ) 595728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 596728cfed7Sksagiyam 5976f336411SStefano Zampini 598728cfed7Sksagiyamclass BaseTestPlexHDF5Homogeneous(BaseTestPlexHDF5): 599728cfed7Sksagiyam """Test save on N / load on N.""" 6006f336411SStefano Zampini 601728cfed7Sksagiyam SUFFIX = 0 602728cfed7Sksagiyam HETEROGENEOUS = False 603728cfed7Sksagiyam 6046f336411SStefano Zampini 605728cfed7Sksagiyamclass BaseTestPlexHDF5Heterogeneous(BaseTestPlexHDF5): 606728cfed7Sksagiyam """Test save on N / load on M.""" 6076f336411SStefano Zampini 608728cfed7Sksagiyam SUFFIX = 1 609728cfed7Sksagiyam HETEROGENEOUS = True 610728cfed7Sksagiyam 6116f336411SStefano Zampini 6126f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHomogeneous( 6136f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 6146f336411SStefano Zampini): 6156f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6166f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6176f336411SStefano Zampini 618728cfed7Sksagiyam 619728cfed7Sksagiyam""" 620728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 621728cfed7Sksagiyamin a sequence in a single session. 622728cfed7Sksagiyam 623728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 624728cfed7Sksagiyam unittest.TestCase): 625728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 626728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 627728cfed7Sksagiyam""" 628728cfed7Sksagiyam 629728cfed7Sksagiyam 6306f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHomogeneous( 6316f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 6326f336411SStefano Zampini): 6336f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6346f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6356f336411SStefano Zampini 6366f336411SStefano Zampini 6376f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHomogeneous(BaseTestPlexHDF5Homogeneous, unittest.TestCase): 6386f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6396f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6406f336411SStefano Zampini 641728cfed7Sksagiyam 642728cfed7Sksagiyam""" 643728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 644728cfed7Sksagiyamin a sequence in a single session. 645728cfed7Sksagiyam 646728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 647728cfed7Sksagiyam unittest.TestCase): 648728cfed7Sksagiyam OUTFORMAT = "hdf5_xdmf" 649728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 650728cfed7Sksagiyam""" 651728cfed7Sksagiyam 652728cfed7Sksagiyam 6536f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHomogeneous( 6546f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 6556f336411SStefano Zampini): 6566f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6576f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 6586f336411SStefano Zampini 6596f336411SStefano Zampini 6606f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHeterogeneous( 6616f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6626f336411SStefano Zampini): 6636f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6646f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6656f336411SStefano Zampini 666728cfed7Sksagiyam 667728cfed7Sksagiyam""" 668728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 669728cfed7Sksagiyamin a sequence in a single session. 670728cfed7Sksagiyam 671728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous, 672728cfed7Sksagiyam unittest.TestCase): 673728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 674728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 675728cfed7Sksagiyam""" 676728cfed7Sksagiyam 677728cfed7Sksagiyam 6786f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHeterogeneous( 6796f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6806f336411SStefano Zampini): 6816f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 6826f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 683728cfed7Sksagiyam 684728cfed7Sksagiyam 6856f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHeterogeneous( 6866f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6876f336411SStefano Zampini): 6886f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6896f336411SStefano Zampini PARTITIONERTYPE = 'simple' 6906f336411SStefano Zampini 6916f336411SStefano Zampini 6926f336411SStefano Zampiniclass TestPlexHDF5XDMFPTScotchHeterogeneous( 6936f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 6946f336411SStefano Zampini): 6956f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 6966f336411SStefano Zampini PARTITIONERTYPE = 'ptscotch' 6976f336411SStefano Zampini 6986f336411SStefano Zampini 6996f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHeterogeneous( 7006f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 7016f336411SStefano Zampini): 7026f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 7036f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 7046f336411SStefano Zampini 705728cfed7Sksagiyam 706728cfed7Sksagiyam# -------------------------------------------------------------------- 707728cfed7Sksagiyam 7085808f684SSatish Balayif __name__ == '__main__': 7095808f684SSatish Balay unittest.main() 710