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_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_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_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])
# 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_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
# Split the mixed solution and collapse u = w.sub(0).collapse() p = w.sub(1).collapse() # We can calculate the :math:`L^2` norms of u and p as follows:: print("Norm of velocity coefficient vector: %.15g" % u.vector.norm()) print("Norm of pressure coefficient vector: %.15g" % p.vector.norm()) # Check pressure norm assert np.isclose(p.vector.norm(), 4147.69457577) # Finally, we can save and plot the solutions:: # Save solution in XDMF format with XDMFFile(MPI.comm_world, "velocity.xdmf") as ufile_xdmf: ufile_xdmf.write(u) with XDMFFile(MPI.comm_world, "pressure.xdmf") as pfile_xdmf: pfile_xdmf.write(p) # Plot solution plt.figure() plot(u, title="velocity") # plt.figure() plot(p, title="pressure" + str(MPI.rank(mesh.mpi_comm()))) # Display plots plt.show()