def pytest_runtest_teardown(item): """Collect garbage after every test to force calling destructors which might be collective""" # Do the normal teardown item.teardown() # Collect the garbage (call destructors collectively) del item # NOTE: How are we sure that 'item' does not hold references # to temporaries and someone else does not hold a reference # to 'item'?! Well, it seems that it works... gc.collect() MPI.barrier(MPI.comm_world)
def test_UnitCubeMeshDistributed(): """Create mesh of unit cube.""" mesh = UnitCubeMesh(MPI.comm_world, 5, 7, 9) assert mesh.num_entities_global(0) == 480 assert mesh.num_entities_global(3) == 1890 assert mesh.geometry.dim == 3 assert MPI.sum(mesh.mpi_comm(), mesh.topology.index_map(0).size_local) == 480
def test_mesh_function_assign_2D_cells(): mesh = UnitSquareMesh(MPI.comm_world, 3, 3) ncells = mesh.num_cells() f = MeshFunction("int", mesh, mesh.topology.dim, 0) for c in range(ncells): f.values[c] = ncells - c g = MeshValueCollection("int", mesh, 2) g.assign(f) assert ncells == len(f.values) assert ncells == g.size() f2 = MeshFunction("int", mesh, g, 0) for c in range(mesh.num_cells()): value = ncells - c assert value == g.get_value(c, 0) assert f2.values[c] == g.get_value(c, 0) h = MeshValueCollection("int", mesh, 2) global_indices = mesh.topology.index_map(2).global_indices(True) ncells_global = mesh.num_entities_global(2) for c in range(mesh.num_cells()): if global_indices[c] in [5, 8, 10]: continue value = ncells_global - global_indices[c] h.set_value(c, int(value)) f3 = MeshFunction("int", mesh, h, 0) values = f3.values values[values > ncells_global] = 0. assert MPI.sum(mesh.mpi_comm(), values.sum() * 1.0) == 140.
def test_gmsh_input_quad(order): pygmsh = pytest.importorskip("pygmsh") # Parameterize test if gmsh gets wider support R = 1 res = 0.2 if order == 2 else 0.2 algorithm = 2 if order == 2 else 5 element = "quad{0:d}".format(int((order + 1)**2)) geo = pygmsh.opencascade.Geometry() geo.add_raw_code("Mesh.ElementOrder={0:d};".format(order)) geo.add_ball([0, 0, 0], R, char_length=res) geo.add_raw_code("Recombine Surface {1};") geo.add_raw_code("Mesh.Algorithm = {0:d};".format(algorithm)) msh = pygmsh.generate_mesh(geo, verbose=True, dim=2) if order > 2: # Quads order > 3 have a gmsh specific ordering, and has to be permuted. msh_to_dolfin = np.array([0, 3, 11, 10, 1, 2, 6, 7, 4, 9, 12, 15, 5, 8, 13, 14]) cells = np.zeros(msh.cells_dict[element].shape) for i in range(len(cells)): for j in range(len(msh_to_dolfin)): cells[i, j] = msh.cells_dict[element][i, msh_to_dolfin[j]] else: # XDMF does not support higher order quads cells = permute_cell_ordering(msh.cells_dict[element], permutation_vtk_to_dolfin( CellType.quadrilateral, msh.cells_dict[element].shape[1])) mesh = Mesh(MPI.comm_world, CellType.quadrilateral, msh.points, cells, [], GhostMode.none) surface = assemble_scalar(1 * dx(mesh)) assert MPI.sum(mesh.mpi_comm(), surface) == pytest.approx(4 * np.pi * R * R, rel=1e-5)
def test_UnitSquareMeshDistributed(): """Create mesh of unit square.""" mesh = UnitSquareMesh(MPI.comm_world, 5, 7) assert mesh.num_entities_global(0) == 48 assert mesh.num_entities_global(2) == 70 assert mesh.geometry.dim == 2 assert MPI.sum(mesh.mpi_comm(), mesh.topology.index_map(0).size_local) == 48
def test_UnitHexMesh(): mesh = UnitCubeMesh(MPI.comm_world, 5, 7, 9, CellType.hexahedron) assert mesh.num_entities_global(0) == 480 assert mesh.num_entities_global(3) == 315 assert mesh.geometry.dim == 3 assert MPI.sum(mesh.mpi_comm(), mesh.topology.index_map(0).size_local) == 480
def test_UnitQuadMesh(): mesh = UnitSquareMesh(MPI.comm_world, 5, 7, CellType.quadrilateral) assert mesh.num_entities_global(0) == 48 assert mesh.num_entities_global(2) == 35 assert mesh.geometry.dim == 2 assert MPI.sum(mesh.mpi_comm(), mesh.topology.index_map(0).size_local) == 48
def test_mpi_atomicity(tempdir): comm_world = MPI.comm_world if MPI.size(comm_world) > 1: filename = os.path.join(tempdir, "mpiatomic.h5") with HDF5File(MPI.comm_world, filename, "w") as f: assert f.get_mpi_atomicity() is False f.set_mpi_atomicity(True) assert f.get_mpi_atomicity() is True
def test_third_order_tri(): # *---*---*---* 3--11--10--2 # | \ | | \ | # * * * * 8 7 15 13 # | \ | | \ | # * * * * 9 14 6 12 # | \ | | \ | # *---*---*---* 0--4---5---1 for H in (1.0, 2.0): for Z in (0.0, 0.5): L = 1 points = np.array([ [0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0, 1, 2, 3 [L / 3, 0, 0], [2 * L / 3, 0, 0], # 4, 5 [2 * L / 3, H / 3, 0], [L / 3, 2 * H / 3, 0], # 6, 7 [0, 2 * H / 3, 0], [0, H / 3, 0], # 8, 9 [2 * L / 3, H, Z], [L / 3, H, Z], # 10, 11 [L, H / 3, 0], [L, 2 * H / 3, 0], # 12, 13 [L / 3, H / 3, 0], # 14 [2 * L / 3, 2 * H / 3, 0] ]) # 15 cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 14], [1, 2, 3, 12, 13, 10, 11, 7, 6, 15]]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] degree = mesh.degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40})) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 9, 8, 3] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_topology_surface(cube): surface_vertex_markers = cube.topology.on_boundary(0) assert surface_vertex_markers n = 3 cube.create_entities(1) cube.create_connectivity(2, 1) surface_edge_markers = cube.topology.on_boundary(1) assert surface_edge_markers surface_facet_markers = cube.topology.on_boundary(2) sf_count = np.count_nonzero(np.array(surface_facet_markers)) assert MPI.sum(cube.mpi_comm(), sf_count) == n * n * 12
def test_save_and_read_mesh_value_collection_with_only_one_marked_entity( tempdir): ndiv = 2 filename = os.path.join(tempdir, "mesh_value_collection.h5") mesh = UnitCubeMesh(MPI.comm_world, ndiv, ndiv, ndiv) mvc = MeshValueCollection("size_t", mesh, 3) mesh.create_entities(3) if MPI.rank(mesh.mpi_comm()) == 0: mvc.set_value(0, 1) # write to file with HDF5File(mesh.mpi_comm(), filename, 'w') as f: f.write(mvc, "/mesh_value_collection") # read from file with HDF5File(mesh.mpi_comm(), filename, 'r') as f: mvc = f.read_mvc_size_t(mesh, "/mesh_value_collection") assert MPI.sum(mesh.mpi_comm(), mvc.size()) == 1 if MPI.rank(mesh.mpi_comm()) == 0: assert mvc.get_value(0, 0) == 1
def test_third_order_quad(L, H, Z): """Test by comparing integration of z+x*y against sympy/scipy integration of a quad element. Z>0 implies curved element. *---------* 3--8--9--2-22-23-17 | | | | | | | 11 14 15 7 26 27 21 | | | | | | | 10 12 13 6 24 25 20 | | | | | *---------* 0--4--5--1-18-19-16 """ points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0 1 2 3 [L / 3, 0, 0], [2 * L / 3, 0, 0], # 4 5 [L, H / 3, 0], [L, 2 * H / 3, 0], # 6 7 [L / 3, H, Z], [2 * L / 3, H, Z], # 8 9 [0, H / 3, 0], [0, 2 * H / 3, 0], # 10 11 [L / 3, H / 3, 0], [2 * L / 3, H / 3, 0], # 12 13 [L / 3, 2 * H / 3, 0], [2 * L / 3, 2 * H / 3, 0], # 14 15 [2 * L, 0, 0], [2 * L, H, Z], # 16 17 [4 * L / 3, 0, 0], [5 * L / 3, 0, 0], # 18 19 [2 * L, H / 3, 0], [2 * L, 2 * H / 3, 0], # 20 21 [4 * L / 3, H, Z], [5 * L / 3, H, Z], # 22 23 [4 * L / 3, H / 3, 0], [5 * L / 3, H / 3, 0], # 24 25 [4 * L / 3, 2 * H / 3, 0], [5 * L / 3, 2 * H / 3, 0]]) # 26 27 # Change to multiple cells when matthews dof-maps work for quads cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [1, 16, 17, 2, 18, 19, 20, 21, 22, 23, 6, 7, 24, 25, 26, 27]]) cells = permute_cell_ordering(cells, permutation_vtk_to_dolfin(CellType.quadrilateral, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.quadrilateral, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] # Interpolate function V = FunctionSpace(mesh, ("CG", 3)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 10, 11] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_insert_local(mesh, V): dm = V.dofmap index_map = dm.index_map assert index_map sp = cpp.fem.SparsityPatternBuilder.build(mesh.mpi_comm(), mesh, [dm._cpp_object, dm._cpp_object], True, False, False) sp.assemble() sp1 = cpp.la.SparsityPattern(mesh.mpi_comm(), [[sp], [sp]]) if (MPI.rank(mesh.mpi_comm()) == 0): print("\nPattern:") print(sp1.str(True)) sp1 = cpp.la.SparsityPattern(mesh.mpi_comm(), [[sp, sp]]) if (MPI.rank(mesh.mpi_comm()) == 0): print("\nPattern:") print(sp1.str(True)) sp1 = cpp.la.SparsityPattern(mesh.mpi_comm(), [[sp, sp], [sp, sp]]) if (MPI.rank(mesh.mpi_comm()) == 0): print("\nPattern:") print(sp1.str(True))
def test_fourth_order_tri(): L = 1 # *--*--*--*--* 3-21-20-19--2 # | \ | | \ | # * * * * * 10 9 24 23 18 # | \ | | \ | # * * * * * 11 15 8 22 17 # | \ | | \ | # * * * * * 12 13 14 7 16 # | \ | | \ | # *--*--*--*--* 0--4--5--6--1 for H in (1.0, 2.0): for Z in (0.0, 0.5): points = np.array( [[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0, 1, 2, 3 [L / 4, 0, 0], [L / 2, 0, 0], [3 * L / 4, 0, 0], # 4, 5, 6 [3 / 4 * L, H / 4, Z / 2], [L / 2, H / 2, 0], # 7, 8 [L / 4, 3 * H / 4, 0], [0, 3 * H / 4, 0], # 9, 10 [0, H / 2, 0], [0, H / 4, Z / 2], # 11, 12 [L / 4, H / 4, Z / 2], [L / 2, H / 4, Z / 2], [L / 4, H / 2, 0], # 13, 14, 15 [L, H / 4, Z / 2], [L, H / 2, 0], [L, 3 * H / 4, 0], # 16, 17, 18 [3 * L / 4, H, Z], [L / 2, H, Z], [L / 4, H, Z], # 19, 20, 21 [3 * L / 4, H / 2, 0], [3 * L / 4, 3 * H / 4, 0], # 22, 23 [L / 2, 3 * H / 4, 0]] # 24 ) cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [1, 2, 3, 16, 17, 18, 19, 20, 21, 9, 8, 7, 22, 23, 24]]) cells = permute_cell_ordering(cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] degree = mesh.degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 50})) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 10, 11, 12] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-4)
def test_save_and_read_vector(tempdir): filename = os.path.join(tempdir, "vector.h5") # Write to file local_range = MPI.local_range(MPI.comm_world, 305) x = PETSc.Vec() x.create(MPI.comm_world) x.setSizes((local_range[1] - local_range[0], None)) x.setFromOptions() x.set(1.2) with HDF5File(MPI.comm_world, filename, "w") as vector_file: vector_file.write(x, "/my_vector") # Read from file with HDF5File(MPI.comm_world, filename, "r") as vector_file: y = vector_file.read_vector(MPI.comm_world, "/my_vector", False) assert y.getSize() == x.getSize() x.axpy(-1.0, y) assert x.norm() == 0.0
def _create_tempdir(request): # Get directory name of test_foo.py file testfile = request.module.__file__ testfiledir = os.path.dirname(os.path.abspath(testfile)) # Construct name test_foo_tempdir from name test_foo.py testfilename = os.path.basename(testfile) outputname = testfilename.replace(".py", "_tempdir_{}".format( worker_id(request))) # Get function name test_something from test_foo.py function = request.function.__name__ # Join all of these to make a unique path for this test function basepath = os.path.join(testfiledir, outputname) path = os.path.join(basepath, function) # Add a sequence number to avoid collisions when tests are # otherwise parameterized if MPI.rank(MPI.comm_world) == 0: _create_tempdir._sequencenumber[path] += 1 sequencenumber = _create_tempdir._sequencenumber[path] sequencenumber = MPI.sum(MPI.comm_world, sequencenumber) else: sequencenumber = MPI.sum(MPI.comm_world, 0) path += "__" + str(sequencenumber) # Delete and re-create directory on root node if MPI.rank(MPI.comm_world) == 0: # First time visiting this basepath, delete the old and create # a new if basepath not in _create_tempdir._basepaths: _create_tempdir._basepaths.add(basepath) if os.path.exists(basepath): shutil.rmtree(basepath) # Make sure we have the base path test_foo_tempdir for # this test_foo.py file if not os.path.exists(basepath): os.mkdir(basepath) # Delete path from old test run if os.path.exists(path): shutil.rmtree(path) # Make sure we have the path for this test execution: # e.g. test_foo_tempdir/test_something__3 if not os.path.exists(path): os.mkdir(path) MPI.barrier(MPI.comm_world) return path
def test_second_order_quad(L, H, Z): """ Test by comparing integration of z+x*y against sympy/scipy integration of a quad element. Z>0 implies curved element. *-----* 3--6--2 | | | | | | 7 8 5 | | | | *-----* 0--4--1 """ points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], [L / 2, 0, 0], [L, H / 2, 0], [L / 2, H, Z], [0, H / 2, 0], [L / 2, H / 2, 0], [2 * L, 0, 0], [2 * L, H, Z]]) cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8]]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.quadrilateral, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.quadrilateral, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] # Interpolate function V = FunctionSpace(mesh, ("CG", 2)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 7] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_second_order_tri(): # Test second order mesh by computing volume of two cells # *-----*-----* 3----6-----2 # | \ | | \ | # | \ | | \ | # * * * 7 8 5 # | \ | | \ | # | \ | | \ | # *-----*-----* 0----4-----1 for H in (1.0, 2.0): for Z in (0.0, 0.5): L = 1 points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], [L / 2, 0, 0], [L, H / 2, 0], [L / 2, H, Z], [0, H / 2, 0], [L / 2, H / 2, 0]]) cells = np.array([[0, 1, 3, 4, 8, 7], [1, 2, 3, 5, 6, 8]]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] degree = mesh.degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar( u * dx(mesh, metadata={"quadrature_degree": 20})) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 7] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_manufactured_poisson(degree, filename, datadir): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ with XDMFFile(MPI.comm_world, os.path.join(datadir, filename)) as xdmf: mesh = xdmf.read_mesh(GhostMode.none) V = FunctionSpace(mesh, ("Lagrange", degree)) u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u), grad(v)) * dx # Get quadrature degree for bilinear form integrand (ignores effect # of non-affine map) a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1}) a.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a) # Source term x = SpatialCoordinate(mesh) u_exact = x[1]**degree f = -div(grad(u_exact)) # Set quadrature degree for linear form integrand (ignores effect of # non-affine map) L = inner(f, v) * dx(metadata={"quadrature_degree": -1}) L.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L) t0 = time.time() L = fem.Form(L) t1 = time.time() print("Linear form compile time:", t1 - t0) u_bc = Function(V) u_bc.interpolate(lambda x: x[1]**degree) # Create Dirichlet boundary condition mesh.create_connectivity_all() facetdim = mesh.topology.dim - 1 bndry_facets = np.where( np.array(mesh.topology.on_boundary(facetdim)) == 1)[0] bdofs = locate_dofs_topological(V, facetdim, bndry_facets) assert (len(bdofs) < V.dim()) bc = DirichletBC(u_bc, bdofs) t0 = time.time() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) t1 = time.time() print("Vector assembly time:", t1 - t0) t0 = time.time() a = fem.Form(a) t1 = time.time() print("Bilinear form compile time:", t1 - t0) t0 = time.time() A = assemble_matrix(a, [bc]) A.assemble() t1 = time.time() print("Matrix assembly time:", t1 - t0) # Create LU linear solver solver = PETSc.KSP().create(MPI.comm_world) solver.setType(PETSc.KSP.Type.PREONLY) solver.getPC().setType(PETSc.PC.Type.LU) solver.setOperators(A) # Solve t0 = time.time() uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) t1 = time.time() print("Linear solver time:", t1 - t0) M = (u_exact - uh)**2 * dx t0 = time.time() M = fem.Form(M) t1 = time.time() print("Error functional compile time:", t1 - t0) t0 = time.time() error = assemble_scalar(M) error = MPI.sum(mesh.mpi_comm(), error) t1 = time.time() print("Error assembly time:", t1 - t0) assert np.absolute(error) < 1.0e-14
# Set matrix operator solver.setOperators(A) # Compute solution solver.setMonitor(lambda ksp, its, rnorm: print( "Iteration: {}, rel. residual: {}".format(its, rnorm))) solver.solve(b, u.vector) solver.view() # Save solution to XDMF format file = XDMFFile(MPI.comm_world, "elasticity.xdmf") file.write(u) unorm = u.vector.norm() if MPI.rank(mesh.mpi_comm()) == 0: print("Solution vector norm:", unorm) # Save colored mesh partitions in VTK format if running in parallel # if MPI.size(mesh.mpi_comm()) > 1: # File("partitions.pvd") << MeshFunction("size_t", mesh, mesh.topology.dim, \ # MPI.rank(mesh.mpi_comm())) # Project and write stress field to post-processing file # W = TensorFunctionSpace(mesh, "Discontinuous Lagrange", 0) # stress = project(sigma(u), V=W) # File("stress.pvd") << stress # Plot solution # import matplotlib.pyplot as plt # import dolfinx.plotting
def test_cffi_assembly(): mesh = UnitSquareMesh(MPI.comm_world, 13, 13) V = FunctionSpace(mesh, ("Lagrange", 1)) if MPI.rank(mesh.mpi_comm()) == 0: from cffi import FFI ffibuilder = FFI() ffibuilder.set_source( "_cffi_kernelA", r""" #include <math.h> #include <stdalign.h> void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE3_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[2] * FE3_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[5] * FE3_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE3_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE3_C0_D01_Q1[0][0][1]; alignas(32) double sp[20]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = J_c0 / sp[2]; sp[4] = -1 * J_c1 / sp[2]; sp[5] = sp[3] * sp[3]; sp[6] = sp[3] * sp[4]; sp[7] = sp[4] * sp[4]; sp[8] = J_c3 / sp[2]; sp[9] = -1 * J_c2 / sp[2]; sp[10] = sp[9] * sp[9]; sp[11] = sp[8] * sp[9]; sp[12] = sp[8] * sp[8]; sp[13] = sp[5] + sp[10]; sp[14] = sp[6] + sp[11]; sp[15] = sp[12] + sp[7]; sp[16] = fabs(sp[2]); sp[17] = sp[13] * sp[16]; sp[18] = sp[14] * sp[16]; sp[19] = sp[15] * sp[16]; // UFLACS block mode: preintegrated A[0] = 0.5 * sp[19] + 0.5 * sp[18] + 0.5 * sp[18] + 0.5 * sp[17]; A[1] = -0.5 * sp[19] + -0.5 * sp[18]; A[2] = -0.5 * sp[18] + -0.5 * sp[17]; A[3] = -0.5 * sp[19] + -0.5 * sp[18]; A[4] = 0.5 * sp[19]; A[5] = 0.5 * sp[18]; A[6] = -0.5 * sp[18] + -0.5 * sp[17]; A[7] = 0.5 * sp[18]; A[8] = 0.5 * sp[17]; } void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE4_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[2] * FE4_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[5] * FE4_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE4_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE4_C0_D01_Q1[0][0][1]; alignas(32) double sp[4]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = fabs(sp[2]); // UFLACS block mode: preintegrated A[0] = 0.1666666666666667 * sp[3]; A[1] = 0.1666666666666667 * sp[3]; A[2] = 0.1666666666666667 * sp[3]; } """) ffibuilder.cdef(""" void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation); void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation); """) ffibuilder.compile(verbose=True) MPI.barrier(mesh.mpi_comm()) from _cffi_kernelA import ffi, lib a = cpp.fem.Form([V._cpp_object, V._cpp_object]) ptrA = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonA")) a.set_tabulate_tensor(FormIntegrals.Type.cell, -1, ptrA) L = cpp.fem.Form([V._cpp_object]) ptrL = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonL")) L.set_tabulate_tensor(FormIntegrals.Type.cell, -1, ptrL) A = dolfinx.fem.assemble_matrix(a) A.assemble() b = dolfinx.fem.assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) Anorm = A.norm(PETSc.NormType.FROBENIUS) bnorm = b.norm(PETSc.NormType.N2) assert (np.isclose(Anorm, 56.124860801609124)) assert (np.isclose(bnorm, 0.0739710713711999)) list_timings(MPI.comm_world, [TimingType.wall])
def test_volume_cells(mesh): num_cells = mesh.num_entities(mesh.topology.dim) v = cpp.mesh.volume_entities(mesh, range(num_cells), mesh.topology.dim) v = MPI.sum(mesh.mpi_comm(), v.sum()) assert v == pytest.approx(1.0, rel=1e-9)
# Copyright (C) 2014-2014 Aslak Wigdahl Bergersen # # This file is part of DOLFINX (https://www.fenicsproject.org) # # SPDX-License-Identifier: LGPL-3.0-or-later """Shared skips for unit tests involving dolfinx.""" import pytest from dolfinx import MPI from dolfinx.common import has_petsc_complex # Skips with respect to parallel or serial xfail_in_parallel = pytest.mark.xfail( MPI.size(MPI.comm_world) > 1, reason="This test does not yet work in parallel.") skip_in_parallel = pytest.mark.skipif( MPI.size(MPI.comm_world) > 1, reason="This test should only be run in serial.") # Skips with respect to the scalar type skip_if_complex = pytest.mark.skipif( has_petsc_complex, reason="This test does not work in complex mode.") xfail_if_complex = pytest.mark.xfail( has_petsc_complex, reason="This test does not work in complex mode.")
def test_UnitHexMesh_assemble(): mesh = UnitCubeMesh(MPI.comm_world, 6, 7, 5, CellType.hexahedron) vol = assemble_scalar(1 * dx(mesh)) vol = MPI.sum(mesh.mpi_comm(), vol) assert (vol == pytest.approx(1, rel=1e-9))
def test_nth_order_triangle(order): num_nodes = (order + 1) * (order + 2) / 2 cells = np.array([range(int(num_nodes))]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) if order == 1: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000]]) elif order == 2: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.50000, 0.50000, -0.25000], [0.00000, 0.50000, -0.25000]]) elif order == 3: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.33333, 0.00000, 0.00000], [0.66667, 0.00000, 0.00000], [0.66667, 0.33333, -0.11111], [0.33333, 0.66667, 0.11111], [0.00000, 0.66667, 0.11111], [0.00000, 0.33333, -0.11111], [0.33333, 0.33333, -0.11111]]) elif order == 4: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.25000, 0.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.75000, 0.00000, 0.00000], [0.75000, 0.25000, -0.06250], [0.50000, 0.50000, 0.06250], [0.25000, 0.75000, -0.06250], [0.00000, 0.75000, -0.06250], [0.00000, 0.50000, 0.06250], [0.00000, 0.25000, -0.06250], [0.25000, 0.25000, -0.06250], [0.50000, 0.25000, -0.06250], [0.25000, 0.50000, 0.06250]]) elif order == 5: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.20000, 0.00000, 0.00000], [0.40000, 0.00000, 0.00000], [0.60000, 0.00000, 0.00000], [0.80000, 0.00000, 0.00000], [0.80000, 0.20000, -0.04000], [0.60000, 0.40000, 0.04000], [0.40000, 0.60000, -0.04000], [0.20000, 0.80000, 0.04000], [0.00000, 0.80000, 0.04000], [0.00000, 0.60000, -0.04000], [0.00000, 0.40000, 0.04000], [0.00000, 0.20000, -0.04000], [0.20000, 0.20000, -0.04000], [0.60000, 0.20000, -0.04000], [0.20000, 0.60000, -0.04000], [0.40000, 0.20000, -0.04000], [0.40000, 0.40000, 0.04000], [0.20000, 0.40000, 0.04000]]) elif order == 6: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.16667, 0.00000, 0.00000], [0.33333, 0.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.66667, 0.00000, 0.00000], [0.83333, 0.00000, 0.00000], [0.83333, 0.16667, -0.00463], [0.66667, 0.33333, 0.00463], [0.50000, 0.50000, -0.00463], [0.33333, 0.66667, 0.00463], [0.16667, 0.83333, -0.00463], [0.00000, 0.83333, -0.00463], [0.00000, 0.66667, 0.00463], [0.00000, 0.50000, -0.00463], [0.00000, 0.33333, 0.00463], [0.00000, 0.16667, -0.00463], [0.16667, 0.16667, -0.00463], [0.66667, 0.16667, -0.00463], [0.16667, 0.66667, 0.00463], [0.33333, 0.16667, -0.00463], [0.50000, 0.16667, -0.00463], [0.50000, 0.33333, 0.00463], [0.33333, 0.50000, -0.00463], [0.16667, 0.50000, -0.00463], [0.16667, 0.33333, 0.00463], [0.33333, 0.33333, 0.00463]]) elif order == 7: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.14286, 0.00000, 0.00000], [0.28571, 0.00000, 0.00000], [0.42857, 0.00000, 0.00000], [0.57143, 0.00000, 0.00000], [0.71429, 0.00000, 0.00000], [0.85714, 0.00000, 0.00000], [0.85714, 0.14286, -0.02041], [0.71429, 0.28571, 0.02041], [0.57143, 0.42857, -0.02041], [0.42857, 0.57143, 0.02041], [0.28571, 0.71429, -0.02041], [0.14286, 0.85714, 0.02041], [0.00000, 0.85714, 0.02041], [0.00000, 0.71429, -0.02041], [0.00000, 0.57143, 0.02041], [0.00000, 0.42857, -0.02041], [0.00000, 0.28571, 0.02041], [0.00000, 0.14286, -0.02041], [0.14286, 0.14286, -0.02041], [0.71429, 0.14286, -0.02041], [0.14286, 0.71429, -0.02041], [0.28571, 0.14286, -0.02041], [0.42857, 0.14286, -0.02041], [0.57143, 0.14286, -0.02041], [0.57143, 0.28571, 0.02041], [0.42857, 0.42857, -0.02041], [0.28571, 0.57143, 0.02041], [0.14286, 0.57143, 0.02041], [0.14286, 0.42857, -0.02041], [0.14286, 0.28571, 0.02041], [0.28571, 0.28571, 0.02041], [0.42857, 0.28571, 0.02041], [0.28571, 0.42857, -0.02041]]) # Higher order tests are too slow elif order == 8: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.12500, 0.00000, 0.00000], [0.25000, 0.00000, 0.00000], [0.37500, 0.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.62500, 0.00000, 0.00000], [0.75000, 0.00000, 0.00000], [0.87500, 0.00000, 0.00000], [0.87500, 0.12500, -0.00195], [0.75000, 0.25000, 0.00195], [0.62500, 0.37500, -0.00195], [0.50000, 0.50000, 0.00195], [0.37500, 0.62500, -0.00195], [0.25000, 0.75000, 0.00195], [0.12500, 0.87500, -0.00195], [0.00000, 0.87500, -0.00195], [0.00000, 0.75000, 0.00195], [0.00000, 0.62500, -0.00195], [0.00000, 0.50000, 0.00195], [0.00000, 0.37500, -0.00195], [0.00000, 0.25000, 0.00195], [0.00000, 0.12500, -0.00195], [0.12500, 0.12500, -0.00195], [0.75000, 0.12500, -0.00195], [0.12500, 0.75000, 0.00195], [0.25000, 0.12500, -0.00195], [0.37500, 0.12500, -0.00195], [0.50000, 0.12500, -0.00195], [0.62500, 0.12500, -0.00195], [0.62500, 0.25000, 0.00195], [0.50000, 0.37500, -0.00195], [0.37500, 0.50000, 0.00195], [0.25000, 0.62500, -0.00195], [0.12500, 0.62500, -0.00195], [0.12500, 0.50000, 0.00195], [0.12500, 0.37500, -0.00195], [0.12500, 0.25000, 0.00195], [0.25000, 0.25000, 0.00195], [0.50000, 0.25000, 0.00195], [0.25000, 0.50000, 0.00195], [0.37500, 0.25000, 0.00195], [0.37500, 0.37500, -0.00195], [0.25000, 0.37500, -0.00195]]) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) # Find nodes corresponding to y axis nodes = [] for j in range(points.shape[0]): if np.isclose(points[j][0], 0): nodes.append(j) def e2(x): return x[2] + x[0] * x[1] # For solution to be in functionspace V = FunctionSpace(mesh, ("CG", max(2, order))) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) quad_order = 30 intu = assemble_scalar(u * dx(metadata={"quadrature_degree": quad_order})) intu = MPI.sum(mesh.mpi_comm(), intu) ref = scipy_one_cell(points, nodes) assert ref == pytest.approx(intu, rel=3e-3)
def test_GetCells(): """Get cells of mesh""" mesh = UnitSquareMesh(MPI.comm_world, 5, 5) assert MPI.sum(mesh.mpi_comm(), len(mesh.cells())) == 50
def test_xdmf_input_tri(datadir): with XDMFFile(MPI.comm_world, os.path.join(datadir, "mesh.xdmf")) as xdmf: mesh = xdmf.read_mesh(GhostMode.none) surface = assemble_scalar(1 * dx(mesh)) assert MPI.sum(mesh.mpi_comm(), surface) == pytest.approx(4 * np.pi, rel=1e-4)
def test_fourth_order_quad(L, H, Z): """Test by comparing integration of z+x*y against sympy/scipy integration of a quad element. Z>0 implies curved element. *---------* 20-21-22-23-24-41--42--43--44 | | | | | | | 15 16 17 18 19 37 38 39 40 | | | | | | | 10 11 12 13 14 33 34 35 36 | | | | | | | 5 6 7 8 9 29 30 31 32 | | | | | *---------* 0--1--2--3--4--25--26--27--28 """ points = np.array([ [0, 0, 0], [L / 4, 0, 0], [L / 2, 0, 0], # 0 1 2 [3 * L / 4, 0, 0], [L, 0, 0], # 3 4 [0, H / 4, -Z / 3], [L / 4, H / 4, -Z / 3], [L / 2, H / 4, -Z / 3], # 5 6 7 [3 * L / 4, H / 4, -Z / 3], [L, H / 4, -Z / 3], # 8 9 [0, H / 2, 0], [L / 4, H / 2, 0], [L / 2, H / 2, 0], # 10 11 12 [3 * L / 4, H / 2, 0], [L, H / 2, 0], # 13 14 [0, (3 / 4) * H, 0], [L / 4, (3 / 4) * H, 0], # 15 16 [L / 2, (3 / 4) * H, 0], [3 * L / 4, (3 / 4) * H, 0], # 17 18 [L, (3 / 4) * H, 0], [0, H, Z], [L / 4, H, Z], # 19 20 21 [L / 2, H, Z], [3 * L / 4, H, Z], [L, H, Z], # 22 23 24 [(5 / 4) * L, 0, 0], [(6 / 4) * L, 0, 0], # 25 26 [(7 / 4) * L, 0, 0], [2 * L, 0, 0], # 27 28 [(5 / 4) * L, H / 4, -Z / 3], [(6 / 4) * L, H / 4, -Z / 3], # 29 30 [(7 / 4) * L, H / 4, -Z / 3], [2 * L, H / 4, -Z / 3], # 31 32 [(5 / 4) * L, H / 2, 0], [(6 / 4) * L, H / 2, 0], # 33 34 [(7 / 4) * L, H / 2, 0], [2 * L, H / 2, 0], # 35 36 [(5 / 4) * L, 3 / 4 * H, 0], # 37 [(6 / 4) * L, 3 / 4 * H, 0], # 38 [(7 / 4) * L, 3 / 4 * H, 0], [2 * L, 3 / 4 * H, 0], # 39 40 [(5 / 4) * L, H, Z], [(6 / 4) * L, H, Z], # 41 42 [(7 / 4) * L, H, Z], [2 * L, H, Z] ]) # 43 44 # VTK ordering cells = np.array([[ 0, 4, 24, 20, 1, 2, 3, 9, 14, 19, 21, 22, 23, 5, 10, 15, 6, 7, 8, 11, 12, 13, 16, 17, 18 ], [ 4, 28, 44, 24, 25, 26, 27, 32, 36, 40, 41, 42, 43, 9, 14, 19, 29, 30, 31, 33, 34, 35, 37, 38, 39 ]]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.quadrilateral, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.quadrilateral, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] V = FunctionSpace(mesh, ("CG", 4)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 5, 10, 15, 20] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-5)
def test_mesh_construction_pygmsh(): pygmsh = pytest.importorskip("pygmsh") if MPI.rank(MPI.comm_world) == 0: geom = pygmsh.opencascade.Geometry() geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.2) pygmsh_mesh = pygmsh.generate_mesh(geom) points, cells = pygmsh_mesh.points, pygmsh_mesh.cells else: points = np.zeros([0, 3]) cells = { "tetra": np.zeros([0, 4], dtype=np.int64), "triangle": np.zeros([0, 3], dtype=np.int64), "line": np.zeros([0, 2], dtype=np.int64) } mesh = Mesh(MPI.comm_world, dolfinx.cpp.mesh.CellType.tetrahedron, points, cells['tetra'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 1 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 3 mesh = Mesh(MPI.comm_world, dolfinx.cpp.mesh.CellType.triangle, points, cells['triangle'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 1 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 2 mesh = Mesh(MPI.comm_world, dolfinx.cpp.mesh.CellType.interval, points, cells['line'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 1 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 1 if MPI.rank(MPI.comm_world) == 0: print("Generate mesh") geom = pygmsh.opencascade.Geometry() geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.2) pygmsh_mesh = pygmsh.generate_mesh( geom, extra_gmsh_arguments=['-order', '2']) points, cells = pygmsh_mesh.points, pygmsh_mesh.cells print("End Generate mesh", cells.keys()) else: points = np.zeros([0, 3]) cells = { "tetra10": np.zeros([0, 10], dtype=np.int64), "triangle6": np.zeros([0, 6], dtype=np.int64), "line3": np.zeros([0, 3], dtype=np.int64) } mesh = Mesh(MPI.comm_world, dolfinx.cpp.mesh.CellType.tetrahedron, points, cells['tetra10'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 2 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 3 mesh = Mesh(MPI.comm_world, dolfinx.cpp.mesh.CellType.triangle, points, cells['triangle6'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 2 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 2
vertices_fiat = np.sort( vertex_global_indices[np.array(entity_topology)]) assert all(vertices_fiat == vertices_dolfin) def test_mesh_topology_lifetime(): """Check that lifetime of Mesh.topology is bound to underlying mesh object""" mesh = UnitSquareMesh(MPI.comm_world, 4, 4) rc = sys.getrefcount(mesh) topology = mesh.topology assert sys.getrefcount(mesh) == rc + 1 del topology assert sys.getrefcount(mesh) == rc @pytest.mark.xfail(condition=MPI.size(MPI.comm_world) > 1, reason="Small meshes fail in parallel") def test_small_mesh(): mesh3d = UnitCubeMesh(MPI.comm_world, 1, 1, 1) gdim = mesh3d.geometry.dim assert mesh3d.num_entities_global(gdim) == 6 mesh2d = UnitSquareMesh(MPI.comm_world, 1, 1) gdim = mesh2d.geometry.dim assert mesh2d.num_entities_global(gdim) == 2 mesh1d = UnitIntervalMesh(MPI.comm_world, 2) gdim = mesh1d.geometry.dim assert mesh1d.num_entities_global(gdim) == 2