1728cfed7Sksagiyamimport petsc4py 25808f684SSatish Balayfrom petsc4py import PETSc 35808f684SSatish Balayimport unittest 4728cfed7Sksagiyamimport os 5728cfed7Sksagiyamimport filecmp 65808f684SSatish Balayimport numpy as np 7*6f336411SStefano Zampiniimport importlib 85808f684SSatish Balay 95808f684SSatish Balay# -------------------------------------------------------------------- 105808f684SSatish Balay 11e77db20cSJoe WallworkERR_ARG_OUTOFRANGE = 63 125808f684SSatish Balay 135808f684SSatish Balay 14*6f336411SStefano Zampiniclass BaseTestPlex: 155808f684SSatish Balay COMM = PETSc.COMM_WORLD 165808f684SSatish Balay DIM = 1 175808f684SSatish Balay CELLS = [[0, 1], [1, 2]] 18*6f336411SStefano Zampini COORDS = [[0.0], [0.5], [1.0]] 195808f684SSatish Balay COMP = 1 205808f684SSatish Balay DOFS = [1, 0] 215808f684SSatish Balay 225808f684SSatish Balay def setUp(self): 23*6f336411SStefano Zampini self.plex = PETSc.DMPlex().createFromCellList( 24*6f336411SStefano Zampini self.DIM, self.CELLS, self.COORDS, comm=self.COMM 25*6f336411SStefano 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) 38*6f336411SStefano 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() 90*6f336411SStefano Zampini entity_dofs = [ 91*6f336411SStefano Zampini self.plex.getStratumSize('depth', d) * self.DOFS[d] 92*6f336411SStefano Zampini for d in range(self.DIM + 1) 93*6f336411SStefano 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() 114*6f336411SStefano Zampini if pEnd - pStart == 0: 115*6f336411SStefano Zampini return 116439f958dSVaclav Hapla 117*6f336411SStefano Zampini self.assertFalse(self.plex.hasLabel('boundary')) 118*6f336411SStefano Zampini self.plex.markBoundaryFaces('boundary') 119*6f336411SStefano Zampini self.assertTrue(self.plex.hasLabel('boundary')) 1205808f684SSatish Balay 121*6f336411SStefano 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: 125*6f336411SStefano Zampini self.plex.setLabelValue('boundary', p, 1) 1265808f684SSatish Balay 1275808f684SSatish Balay for p in range(pStart, pEnd): 128*6f336411SStefano Zampini if self.plex.getLabelValue('boundary', p) != 1: 129*6f336411SStefano Zampini self.plex.setLabelValue('boundary', p, 2) 1305808f684SSatish Balay 131*6f336411SStefano Zampini numBoundary = self.plex.getStratumSize('boundary', 1) 132*6f336411SStefano 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): 138*6f336411SStefano Zampini if self.DIM == 1: 139*6f336411SStefano Zampini return 140d6a8d7c6SJoe Wallwork self.plex.distribute() 141*6f336411SStefano Zampini if self.CELLS is None and not self.plex.isSimplex(): 142*6f336411SStefano Zampini return 143b59e092eSJoe Wallwork self.plex.orient() 144d6a8d7c6SJoe Wallwork 145d6a8d7c6SJoe Wallwork h_min = 1.0e-30 146*6f336411SStefano Zampini h_max = 1.0e30 147*6f336411SStefano 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()) 176*6f336411SStefano Zampini self.assertTrue(self.plex.metricGetVerbosity() == -1) 177*6f336411SStefano Zampini self.assertTrue(self.plex.metricGetNumIterations() == 3) 178*6f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMinimumMagnitude(), h_min)) 179*6f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMaximumMagnitude(), h_max)) 180*6f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetMaximumAnisotropy(), a_max)) 181*6f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetTargetComplexity(), target)) 182*6f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetNormalizationOrder(), p)) 183*6f336411SStefano Zampini self.assertTrue(np.isclose(self.plex.metricGetGradationFactor(), beta)) 184*6f336411SStefano 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 192*6f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric1.array)) 1935d6e921eSJoe Wallwork self.plex.metricIntersection2(metric1, metric2, metric) 194*6f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric2.array)) 19555a74a43SLisandro Dalcin self.plex.metricEnforceSPD(metric, metric1, det[0]) 196*6f336411SStefano Zampini self.assertTrue(np.allclose(metric.array, metric1.array)) 197*6f336411SStefano Zampini 198*6f336411SStefano Zampini if self.DIM == 2 and PETSc.COMM_WORLD.getSize() > 6: 199*6f336411SStefano Zampini # Error with 7 processes in 2D: normalization factor is -1 200*6f336411SStefano Zampini return 201*6f336411SStefano Zampini 202*6f336411SStefano Zampini self.plex.metricNormalize( 203*6f336411SStefano Zampini metric, metric1, det[0], restrictSizes=False, restrictAnisotropy=False 204*6f336411SStefano Zampini ) 2055d6e921eSJoe Wallwork metric2.scale(pow(target, 2.0 / self.DIM)) 206*6f336411SStefano Zampini self.assertTrue(np.allclose(metric1.array, metric2.array)) 2075808f684SSatish Balay 2085808f684SSatish Balay def testAdapt(self): 209*6f336411SStefano Zampini if self.DIM == 1: 210*6f336411SStefano Zampini return 211*6f336411SStefano Zampini if self.DIM == 3 and PETSc.COMM_WORLD.getSize() > 4: 212*6f336411SStefano Zampini # Error with 5 processes in 3D 213*6f336411SStefano Zampini # ---------------------------- 214*6f336411SStefano Zampini # Warning: MMG5_mmgIntextmet: Unable to diagonalize at least 1 metric. 215*6f336411SStefano Zampini # Error: MMG3D_defsiz_ani: unable to intersect metrics at point 8. 216*6f336411SStefano Zampini # Metric undefined. Exit program. 217*6f336411SStefano Zampini # MMG remeshing problem. Exit program. 218*6f336411SStefano Zampini return 219d03c5e66SJoe Wallwork self.plex.orient() 220d03c5e66SJoe Wallwork plex = self.plex.refine() 221d03c5e66SJoe Wallwork plex.distribute() 222*6f336411SStefano Zampini if self.CELLS is None and not plex.isSimplex(): 223*6f336411SStefano Zampini return 224*6f336411SStefano Zampini if sum(self.DOFS) > 1: 225*6f336411SStefano Zampini return 226d03c5e66SJoe Wallwork metric = plex.metricCreateUniform(9.0) 2275808f684SSatish Balay try: 228*6f336411SStefano Zampini newplex = plex.adaptMetric(metric, '') 229*6f336411SStefano Zampini newplex.destroy() 2305808f684SSatish Balay except PETSc.Error as exc: 231*6f336411SStefano Zampini if exc.ierr != ERR_ARG_OUTOFRANGE: 232*6f336411SStefano Zampini raise 2335808f684SSatish Balay 2345808f684SSatish Balay 2355808f684SSatish Balay# -------------------------------------------------------------------- 2365808f684SSatish Balay 237*6f336411SStefano Zampini 2385808f684SSatish Balayclass BaseTestPlex_2D(BaseTestPlex): 2395808f684SSatish Balay DIM = 2 240*6f336411SStefano Zampini CELLS = [ 241*6f336411SStefano Zampini [0, 1, 3], 242*6f336411SStefano Zampini [1, 3, 4], 243*6f336411SStefano Zampini [1, 2, 4], 244*6f336411SStefano Zampini [2, 4, 5], 245*6f336411SStefano Zampini [3, 4, 6], 246*6f336411SStefano Zampini [4, 6, 7], 247*6f336411SStefano Zampini [4, 5, 7], 248*6f336411SStefano Zampini [5, 7, 8], 249*6f336411SStefano Zampini ] 250*6f336411SStefano Zampini COORDS = [ 251*6f336411SStefano Zampini [0.0, 0.0], 252*6f336411SStefano Zampini [0.5, 0.0], 253*6f336411SStefano Zampini [1.0, 0.0], 254*6f336411SStefano Zampini [0.0, 0.5], 255*6f336411SStefano Zampini [0.5, 0.5], 256*6f336411SStefano Zampini [1.0, 0.5], 257*6f336411SStefano Zampini [0.0, 1.0], 258*6f336411SStefano Zampini [0.5, 1.0], 259*6f336411SStefano Zampini [1.0, 1.0], 260*6f336411SStefano Zampini ] 2615808f684SSatish Balay DOFS = [1, 0, 0] 2625808f684SSatish Balay 263*6f336411SStefano Zampini 2645808f684SSatish Balayclass BaseTestPlex_3D(BaseTestPlex): 2655808f684SSatish Balay DIM = 3 266*6f336411SStefano Zampini CELLS = [ 267*6f336411SStefano Zampini [0, 2, 3, 7], 268*6f336411SStefano Zampini [0, 2, 6, 7], 269*6f336411SStefano Zampini [0, 4, 6, 7], 270*6f336411SStefano Zampini [0, 1, 3, 7], 271*6f336411SStefano Zampini [0, 1, 5, 7], 272*6f336411SStefano Zampini [0, 4, 5, 7], 273*6f336411SStefano Zampini ] 274*6f336411SStefano Zampini COORDS = [ 275*6f336411SStefano Zampini [0.0, 0.0, 0.0], 276*6f336411SStefano Zampini [1.0, 0.0, 0.0], 277*6f336411SStefano Zampini [0.0, 1.0, 0.0], 278*6f336411SStefano Zampini [1.0, 1.0, 0.0], 279*6f336411SStefano Zampini [0.0, 0.0, 1.0], 280*6f336411SStefano Zampini [1.0, 0.0, 1.0], 281*6f336411SStefano Zampini [0.0, 1.0, 1.0], 282*6f336411SStefano Zampini [1.0, 1.0, 1.0], 283*6f336411SStefano Zampini ] 2845808f684SSatish Balay DOFS = [1, 0, 0, 0] 2855808f684SSatish Balay 286*6f336411SStefano Zampini 2875808f684SSatish Balay# -------------------------------------------------------------------- 2885808f684SSatish Balay 289*6f336411SStefano Zampini 2905808f684SSatish Balayclass TestPlex_1D(BaseTestPlex, unittest.TestCase): 2915808f684SSatish Balay pass 2925808f684SSatish Balay 2934aa747acSUmberto Zerbinati 294*6f336411SStefano Zampiniclass TestPlex_2D(BaseTestPlex_2D, unittest.TestCase): 2954aa747acSUmberto Zerbinati def testTransform(self): 2964aa747acSUmberto Zerbinati plex = self.plex 2974aa747acSUmberto Zerbinati cstart, cend = plex.getHeightStratum(0) 2984aa747acSUmberto Zerbinati tr = PETSc.DMPlexTransform().create(comm=PETSc.COMM_WORLD) 2994aa747acSUmberto Zerbinati tr.setType(PETSc.DMPlexTransformType.REFINEALFELD) 3004aa747acSUmberto Zerbinati tr.setDM(plex) 3014aa747acSUmberto Zerbinati tr.setUp() 3024aa747acSUmberto Zerbinati newplex = tr.apply(plex) 3034aa747acSUmberto Zerbinati tr.destroy() 3044aa747acSUmberto Zerbinati newcstart, newcend = newplex.getHeightStratum(0) 3054aa747acSUmberto Zerbinati newplex.destroy() 3064aa747acSUmberto Zerbinati self.assertTrue((newcend - newcstart) == 3 * (cend - cstart)) 3075808f684SSatish Balay 308*6f336411SStefano Zampini 3095808f684SSatish Balayclass TestPlex_3D(BaseTestPlex_3D, unittest.TestCase): 3105808f684SSatish Balay pass 3115808f684SSatish Balay 312*6f336411SStefano Zampini 3135808f684SSatish Balayclass TestPlex_2D_P3(BaseTestPlex_2D, unittest.TestCase): 3145808f684SSatish Balay DOFS = [1, 2, 1] 3155808f684SSatish Balay 316*6f336411SStefano Zampini 3175808f684SSatish Balayclass TestPlex_3D_P3(BaseTestPlex_3D, unittest.TestCase): 3185808f684SSatish Balay DOFS = [1, 2, 1, 0] 3195808f684SSatish Balay 320*6f336411SStefano Zampini 3215808f684SSatish Balayclass TestPlex_3D_P4(BaseTestPlex_3D, unittest.TestCase): 3225808f684SSatish Balay DOFS = [1, 3, 3, 1] 3235808f684SSatish Balay 324*6f336411SStefano Zampini 3255808f684SSatish Balayclass TestPlex_2D_BoxTensor(BaseTestPlex_2D, unittest.TestCase): 3265808f684SSatish Balay CELLS = None 3275808f684SSatish Balay COORDS = None 328*6f336411SStefano Zampini 3295808f684SSatish Balay def setUp(self): 3305808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3], simplex=False) 3315808f684SSatish Balay 332*6f336411SStefano Zampini 3335808f684SSatish Balayclass TestPlex_3D_BoxTensor(BaseTestPlex_3D, unittest.TestCase): 3345808f684SSatish Balay CELLS = None 3355808f684SSatish Balay COORDS = None 336*6f336411SStefano Zampini 3375808f684SSatish Balay def setUp(self): 3385808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([3, 3, 3], simplex=False) 3395808f684SSatish Balay 340*6f336411SStefano Zampini 341*6f336411SStefano Zampini# FIXME 3425808f684SSatish Balaytry: 3435808f684SSatish Balay raise PETSc.Error 3445808f684SSatish Balay PETSc.DMPlex().createBoxMesh([2, 2], simplex=True, comm=PETSc.COMM_SELF).destroy() 3455808f684SSatish Balayexcept PETSc.Error: 3465808f684SSatish Balay pass 3475808f684SSatish Balayelse: 348*6f336411SStefano Zampini 3495808f684SSatish Balay class TestPlex_2D_Box(BaseTestPlex_2D, unittest.TestCase): 3505808f684SSatish Balay CELLS = None 3515808f684SSatish Balay COORDS = None 352*6f336411SStefano Zampini 3535808f684SSatish Balay def setUp(self): 3545808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1], simplex=True) 3555808f684SSatish Balay 3565808f684SSatish Balay class TestPlex_2D_Boundary(BaseTestPlex_2D, unittest.TestCase): 3575808f684SSatish Balay CELLS = None 3585808f684SSatish Balay COORDS = None 359*6f336411SStefano Zampini 3605808f684SSatish Balay def setUp(self): 3615808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 362*6f336411SStefano Zampini boundary.createSquareBoundary([0.0, 0.0], [1.0, 1.0], [2, 2]) 3635808f684SSatish Balay boundary.setDimension(self.DIM - 1) 3645808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 3655808f684SSatish Balay 3665808f684SSatish Balay class TestPlex_3D_Box(BaseTestPlex_3D, unittest.TestCase): 3675808f684SSatish Balay CELLS = None 3685808f684SSatish Balay COORDS = None 369*6f336411SStefano Zampini 3705808f684SSatish Balay def setUp(self): 3715808f684SSatish Balay self.plex = PETSc.DMPlex().createBoxMesh([1, 1, 1], simplex=True) 3725808f684SSatish Balay 3735808f684SSatish Balay class TestPlex_3D_Boundary(BaseTestPlex_3D, unittest.TestCase): 3745808f684SSatish Balay CELLS = None 3755808f684SSatish Balay COORDS = None 376*6f336411SStefano Zampini 3775808f684SSatish Balay def setUp(self): 3785808f684SSatish Balay boundary = PETSc.DMPlex().create(self.COMM) 379*6f336411SStefano Zampini boundary.createCubeBoundary([0.0, 0.0, 0.0], [1.0, 1.0, 1.0], [1, 1, 1]) 3805808f684SSatish Balay boundary.setDimension(self.DIM - 1) 3815808f684SSatish Balay self.plex = PETSc.DMPlex().generate(boundary) 3825808f684SSatish Balay 3835808f684SSatish Balay# -------------------------------------------------------------------- 3845808f684SSatish Balay 385728cfed7SksagiyamPETSC_DIR = petsc4py.get_config()['PETSC_DIR'] 386728cfed7Sksagiyam 387*6f336411SStefano Zampini 388728cfed7Sksagiyamdef check_dtype(method): 389728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 390728cfed7Sksagiyam if PETSc.ScalarType is PETSc.ComplexType: 391*6f336411SStefano Zampini return None 392728cfed7Sksagiyam return method(self, *args, **kwargs) 393*6f336411SStefano Zampini 394728cfed7Sksagiyam return wrapper 395728cfed7Sksagiyam 396*6f336411SStefano Zampini 397728cfed7Sksagiyamdef check_package(method): 398728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 399*6f336411SStefano Zampini if not PETSc.Sys.hasExternalPackage('hdf5'): 400*6f336411SStefano Zampini return None 401*6f336411SStefano Zampini if self.PARTITIONERTYPE != 'simple' and not PETSc.Sys.hasExternalPackage( 402*6f336411SStefano Zampini self.PARTITIONERTYPE 403*6f336411SStefano Zampini ): 404*6f336411SStefano Zampini return None 405728cfed7Sksagiyam return method(self, *args, **kwargs) 406*6f336411SStefano Zampini 407728cfed7Sksagiyam return wrapper 408728cfed7Sksagiyam 409*6f336411SStefano Zampini 410728cfed7Sksagiyamdef check_nsize(method): 411728cfed7Sksagiyam def wrapper(self, *args, **kwargs): 412728cfed7Sksagiyam if PETSc.COMM_WORLD.size != self.NSIZE: 413*6f336411SStefano Zampini return None 414728cfed7Sksagiyam return method(self, *args, **kwargs) 415*6f336411SStefano Zampini 416728cfed7Sksagiyam return wrapper 417728cfed7Sksagiyam 418*6f336411SStefano Zampini 419*6f336411SStefano Zampiniclass BaseTestPlexHDF5: 420728cfed7Sksagiyam NSIZE = 4 421728cfed7Sksagiyam NTIMES = 3 422728cfed7Sksagiyam 423728cfed7Sksagiyam def setUp(self): 424728cfed7Sksagiyam self.txtvwr = PETSc.Viewer() 425728cfed7Sksagiyam 426728cfed7Sksagiyam def tearDown(self): 427728cfed7Sksagiyam if not PETSc.COMM_WORLD.rank: 428728cfed7Sksagiyam if os.path.exists(self.outfile()): 429728cfed7Sksagiyam os.remove(self.outfile()) 430728cfed7Sksagiyam if os.path.exists(self.tmp_output_file()): 431728cfed7Sksagiyam os.remove(self.tmp_output_file()) 432728cfed7Sksagiyam self.txtvwr = None 433728cfed7Sksagiyam 434728cfed7Sksagiyam def _name(self): 435*6f336411SStefano Zampini return f'{self.SUFFIX}_outformat-{self.OUTFORMAT}_{self.PARTITIONERTYPE}' 436728cfed7Sksagiyam 437728cfed7Sksagiyam def infile(self): 438*6f336411SStefano Zampini return os.path.join( 439*6f336411SStefano Zampini PETSC_DIR, 'share/petsc/datafiles/', 'meshes/blockcylinder-50.h5' 440*6f336411SStefano Zampini ) 441728cfed7Sksagiyam 442728cfed7Sksagiyam def outfile(self): 443*6f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.h5' % self._name()) 444728cfed7Sksagiyam 445728cfed7Sksagiyam def informat(self): 446728cfed7Sksagiyam return PETSc.Viewer.Format.HDF5_XDMF 447728cfed7Sksagiyam 448728cfed7Sksagiyam def outformat(self): 449*6f336411SStefano Zampini d = { 450*6f336411SStefano Zampini 'hdf5_petsc': PETSc.Viewer.Format.HDF5_PETSC, 451*6f336411SStefano Zampini 'hdf5_xdmf': PETSc.Viewer.Format.HDF5_XDMF, 452*6f336411SStefano Zampini } 453728cfed7Sksagiyam return d[self.OUTFORMAT] 454728cfed7Sksagiyam 455728cfed7Sksagiyam def partitionerType(self): 456*6f336411SStefano Zampini d = { 457*6f336411SStefano Zampini 'simple': PETSc.Partitioner.Type.SIMPLE, 458*6f336411SStefano Zampini 'ptscotch': PETSc.Partitioner.Type.PTSCOTCH, 459*6f336411SStefano Zampini 'parmetis': PETSc.Partitioner.Type.PARMETIS, 460*6f336411SStefano Zampini } 461728cfed7Sksagiyam return d[self.PARTITIONERTYPE] 462728cfed7Sksagiyam 463728cfed7Sksagiyam def ref_output_file(self): 464*6f336411SStefano Zampini return os.path.join( 465*6f336411SStefano Zampini PETSC_DIR, 466*6f336411SStefano Zampini 'src/dm/impls/plex/tutorials/', 467*6f336411SStefano Zampini 'output/ex5_%s.out' % self._name(), 468*6f336411SStefano Zampini ) 469728cfed7Sksagiyam 470728cfed7Sksagiyam def tmp_output_file(self): 471*6f336411SStefano Zampini return os.path.join('./temp_test_dmplex_%s.out' % self._name()) 472728cfed7Sksagiyam 473728cfed7Sksagiyam def outputText(self, msg, comm): 474728cfed7Sksagiyam if not comm.rank: 475728cfed7Sksagiyam with open(self.tmp_output_file(), 'a') as f: 476728cfed7Sksagiyam f.write(msg) 477728cfed7Sksagiyam 478728cfed7Sksagiyam def outputPlex(self, plex): 479*6f336411SStefano Zampini self.txtvwr.createASCII(self.tmp_output_file(), mode='a', comm=plex.comm) 480728cfed7Sksagiyam plex.view(viewer=self.txtvwr) 481728cfed7Sksagiyam self.txtvwr.destroy() 482728cfed7Sksagiyam 483728cfed7Sksagiyam @check_dtype 484728cfed7Sksagiyam @check_package 485728cfed7Sksagiyam @check_nsize 486728cfed7Sksagiyam def testViewLoadCycle(self): 487728cfed7Sksagiyam grank = PETSc.COMM_WORLD.rank 488728cfed7Sksagiyam for i in range(self.NTIMES): 489728cfed7Sksagiyam if i == 0: 490728cfed7Sksagiyam infname = self.infile() 491728cfed7Sksagiyam informt = self.informat() 492728cfed7Sksagiyam else: 493728cfed7Sksagiyam infname = self.outfile() 494728cfed7Sksagiyam informt = self.outformat() 495728cfed7Sksagiyam if self.HETEROGENEOUS: 496*6f336411SStefano Zampini mycolor = grank > self.NTIMES - i 497728cfed7Sksagiyam else: 498728cfed7Sksagiyam mycolor = 0 499*6f336411SStefano Zampini if importlib.util.find_spec('mpi4py') is None: 500f89ec98fSSatish Balay self.skipTest('mpi4py') # throws special exception to signal test skip 501728cfed7Sksagiyam mpicomm = PETSc.COMM_WORLD.tompi4py() 502728cfed7Sksagiyam comm = PETSc.Comm(comm=mpicomm.Split(color=mycolor, key=grank)) 503728cfed7Sksagiyam if mycolor == 0: 504*6f336411SStefano 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) 509*6f336411SStefano 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) 514*6f336411SStefano 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() 522*6f336411SStefano Zampini self.outputText( 523*6f336411SStefano Zampini 'Loaded mesh distributed? %s\n' % str(flg).upper(), comm 524*6f336411SStefano Zampini ) 525728cfed7Sksagiyam # Interpolate 526728cfed7Sksagiyam plex.interpolate() 527*6f336411SStefano Zampini plex.setOptionsPrefix('interpolated_') 528728cfed7Sksagiyam plex.setFromOptions() 529728cfed7Sksagiyam self.outputPlex(plex) 530728cfed7Sksagiyam # Redistribute 531728cfed7Sksagiyam part = plex.getPartitioner() 532728cfed7Sksagiyam part.setType(self.partitionerType()) 533*6f336411SStefano Zampini plex.distribute(overlap=0) 534*6f336411SStefano Zampini part.destroy() 535*6f336411SStefano Zampini plex.setName('DMPlex Object') 536*6f336411SStefano Zampini plex.setOptionsPrefix('redistributed_') 537728cfed7Sksagiyam plex.setFromOptions() 538728cfed7Sksagiyam self.outputPlex(plex) 539728cfed7Sksagiyam # Save redistributed dm to XDMF in parallel 540728cfed7Sksagiyam vwr.create(self.outfile(), mode='w', comm=comm) 541728cfed7Sksagiyam vwr.pushFormat(format=self.outformat()) 542*6f336411SStefano Zampini plex.setName('DMPlex Object') 543728cfed7Sksagiyam plex.view(viewer=vwr) 544728cfed7Sksagiyam vwr.popFormat() 545728cfed7Sksagiyam vwr.destroy() 546728cfed7Sksagiyam # Destroy plex 547728cfed7Sksagiyam plex.destroy() 548*6f336411SStefano Zampini self.outputText('End cycle %d\n--------\n' % i, comm) 549728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 550728cfed7Sksagiyam # Check that the output is identical to that of plex/tutorial/ex5.c. 551*6f336411SStefano Zampini self.assertTrue( 552*6f336411SStefano Zampini filecmp.cmp(self.tmp_output_file(), self.ref_output_file(), shallow=False), 553*6f336411SStefano Zampini 'Contents of the files not the same.', 554*6f336411SStefano Zampini ) 555728cfed7Sksagiyam PETSc.COMM_WORLD.Barrier() 556728cfed7Sksagiyam 557*6f336411SStefano Zampini 558728cfed7Sksagiyamclass BaseTestPlexHDF5Homogeneous(BaseTestPlexHDF5): 559728cfed7Sksagiyam """Test save on N / load on N.""" 560*6f336411SStefano Zampini 561728cfed7Sksagiyam SUFFIX = 0 562728cfed7Sksagiyam HETEROGENEOUS = False 563728cfed7Sksagiyam 564*6f336411SStefano Zampini 565728cfed7Sksagiyamclass BaseTestPlexHDF5Heterogeneous(BaseTestPlexHDF5): 566728cfed7Sksagiyam """Test save on N / load on M.""" 567*6f336411SStefano Zampini 568728cfed7Sksagiyam SUFFIX = 1 569728cfed7Sksagiyam HETEROGENEOUS = True 570728cfed7Sksagiyam 571*6f336411SStefano Zampini 572*6f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHomogeneous( 573*6f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 574*6f336411SStefano Zampini): 575*6f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 576*6f336411SStefano Zampini PARTITIONERTYPE = 'simple' 577*6f336411SStefano Zampini 578728cfed7Sksagiyam 579728cfed7Sksagiyam""" 580728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 581728cfed7Sksagiyamin a sequence in a single session. 582728cfed7Sksagiyam 583728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 584728cfed7Sksagiyam unittest.TestCase): 585728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 586728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 587728cfed7Sksagiyam""" 588728cfed7Sksagiyam 589728cfed7Sksagiyam 590*6f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHomogeneous( 591*6f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 592*6f336411SStefano Zampini): 593*6f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 594*6f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 595*6f336411SStefano Zampini 596*6f336411SStefano Zampini 597*6f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHomogeneous(BaseTestPlexHDF5Homogeneous, unittest.TestCase): 598*6f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 599*6f336411SStefano Zampini PARTITIONERTYPE = 'simple' 600*6f336411SStefano Zampini 601728cfed7Sksagiyam 602728cfed7Sksagiyam""" 603728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 604728cfed7Sksagiyamin a sequence in a single session. 605728cfed7Sksagiyam 606728cfed7Sksagiyamclass TestPlexHDF5XDMFPTScotchHomogeneous(BaseTestPlexHDF5Homogeneous, 607728cfed7Sksagiyam unittest.TestCase): 608728cfed7Sksagiyam OUTFORMAT = "hdf5_xdmf" 609728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 610728cfed7Sksagiyam""" 611728cfed7Sksagiyam 612728cfed7Sksagiyam 613*6f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHomogeneous( 614*6f336411SStefano Zampini BaseTestPlexHDF5Homogeneous, unittest.TestCase 615*6f336411SStefano Zampini): 616*6f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 617*6f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 618*6f336411SStefano Zampini 619*6f336411SStefano Zampini 620*6f336411SStefano Zampiniclass TestPlexHDF5PETSCSimpleHeterogeneous( 621*6f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 622*6f336411SStefano Zampini): 623*6f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 624*6f336411SStefano Zampini PARTITIONERTYPE = 'simple' 625*6f336411SStefano Zampini 626728cfed7Sksagiyam 627728cfed7Sksagiyam""" 628728cfed7SksagiyamSkipping. PTScotch produces different distributions when run 629728cfed7Sksagiyamin a sequence in a single session. 630728cfed7Sksagiyam 631728cfed7Sksagiyamclass TestPlexHDF5PETSCPTScotchHeterogeneous(BaseTestPlexHDF5Heterogeneous, 632728cfed7Sksagiyam unittest.TestCase): 633728cfed7Sksagiyam OUTFORMAT = "hdf5_petsc" 634728cfed7Sksagiyam PARTITIONERTYPE = "ptscotch" 635728cfed7Sksagiyam""" 636728cfed7Sksagiyam 637728cfed7Sksagiyam 638*6f336411SStefano Zampiniclass TestPlexHDF5PETSCParmetisHeterogeneous( 639*6f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 640*6f336411SStefano Zampini): 641*6f336411SStefano Zampini OUTFORMAT = 'hdf5_petsc' 642*6f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 643728cfed7Sksagiyam 644728cfed7Sksagiyam 645*6f336411SStefano Zampiniclass TestPlexHDF5XDMFSimpleHeterogeneous( 646*6f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 647*6f336411SStefano Zampini): 648*6f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 649*6f336411SStefano Zampini PARTITIONERTYPE = 'simple' 650*6f336411SStefano Zampini 651*6f336411SStefano Zampini 652*6f336411SStefano Zampiniclass TestPlexHDF5XDMFPTScotchHeterogeneous( 653*6f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 654*6f336411SStefano Zampini): 655*6f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 656*6f336411SStefano Zampini PARTITIONERTYPE = 'ptscotch' 657*6f336411SStefano Zampini 658*6f336411SStefano Zampini 659*6f336411SStefano Zampiniclass TestPlexHDF5XDMFParmetisHeterogeneous( 660*6f336411SStefano Zampini BaseTestPlexHDF5Heterogeneous, unittest.TestCase 661*6f336411SStefano Zampini): 662*6f336411SStefano Zampini OUTFORMAT = 'hdf5_xdmf' 663*6f336411SStefano Zampini PARTITIONERTYPE = 'parmetis' 664*6f336411SStefano Zampini 665728cfed7Sksagiyam 666728cfed7Sksagiyam# -------------------------------------------------------------------- 667728cfed7Sksagiyam 6685808f684SSatish Balayif __name__ == '__main__': 6695808f684SSatish Balay unittest.main() 670