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)
(dim_x / 2 - d_absorb)) / d_absorb)**deg_absorb sigma_y = sigma0 * ((np.abs(x[1]) - (dim_x / 2 - d_absorb)) / d_absorb)**deg_absorb # 2j*sigma - sigma^2 in absorbing layers x_layers = in_absorber_x * (2j * sigma_x * k0 - sigma_x**2) y_layers = in_absorber_y * (2j * sigma_y * k0 - sigma_y**2) return x_layers + y_layers # Define function space V = FunctionSpace(mesh, ("Lagrange", degree)) # Interpolate absorbing layer piece of wavenumber k_absorb onto V k_absorb = Function(V) k_absorb.interpolate(adiabatic_layer) # Interpolate incident wave field onto V ui = Function(V) ui.interpolate(incident) # Define variational problem u = TrialFunction(V) v = TestFunction(V) F = inner(grad(u), grad(v)) * dx - k0**2 * inner(u, v) * dx - \ k_absorb * inner(u, v) * dx \ + inner(dot(grad(ui), n), v) * ds(1) a = lhs(F)
def test_nth_order_triangle(order): num_nodes = (order + 1) * (order + 2) / 2 cells = np.array([range(int(num_nodes))]) cells = cells[:, perm_vtk(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]]) cell = ufl.Cell("triangle", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, order)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) # 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) u.interpolate(e2) quad_order = 30 intu = assemble_scalar(u * dx(metadata={"quadrature_degree": quad_order})) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) ref = scipy_one_cell(points, nodes) assert ref == pytest.approx(intu, rel=3e-3)
def test_facet_normals(cell_type): """Test that FacetNormal is outward facing""" for count in range(5): mesh = unit_cell(cell_type) tdim = mesh.topology.dim mesh.topology.create_entities(tdim - 1) V = VectorFunctionSpace(mesh, ("Lagrange", 1)) normal = ufl.FacetNormal(mesh) v = Function(V) mesh.topology.create_entities(tdim - 1) map_f = mesh.topology.index_map(tdim - 1) num_facets = map_f.size_local + map_f.num_ghosts indices = np.arange(0, num_facets) values = np.arange(0, num_facets, dtype=np.intc) marker = MeshTags(mesh, tdim - 1, indices, values) # For each facet, check that the inner product of the normal and # the vector that has a positive normal component on only that # facet is positive for i in range(num_facets): if cell_type == CellType.interval: co = mesh.geometry.x[i] v.interpolate(lambda x: x[0] - co[0]) if cell_type == CellType.triangle: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away # from `co` so that there is no normal component on two # edges and the integral over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 2, (x[1] - co[1]) / 2)) elif cell_type == CellType.tetrahedron: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away # from `co` so that there is no normal component on # three faces and the integral over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 3, (x[1] - co[1]) / 3, (x[2] - co[2]) / 3)) elif cell_type == CellType.quadrilateral: # function that is 0 on one edge and points away from # that edge so that there is no normal component on # three edges v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 2 else 0 * x[j] for j in range(2))) elif cell_type == CellType.hexahedron: # function that is 0 on one face and points away from # that face so that there is no normal component on five # faces v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 3 else 0 * x[j] for j in range(3))) # assert that the integrals these functions dotted with the # normal over a face is 1 on one face and 0 on the others ones = 0 for j in range(num_facets): a = ufl.inner(v, normal) * ufl.ds(subdomain_data=marker, subdomain_id=j) result = fem.assemble_scalar(a) if np.isclose(result, 1): ones += 1 else: assert np.isclose(result, 0) assert ones == 1
def run_dg_test(mesh, V, degree): """Manufactured Poisson problem, solving u = x[component]**n, where n is the degree of the Lagrange function space. """ u, v = TrialFunction(V), TestFunction(V) # Exact solution x = SpatialCoordinate(mesh) u_exact = x[1] ** degree # Coefficient k = Function(V) k.vector.set(2.0) k.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) # Source term f = - div(k * grad(u_exact)) # Mesh normals and element size n = FacetNormal(mesh) h = CellDiameter(mesh) h_avg = (h("+") + h("-")) / 2.0 # Penalty parameter alpha = 32 dx_ = dx(metadata={"quadrature_degree": -1}) ds_ = ds(metadata={"quadrature_degree": -1}) dS_ = dS(metadata={"quadrature_degree": -1}) a = inner(k * grad(u), grad(v)) * dx_ \ - k("+") * inner(avg(grad(u)), jump(v, n)) * dS_ \ - k("+") * inner(jump(u, n), avg(grad(v))) * dS_ \ + k("+") * (alpha / h_avg) * inner(jump(u, n), jump(v, n)) * dS_ \ - inner(k * grad(u), v * n) * ds_ \ - inner(u * n, k * grad(v)) * ds_ \ + (alpha / h) * inner(k * u, v) * ds_ L = inner(f, v) * dx_ - inner(k * u_exact * n, grad(v)) * ds_ \ + (alpha / h) * inner(k * u_exact, v) * ds_ for integral in a.integrals(): integral.metadata()["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a) for integral in L.integrals(): integral.metadata()["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L) b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a, []) A.assemble() # 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 uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) # Calculate error M = (u_exact - uh)**2 * dx M = fem.Form(M) error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
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), "r", encoding=XDMFFile.Encoding.ASCII) as xdmf: mesh = xdmf.read_mesh(name="Grid") 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.topology.create_connectivity_all() facetdim = mesh.topology.dim - 1 bndry_facets = np.where(np.array(cpp.mesh.compute_boundary_facets(mesh.topology)) == 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 = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) t1 = time.time() print("Error assembly time:", t1 - t0) assert np.absolute(error) < 1.0e-14
def neumann_bcs(self, V, V_real): w, w_old = as_ufl(0), as_ufl(0) for n in self.bc_dict['neumann']: if n['dir'] == 'xyz': func, func_old = Function(V), Function(V) if 'curve' in n.keys(): load = expression.template_vector() load.val_x, load.val_y, load.val_z = self.ti.timecurves( n['curve'][0])(self.ti.t_init), self.ti.timecurves( n['curve'][1])(self.ti.t_init), self.ti.timecurves( n['curve'][2])(self.ti.t_init) func.interpolate(load.evaluate), func_old.interpolate( load.evaluate) self.ti.funcs_to_update_vec.append({ func: [ self.ti.timecurves(n['curve'][0]), self.ti.timecurves(n['curve'][1]), self.ti.timecurves(n['curve'][2]) ] }) self.ti.funcs_to_update_vec_old.append({ func_old: [ self.ti.timecurves(n['curve'][0]), self.ti.timecurves(n['curve'][1]), self.ti.timecurves(n['curve'][2]) ] }) else: func.vector.set( n['val'] ) # currently only one value for all directions - use constant load function otherwise! for i in range(len(n['id'])): ds_ = ds(subdomain_data=self.io.mt_b1, subdomain_id=n['id'][i], metadata={'quadrature_degree': self.quad_degree}) w += self.vf.deltaP_ext_neumann(func, ds_) w_old += self.vf.deltaP_ext_neumann(func_old, ds_) elif n['dir'] == 'normal': # reference normal func, func_old = Function(V_real), Function(V_real) if 'curve' in n.keys(): load = expression.template() load.val = self.ti.timecurves(n['curve'])(self.ti.t_init) func.interpolate(load.evaluate), func_old.interpolate( load.evaluate) self.ti.funcs_to_update.append( {func: self.ti.timecurves(n['curve'])}) self.ti.funcs_to_update_old.append( {func_old: self.ti.timecurves(n['curve'])}) else: func.vector.set(n['val']) for i in range(len(n['id'])): ds_ = ds(subdomain_data=self.io.mt_b1, subdomain_id=n['id'][i], metadata={'quadrature_degree': self.quad_degree}) w += self.vf.deltaP_ext_neumann_normal(func, ds_) w_old += self.vf.deltaP_ext_neumann_normal(func_old, ds_) else: raise NameError("Unknown dir option for Neumann BC!") return w, w_old
def xtest_tetrahedron_integral(space_type, space_order): domain = ufl.Mesh(ufl.VectorElement("Lagrange", "tetrahedron", 1)) temp_points = np.array([[-1., 0., -1.], [0., 0., 0.], [1., 0., 1.], [0., 1., 0.], [0., 0., 1.]]) for repeat in range(10): order = [i for i, j in enumerate(temp_points)] shuffle(order) points = np.zeros(temp_points.shape) for i, j in enumerate(order): points[j] = temp_points[i] cells = [] for cell in [[0, 1, 3, 4], [1, 2, 3, 4]]: # Randomly number the cell cell_order = list(range(4)) shuffle(cell_order) cells.append([order[cell[i]] for i in cell_order]) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) V = FunctionSpace(mesh, (space_type, space_order)) Vvec = VectorFunctionSpace(mesh, ("P", 1)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] for d in dofs: v = Function(V) v.vector[:] = [1 if i == d else 0 for i in range(V.dim)] if space_type in ["RT", "BDM"]: # Hdiv def normal(x): values = np.zeros((3, x.shape[1])) values[0] = [1 for i in values[0]] return values n = Function(Vvec) n.interpolate(normal) form = ufl.inner(ufl.jump(v), n) * ufl.dS elif space_type in ["N1curl", "N2curl"]: # Hcurl def tangent1(x): values = np.zeros((3, x.shape[1])) values[1] = [1 for i in values[1]] return values def tangent2(x): values = np.zeros((3, x.shape[1])) values[2] = [1 for i in values[2]] return values t1 = Function(Vvec) t1.interpolate(tangent1) t2 = Function(Vvec) t2.interpolate(tangent1) form = ufl.inner(ufl.jump(v), t1) * ufl.dS form += ufl.inner(ufl.jump(v), t2) * ufl.dS else: form = ufl.jump(v) * ufl.dS value = fem.assemble_scalar(form) assert np.isclose(value, 0)
def xtest_hexahedron_integral(space_type, space_order): domain = ufl.Mesh(ufl.VectorElement("Lagrange", "hexahedron", 1)) temp_points = np.array([[-1., 0., -1.], [0., 0., 0.], [1., 0., 1.], [-1., 1., 1.], [0., 1., 0.], [1., 1., 1.], [-1., 0., 0.], [0., 0., 1.], [1., 0., 2.], [-1., 1., 2.], [0., 1., 1.], [1., 1., 2.]]) for repeat in range(10): order = [i for i, j in enumerate(temp_points)] shuffle(order) points = np.zeros(temp_points.shape) for i, j in enumerate(order): points[j] = temp_points[i] connections = { 0: [1, 2, 4], 1: [0, 3, 5], 2: [0, 3, 6], 3: [1, 2, 7], 4: [0, 5, 6], 5: [1, 4, 7], 6: [2, 4, 7], 7: [3, 5, 6] } cells = [] for cell in [[0, 1, 3, 4, 6, 7, 9, 10], [1, 2, 4, 5, 7, 8, 10, 11]]: # Randomly number the cell start = choice(range(8)) cell_order = [start] for i in range(3): diff = choice([ i for i in connections[start] if i not in cell_order ]) - cell_order[0] cell_order += [c + diff for c in cell_order] cells.append([order[cell[i]] for i in cell_order]) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) V = FunctionSpace(mesh, (space_type, space_order)) Vvec = VectorFunctionSpace(mesh, ("P", 1)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] for d in dofs: v = Function(V) v.vector[:] = [1 if i == d else 0 for i in range(V.dim)] if space_type in ["NCF"]: # Hdiv def normal(x): values = np.zeros((3, x.shape[1])) values[0] = [1 for i in values[0]] return values n = Function(Vvec) n.interpolate(normal) form = ufl.inner(ufl.jump(v), n) * ufl.dS elif space_type in ["NCE"]: # Hcurl def tangent1(x): values = np.zeros((3, x.shape[1])) values[1] = [1 for i in values[1]] return values def tangent2(x): values = np.zeros((3, x.shape[1])) values[2] = [1 for i in values[2]] return values t1 = Function(Vvec) t1.interpolate(tangent1) t2 = Function(Vvec) t2.interpolate(tangent1) form = ufl.inner(ufl.jump(v), t1) * ufl.dS form += ufl.inner(ufl.jump(v), t2) * ufl.dS else: form = ufl.jump(v) * ufl.dS value = fem.assemble_scalar(form) assert np.isclose(value, 0)
def amg_solve(N, method): # Elasticity parameters E = 1.0e9 nu = 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) # Stress computation def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym( grad(v))) * Identity(2) # Define problem mesh = UnitSquareMesh(MPI.COMM_WORLD, N, N) V = VectorFunctionSpace(mesh, 'Lagrange', 1) bc0 = Function(V) with bc0.vector.localForm() as bc_local: bc_local.set(0.0) def boundary(x): return np.full(x.shape[1], True) facetdim = mesh.topology.dim - 1 bndry_facets = locate_entities_boundary(mesh, facetdim, boundary) bdofs = locate_dofs_topological(V.sub(0), V, facetdim, bndry_facets) bc = DirichletBC(bc0, bdofs, V.sub(0)) u = TrialFunction(V) v = TestFunction(V) # Forms a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector((1.0, 1.0)), v) * dx # Assemble linear algebra objects A = assemble_matrix(a, [bc]) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) # Create solution function u = Function(V) # Create near null space basis and orthonormalize null_space = build_nullspace(V, u.vector) # Attached near-null space to matrix A.set_near_nullspace(null_space) # Test that basis is orthonormal assert null_space.is_orthonormal() # Create PETSC smoothed aggregation AMG preconditioner, and # create CG solver solver = PETSc.KSP().create(mesh.mpi_comm) solver.setType("cg") # Set matrix operator solver.setOperators(A) # Compute solution and return number of iterations return solver.solve(b, u.vector)
def test_hexahedron_evaluation(space_type, space_order): if space_type == "NCF" and space_order >= 3: print("Eval in this space not supported yet") return if space_type == "NCE" and space_order >= 2: print("Eval in this space not supported yet") return domain = ufl.Mesh(ufl.VectorElement("Lagrange", "hexahedron", 1)) temp_points = np.array([[-1., 0., -1.], [0., 0., 0.], [1., 0., 1.], [-1., 1., 1.], [0., 1., 0.], [1., 1., 1.], [-1., 0., 0.], [0., 0., 1.], [1., 0., 2.], [-1., 1., 2.], [0., 1., 1.], [1., 1., 2.]]) for repeat in range(10): order = [i for i, j in enumerate(temp_points)] shuffle(order) points = np.zeros(temp_points.shape) for i, j in enumerate(order): points[j] = temp_points[i] connections = { 0: [1, 2, 4], 1: [0, 3, 5], 2: [0, 3, 6], 3: [1, 2, 7], 4: [0, 5, 6], 5: [1, 4, 7], 6: [2, 4, 7], 7: [3, 5, 6] } cells = [] for cell in [[0, 1, 3, 4, 6, 7, 9, 10], [1, 2, 4, 5, 7, 8, 10, 11]]: # Randomly number the cell start = choice(range(8)) cell_order = [start] for i in range(3): diff = choice([ i for i in connections[start] if i not in cell_order ]) - cell_order[0] cell_order += [c + diff for c in cell_order] cells.append([order[cell[i]] for i in cell_order]) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) V = FunctionSpace(mesh, (space_type, space_order)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] N = 6 eval_points = np.array([[0., i / N, j / N] for i in range(N + 1) for j in range(N + 1)]) for d in dofs: v = Function(V) v.vector[:] = [1 if i == d else 0 for i in range(V.dim)] values0 = v.eval(eval_points, [0 for i in eval_points]) values1 = v.eval(eval_points, [1 for i in eval_points]) if len(eval_points) == 1: values0 = [values0] values1 = [values1] if space_type == "NCF": # Hdiv for i, j in zip(values0, values1): assert np.isclose(i[0], j[0]) elif space_type == "NCE": # Hcurl for i, j in zip(values0, values1): assert np.allclose(i[1:], j[1:]) else: assert np.allclose(values0, values1)
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_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_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_interpolation_mismatch_rank1(W): u = Function(W) with pytest.raises(RuntimeError): u.interpolate(lambda x: np.ones((2, x.shape[1])))
t = 0.01 # [day] with intern_var0["eta_dash"].vector.localForm() as local: local.set(t / fecoda.mps.MPS_q4 * 1.0e-6) with w0["temp"].vector.localForm() as local: local.set(fecoda.misc.room_temp - 5) with w1["temp"].vector.localForm() as local: local.set(fecoda.misc.room_temp - 5) with w0["phi"].vector.localForm() as local: local.set(0.95) with w1["phi"].vector.localForm() as local: local.set(0.95) co2_bc = Function(w0["co2"].function_space) phi_bc = Function(w0["phi"].function_space) displ_bc = Function(w0["displ"].function_space) temp_bc = Function(w0["temp"].function_space) moulding_end = 3 loading_time = 1.0 moulding_times = np.linspace(t, moulding_end, args.moulding_steps, endpoint=False) wetting_times = np.linspace(moulding_end, fecoda.water.t_drying_onset, args.wetting_steps, endpoint=False)
def test_name_argument(W): u = Function(W) v = Function(W, name="v") assert u.name == "f_{}".format(u.count()) assert v.name == "v" assert str(v) == "v"
def test_interpolation_mismatch_rank0(W): def f(x): return np.ones(x.shape[1]) u = Function(W) with pytest.raises(RuntimeError): u.interpolate(f)
def dirichlet_bcs(self, V): for d in self.bc_dict['dirichlet']: func, func_old = Function(V), Function(V) if 'curve' in d.keys(): load = expression.template() load.val = self.ti.timecurves(d['curve'][0])(self.ti.t_init) func.interpolate(load.evaluate), func_old.interpolate( load.evaluate) self.ti.funcs_to_update.append( {func: self.ti.timecurves(d['curve'][0])}) self.ti.funcs_to_update_old.append( {func_old: self.ti.timecurves(d['curve'][0])}) else: func.vector.set(d['val']) if d['dir'] == 'all': for i in range(len(d['id'])): self.dbcs.append( DirichletBC( func, locate_dofs_topological( V, self.io.mesh.topology.dim - 1, self.io.mt_b1.indices[self.io.mt_b1.values == d['id'][i]]))) elif d['dir'] == 'x': for i in range(len(d['id'])): self.dbcs.append( DirichletBC( func, locate_dofs_topological( (V.sub(0), V.sub(0).collapse()), self.io.mesh.topology.dim - 1, self.io.mt_b1.indices[self.io.mt_b1.values == d['id'][i]]), V.sub(0))) elif d['dir'] == 'y': for i in range(len(d['id'])): self.dbcs.append( DirichletBC( func, locate_dofs_topological( (V.sub(1), V.sub(1).collapse()), self.io.mesh.topology.dim - 1, self.io.mt_b1.indices[self.io.mt_b1.values == d['id'][i]]), V.sub(1))) elif d['dir'] == 'z': for i in range(len(d['id'])): self.dbcs.append( DirichletBC( func, locate_dofs_topological( (V.sub(2), V.sub(2).collapse()), self.io.mesh.topology.dim - 1, self.io.mt_b1.indices[self.io.mt_b1.values == d['id'][i]]), V.sub(2))) elif d['dir'] == '2dimX': self.dbcs.append( DirichletBC( func, locate_dofs_topological( (V.sub(0), V.sub(0).collapse()), self.io.mesh.topology.dim - 1, locate_entities_boundary( self.io.mesh, self.io.mesh.topology.dim - 1, self.twodimX)), V.sub(0))) elif d['dir'] == '2dimY': self.dbcs.append( DirichletBC( func, locate_dofs_topological( (V.sub(1), V.sub(1).collapse()), self.io.mesh.topology.dim - 1, locate_entities_boundary( self.io.mesh, self.io.mesh.topology.dim - 1, self.twodimY)), V.sub(1))) elif d['dir'] == '2dimZ': self.dbcs.append( DirichletBC( func, locate_dofs_topological( (V.sub(2), V.sub(2).collapse()), self.io.mesh.topology.dim - 1, locate_entities_boundary( self.io.mesh, self.io.mesh.topology.dim - 1, self.twodimZ)), V.sub(2))) else: raise NameError("Unknown dir option for Dirichlet BC!")
def test_assign(V, W): for V0, V1, vector_space in [(V, W, False), (W, V, True)]: u = Function(V0) u0 = Function(V0) u1 = Function(V0) u2 = Function(V0) u3 = Function(V1) u.vector[:] = 1.0 u0.vector[:] = 2.0 u1.vector[:] = 3.0 u2.vector[:] = 4.0 u3.vector[:] = 5.0 uu = Function(V0) uu.assign(2 * u) assert uu.vector.get_local().sum() == u0.vector.get_local().sum() uu = Function(V1) uu.assign(3 * u) assert uu.vector.get_local().sum() == u1.vector.get_local().sum() # Test complex assignment expr = 3 * u - 4 * u1 - 0.1 * 4 * u * 4 + u2 + 3 * u0 / 3. / 0.5 expr_scalar = 3 - 4 * 3 - 0.1 * 4 * 4 + 4. + 3 * 2. / 3. / 0.5 uu.assign(expr) assert (round( uu.vector.get_local().sum() - float( expr_scalar * uu.vector.size()), 7) == 0) # Test self assignment expr = 3 * u - 5.0 * u2 + u1 - 5 * u expr_scalar = 3 - 5 * 4. + 3. - 5 u.assign(expr) assert (round( u.vector.get_local().sum() - float( expr_scalar * u.vector.size()), 7) == 0) # Test zero assignment u.assign(-u2 / 2 + 2 * u1 - u1 / 0.5 + u2 * 0.5) assert round(u.vector.get_local().sum() - 0.0, 7) == 0 # Test erroneous assignments uu = Function(V1) def f(values, x): values[:, 0] = 1.0 with pytest.raises(RuntimeError): uu.assign(1.0) with pytest.raises(RuntimeError): uu.assign(4 * f) if not vector_space: with pytest.raises(RuntimeError): uu.assign(u * u0) with pytest.raises(RuntimeError): uu.assign(4 / u0) with pytest.raises(RuntimeError): uu.assign(4 * u * u1)
def __init__(self, io_params, time_params, fem_params, constitutive_models, bc_dict, time_curves, io, comm=None): problem_base.__init__(self, io_params, time_params, comm) self.problem_physics = 'fluid' self.simname = io_params['simname'] self.io = io # number of distinct domains (each one has to be assigned a own material model) self.num_domains = len(constitutive_models) self.order_vel = fem_params['order_vel'] self.order_pres = fem_params['order_pres'] self.quad_degree = fem_params['quad_degree'] # collect domain data self.dx_, self.rho = [], [] for n in range(self.num_domains): # integration domains self.dx_.append( dx(subdomain_data=self.io.mt_d, subdomain_id=n + 1, metadata={'quadrature_degree': self.quad_degree})) # data for inertial forces: density self.rho.append(constitutive_models['MAT' + str(n + 1) + '']['inertia']['rho']) self.incompressible_2field = True # always true! self.localsolve = False # no idea what might have to be solved locally... self.prestress_initial = False # guess prestressing in fluid is somehow senseless... self.p11 = as_ufl( 0 ) # can't think of a fluid case with non-zero 11-block in system matrix... # type of discontinuous function spaces if str(self.io.mesh.ufl_cell()) == 'tetrahedron' or str( self.io.mesh.ufl_cell()) == 'triangle3D': dg_type = "DG" if (self.order_vel > 1 or self.order_pres > 1) and self.quad_degree < 3: raise ValueError( "Use at least a quadrature degree of 3 or more for higher-order meshes!" ) elif str(self.io.mesh.ufl_cell()) == 'hexahedron' or str( self.io.mesh.ufl_cell()) == 'quadrilateral3D': dg_type = "DQ" if (self.order_vel > 1 or self.order_pres > 1) and self.quad_degree < 5: raise ValueError( "Use at least a quadrature degree of 5 or more for higher-order meshes!" ) else: raise NameError("Unknown cell/element type!") # create finite element objects for v and p self.P_v = VectorElement("CG", self.io.mesh.ufl_cell(), self.order_vel) self.P_p = FiniteElement("CG", self.io.mesh.ufl_cell(), self.order_pres) # function spaces for v and p self.V_v = FunctionSpace(self.io.mesh, self.P_v) self.V_p = FunctionSpace(self.io.mesh, self.P_p) # a discontinuous tensor, vector, and scalar function space self.Vd_tensor = TensorFunctionSpace(self.io.mesh, (dg_type, self.order_vel - 1)) self.Vd_vector = VectorFunctionSpace(self.io.mesh, (dg_type, self.order_vel - 1)) self.Vd_scalar = FunctionSpace(self.io.mesh, (dg_type, self.order_vel - 1)) # functions self.dv = TrialFunction(self.V_v) # Incremental velocity self.var_v = TestFunction(self.V_v) # Test function self.dp = TrialFunction(self.V_p) # Incremental pressure self.var_p = TestFunction(self.V_p) # Test function self.v = Function(self.V_v, name="Velocity") self.p = Function(self.V_p, name="Pressure") # values of previous time step self.v_old = Function(self.V_v) self.a_old = Function(self.V_v) self.p_old = Function(self.V_p) self.ndof = self.v.vector.getSize() + self.p.vector.getSize() # initialize fluid time-integration class self.ti = timeintegration.timeintegration_fluid( time_params, fem_params, time_curves, self.t_init, self.comm) # initialize kinematics_constitutive class self.ki = fluid_kinematics_constitutive.kinematics() # initialize material/constitutive class self.ma = [] for n in range(self.num_domains): self.ma.append( fluid_kinematics_constitutive.constitutive( self.ki, constitutive_models['MAT' + str(n + 1) + ''])) # initialize fluid variational form class self.vf = fluid_variationalform.variationalform( self.var_v, self.dv, self.var_p, self.dp, self.io.n0) # initialize boundary condition class self.bc = boundaryconditions.boundary_cond_fluid( bc_dict, fem_params, self.io, self.ki, self.vf, self.ti) self.bc_dict = bc_dict # Dirichlet boundary conditions if 'dirichlet' in self.bc_dict.keys(): self.bc.dirichlet_bcs(self.V_v) self.set_variational_forms_and_jacobians()
mesh = UnitSquareMesh(MPI.COMM_WORLD, n_elem, n_elem) n = FacetNormal(mesh) # Source amplitude if has_petsc_complex: A = 1 + 1j else: A = 1 # Test and trial function space V = FunctionSpace(mesh, ("Lagrange", deg)) # Define variational problem u = TrialFunction(V) v = TestFunction(V) f = Function(V) f.interpolate(lambda x: A * k0**2 * np.cos(k0 * x[0]) * np.cos(k0 * x[1])) a = inner(grad(u), grad(v)) * dx - k0**2 * inner(u, v) * dx L = inner(f, v) * dx # Compute solution u = Function(V) solve(a == L, u, []) # Save solution in XDMF format (to be viewed in Paraview, for example) with XDMFFile(MPI.COMM_WORLD, "plane_wave.xdmf", "w", encoding=XDMFFile.Encoding.HDF5) as file: file.write_mesh(mesh) file.write_function(u)
q, v = TestFunctions(ME) # .. index:: split functions # # For the test functions, # :py:func:`TestFunctions<dolfinx.functions.fem.TestFunctions>` (note # the 's' at the end) is used to define the scalar test functions ``q`` # and ``v``. The # :py:class:`TrialFunction<dolfinx.functions.fem.TrialFunction>` # ``du`` has dimension two. Some mixed objects of the # :py:class:`Function<dolfinx.functions.fem.Function>` class on ``ME`` # are defined to represent :math:`u = (c_{n+1}, \mu_{n+1})` and :math:`u0 # = (c_{n}, \mu_{n})`, and these are then split into sub-functions:: # Define functions u = Function(ME) # current solution u0 = Function(ME) # solution from previous converged step # Split mixed functions dc, dmu = split(du) c, mu = split(u) c0, mu0 = split(u0) # The line ``c, mu = split(u)`` permits direct access to the components of # a mixed function. Note that ``c`` and ``mu`` are references for # components of ``u``, and not copies. # # .. index:: # single: interpolating functions; (in Cahn-Hilliard demo) # # The initial conditions are interpolated into a finite element space::
def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym(grad(v))) * Identity( len(v)) # Create function space V = VectorFunctionSpace(mesh, ("Lagrange", 1)) # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(sigma(u), grad(v)) * dx L = inner(f, v) * dx u0 = Function(V) with u0.vector.localForm() as bc_local: bc_local.set(0.0) # Set up boundary condition on inner surface bc = DirichletBC(u0, locate_dofs_geometrical(V, boundary)) # Explicitly compile a UFL Form into dolfinx Form form = Form(a, jit_parameters={ "cffi_extra_compile_args": "-Ofast -march=native", "cffi_verbose": True }) # Assemble system, applying boundary conditions and preserving symmetry A = assemble_matrix(form, [bc])
def test_biharmonic(): """Manufactured biharmonic problem. Solved using rotated Regge mixed finite element method. This is equivalent to the Hellan-Herrmann-Johnson (HHJ) finite element method in two-dimensions.""" mesh = RectangleMesh(MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]), np.array([1.0, 1.0, 0.0])], [32, 32], CellType.triangle) element = ufl.MixedElement([ufl.FiniteElement("Regge", ufl.triangle, 1), ufl.FiniteElement("Lagrange", ufl.triangle, 2)]) V = FunctionSpace(mesh, element) sigma, u = ufl.TrialFunctions(V) tau, v = ufl.TestFunctions(V) x = ufl.SpatialCoordinate(mesh) u_exact = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) * ufl.sin(ufl.pi * x[1]) f_exact = div(grad(div(grad(u_exact)))) sigma_exact = grad(grad(u_exact)) # sigma and tau are tangential-tangential continuous according to the # H(curl curl) continuity of the Regge space. However, for the biharmonic # problem we require normal-normal continuity H (div div). Theorem 4.2 of # Lizao Li's PhD thesis shows that the latter space can be constructed by # the former through the action of the operator S: def S(tau): return tau - ufl.Identity(2) * ufl.tr(tau) sigma_S = S(sigma) tau_S = S(tau) # Discrete duality inner product eq. 4.5 Lizao Li's PhD thesis def b(tau_S, v): n = FacetNormal(mesh) return inner(tau_S, grad(grad(v))) * dx \ - ufl.dot(ufl.dot(tau_S('+'), n('+')), n('+')) * jump(grad(v), n) * dS \ - ufl.dot(ufl.dot(tau_S, n), n) * ufl.dot(grad(v), n) * ds # Non-symmetric formulation a = inner(sigma_S, tau_S) * dx - b(tau_S, u) + b(sigma_S, v) L = inner(f_exact, v) * dx V_1 = V.sub(1).collapse() zero_u = Function(V_1) with zero_u.vector.localForm() as zero_u_local: zero_u_local.set(0.0) # Strong (Dirichlet) boundary condition boundary_facets = locate_entities_boundary( mesh, mesh.topology.dim - 1, lambda x: np.full(x.shape[1], True, dtype=bool)) boundary_dofs = locate_dofs_topological((V.sub(1), V_1), mesh.topology.dim - 1, boundary_facets) bcs = [DirichletBC(zero_u, boundary_dofs, V.sub(1))] A = assemble_matrix(a, bcs=bcs) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], [bcs]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Solve solver = PETSc.KSP().create(MPI.COMM_WORLD) PETSc.Options()["ksp_type"] = "preonly" PETSc.Options()["pc_type"] = "lu" # PETSc.Options()["pc_factor_mat_solver_type"] = "mumps" solver.setFromOptions() solver.setOperators(A) x_h = Function(V) solver.solve(b, x_h.vector) x_h.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) # Recall that x_h has flattened indices. u_error_numerator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar( inner(u_exact - x_h[4], u_exact - x_h[4]) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM)) u_error_denominator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar( inner(u_exact, u_exact) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM)) assert(np.absolute(u_error_numerator / u_error_denominator) < 0.05) # Reconstruct tensor from flattened indices. # Apply inverse transform. In 2D we have S^{-1} = S. sigma_h = S(ufl.as_tensor([[x_h[0], x_h[1]], [x_h[2], x_h[3]]])) sigma_error_numerator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar( inner(sigma_exact - sigma_h, sigma_exact - sigma_h) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM)) sigma_error_denominator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar( inner(sigma_exact, sigma_exact) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM)) assert(np.absolute(sigma_error_numerator / sigma_error_denominator) < 0.005)
def test_integral(cell_type, space_type, space_order): # TODO: Fix jump integrals in FFCx by passing in full info for both cells, then re-enable these tests pytest.xfail() random.seed(4) for repeat in range(10): mesh = random_evaluation_mesh(cell_type) tdim = mesh.topology.dim V = FunctionSpace(mesh, (space_type, space_order)) Vvec = VectorFunctionSpace(mesh, ("P", 1)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] for d in dofs: v = Function(V) v.vector[:] = [1 if i == d else 0 for i in range(V.dim)] if space_type in ["RT", "BDM", "RTCF", "NCF"]: # Hdiv def normal(x): values = np.zeros((tdim, x.shape[1])) values[0] = [1 for i in values[0]] return values n = Function(Vvec) n.interpolate(normal) form = ufl.inner(ufl.jump(v), n) * ufl.dS elif space_type in ["N1curl", "N2curl", "RTCE", "NCE"]: # Hcurl def tangent(x): values = np.zeros((tdim, x.shape[1])) values[1] = [1 for i in values[1]] return values t = Function(Vvec) t.interpolate(tangent) form = ufl.inner(ufl.jump(v), t) * ufl.dS if tdim == 3: def tangent2(x): values = np.zeros((3, x.shape[1])) values[2] = [1 for i in values[2]] return values t2 = Function(Vvec) t2.interpolate(tangent2) form += ufl.inner(ufl.jump(v), t2) * ufl.dS else: form = ufl.jump(v) * ufl.dS value = fem.assemble_scalar(form) assert np.isclose(value, 0)
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 = cells[:, perm_vtk(CellType.triangle, cells.shape[1])] cell = ufl.Cell("triangle", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 4)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) def e2(x): return x[2] + x[0] * x[1] # Interpolate function V = FunctionSpace(mesh, ("Lagrange", 4)) u = Function(V) u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 50})) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) nodes = [0, 3, 10, 11, 12] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-4)
def test_eval(V, W, Q, mesh): u1 = Function(V) u2 = Function(W) u3 = Function(Q) def e1(x): return x[0] + x[1] + x[2] def e2(x): values = np.empty((3, x.shape[1])) values[0] = x[0] + x[1] + x[2] values[1] = x[0] - x[1] - x[2] values[2] = x[0] + x[1] + x[2] return values def e3(x): values = np.empty((9, x.shape[1])) values[0] = x[0] + x[1] + x[2] values[1] = x[0] - x[1] - x[2] values[2] = x[0] + x[1] + x[2] values[3] = x[0] values[4] = x[1] values[5] = x[2] values[6] = -x[0] values[7] = -x[1] values[8] = -x[2] return values u1.interpolate(e1) u2.interpolate(e2) u3.interpolate(e3) x0 = (mesh.geometry.x[0] + mesh.geometry.x[1]) / 2.0 tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim) cell_candidates = geometry.compute_collisions_point(tree, x0) cell = dolfinx.cpp.geometry.select_colliding_cells(mesh, cell_candidates, x0, 1) assert np.allclose(u3.eval(x0, cell)[:3], u2.eval(x0, cell), rtol=1e-15, atol=1e-15)
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 = cells[:, perm_vtk(CellType.quadrilateral, cells.shape[1])] cell = ufl.Cell("quadrilateral", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 3)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) def e2(x): return x[2] + x[0] * x[1] # Interpolate function V = FunctionSpace(mesh, ("CG", 3)) u = Function(V) u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) nodes = [0, 3, 10, 11] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-6)
def xtest_quadrilateral_integral(space_type, space_order): domain = ufl.Mesh(ufl.VectorElement("Lagrange", "quadrilateral", 1)) temp_points = np.array([[-1., -1.], [0., 0.], [1., 0.], [-1., 1.], [0., 1.], [2., 2.]]) for repeat in range(10): order = [i for i, j in enumerate(temp_points)] shuffle(order) points = np.zeros(temp_points.shape) for i, j in enumerate(order): points[j] = temp_points[i] connections = {0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2]} cells = [] for cell in [[0, 1, 3, 4], [1, 2, 4, 5]]: # Randomly number the cell start = choice(range(4)) cell_order = [start] for i in range(2): diff = choice([ i for i in connections[start] if i not in cell_order ]) - cell_order[0] cell_order += [c + diff for c in cell_order] cells.append([order[cell[i]] for i in cell_order]) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) V = FunctionSpace(mesh, (space_type, space_order)) Vvec = VectorFunctionSpace(mesh, ("P", 1)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] for d in dofs: v = Function(V) v.vector[:] = [ 1 if i == d else 0 for i in range(v.vector.local_size) ] if space_type in ["RTCF"]: # Hdiv def normal(x): values = np.zeros((2, x.shape[1])) values[0] = [1 for i in values[0]] return values n = Function(Vvec) n.interpolate(normal) form = ufl.inner(ufl.jump(v), n) * ufl.dS elif space_type in ["RTCE"]: # Hcurl def tangent(x): values = np.zeros((2, x.shape[1])) values[1] = [1 for i in values[1]] return values t = Function(Vvec) t.interpolate(tangent) form = ufl.inner(ufl.jump(v), t) * ufl.dS else: form = ufl.jump(v) * ufl.dS value = fem.assemble_scalar(form) assert np.isclose(value, 0)