def test_de_rahm_2D(order): mesh = create_unit_square(MPI.COMM_WORLD, 3, 4) W = FunctionSpace(mesh, ("Lagrange", order)) w = Function(W) w.interpolate(lambda x: x[0] + x[0] * x[1] + 2 * x[1]**2) g = ufl.grad(w) Q = FunctionSpace(mesh, ("N2curl", order - 1)) q = Function(Q) q.interpolate(Expression(g, Q.element.interpolation_points)) x = ufl.SpatialCoordinate(mesh) g_ex = ufl.as_vector((1 + x[1], 4 * x[1] + x[0])) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(q - g_ex, q - g_ex) * ufl.dx))), 0) V = FunctionSpace(mesh, ("BDM", order - 1)) v = Function(V) def curl2D(u): return ufl.as_vector((ufl.Dx(u[1], 0), -ufl.Dx(u[0], 1))) v.interpolate( Expression(curl2D(ufl.grad(w)), V.element.interpolation_points)) h_ex = ufl.as_vector((1, -1)) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(v - h_ex, v - h_ex) * ufl.dx))), 0)
def CubedSphereMesh(radius, refinement_level=0, degree=1, reorder=None, comm=COMM_WORLD): """Generate an cubed approximation to the surface of the sphere. :arg radius: The radius of the sphere to approximate. :kwarg refinement_level: optional number of refinements (0 is a cube). :kwarg degree: polynomial degree of coordinate space (defaults to 1: bilinear quads) :kwarg reorder: (optional), should the mesh be reordered? """ if refinement_level < 0 or refinement_level % 1: raise RuntimeError("Number of refinements must be a non-negative integer") if degree < 1: raise ValueError("Mesh coordinate degree must be at least 1") cells, coords = _cubedsphere_cells_and_coords(radius, refinement_level) plex = mesh._from_cell_list(2, cells, coords, comm) m = mesh.Mesh(plex, dim=3, reorder=reorder) if degree > 1: new_coords = function.Function(functionspace.VectorFunctionSpace(m, "Q", degree)) new_coords.interpolate(ufl.SpatialCoordinate(m)) # "push out" to sphere new_coords.dat.data[:] *= (radius / np.linalg.norm(new_coords.dat.data, axis=1)).reshape(-1, 1) m = mesh.Mesh(new_coords) m._radius = radius return m
def test_nedelec_spatial(order, dim): if dim == 2: mesh = create_unit_square(MPI.COMM_WORLD, 4, 4) elif dim == 3: mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) V = FunctionSpace(mesh, ("N1curl", order)) u = Function(V) x = ufl.SpatialCoordinate(mesh) # The expression (x,y,z) is contained in the N1curl function space # order>1 f_ex = x f = Expression(f_ex, V.element.interpolation_points) u.interpolate(f) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(u - f_ex, u - f_ex) * ufl.dx))), 0) # The target expression is also contained in N2curl space of any # order V2 = FunctionSpace(mesh, ("N2curl", 1)) w = Function(V2) f2 = Expression(f_ex, V2.element.interpolation_points) w.interpolate(f2) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(w - f_ex, w - f_ex) * ufl.dx))), 0)
def __init__(self, mesh, lame, model): def sigma_law(u): return lame[0] * ufl.nabla_div(u) * ufl.Identity( 2) + 2 * lame[1] * symgrad(u) self.sigma_law = sigma_law self.mesh = mesh self.model = model self.coord_min = np.min(self.mesh.coordinates(), axis=0) self.coord_max = np.max(self.mesh.coordinates(), axis=0) # it should be modified before computing tangent (if needed) self.others = { "polyorder": 1, "x0": self.coord_min[0], "x1": self.coord_max[0], "y0": self.coord_min[1], "y1": self.coord_max[1] } self.multiscale_model = list_multiscale_models[model] self.x = ufl.SpatialCoordinate(self.mesh) self.ndim = 2 self.nvoigt = int(self.ndim * (self.ndim + 1) / 2) self.Chom_ = None # will be computed by get_tangent
def test_interpolate_subset(order, dim, affine): if dim == 2: ct = CellType.triangle if affine else CellType.quadrilateral mesh = create_unit_square(MPI.COMM_WORLD, 3, 4, ct) elif dim == 3: ct = CellType.tetrahedron if affine else CellType.hexahedron mesh = create_unit_cube(MPI.COMM_WORLD, 3, 2, 2, ct) V = FunctionSpace(mesh, ("DG", order)) u = Function(V) cells = locate_entities(mesh, mesh.topology.dim, lambda x: x[1] <= 0.5 + 1e-10) num_local_cells = mesh.topology.index_map(mesh.topology.dim).size_local cells_local = cells[cells < num_local_cells] x = ufl.SpatialCoordinate(mesh) f = x[1]**order expr = Expression(f, V.element.interpolation_points) u.interpolate(expr, cells_local) mt = MeshTags(mesh, mesh.topology.dim, cells_local, np.ones(cells_local.size, dtype=np.int32)) dx = ufl.Measure("dx", domain=mesh, subdomain_data=mt) assert np.isclose( np.abs(form(assemble_scalar(form(ufl.inner(u - f, u - f) * dx(1))))), 0) integral = mesh.comm.allreduce(assemble_scalar(form(u * dx)), op=MPI.SUM) assert np.isclose(integral, 1 / (order + 1) * 0.5**(order + 1), 0)
def fenics_cost(u, f): x = ufl.SpatialCoordinate(mesh) w = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) d = 1 / (2 * ufl.pi ** 2) * w alpha = fa.Constant(1e-6) J_form = (0.5 * ufl.inner(u - d, u - d)) * ufl.dx + alpha / 2 * f ** 2 * ufl.dx J = fa.assemble(J_form) return J
def __init__(self, functionSpace, value, xL, xR, eps=1e-10): cond = 1 x = ufl.SpatialCoordinate(functionSpace) for l, r, c in zip(xL, xR, x): if l is not None: cond *= ufl.conditional(c > l - eps, 1, 0) if r is not None: cond *= ufl.conditional(c < r + eps, 1, 0) DirichletBC.__init__(self, functionSpace, value, cond)
def test_ufl_only_spatialcoordinate(): mesh = ufl.Mesh(ufl.VectorElement("P", ufl.triangle, 1)) V = ufl.FunctionSpace(mesh, ufl.FiniteElement("P", ufl.triangle, 2)) x, y = ufl.SpatialCoordinate(mesh) expr = x * y - y**2 + x W = V to_element = create_element(W.ufl_element()) ast, oriented, needs_cell_sizes, coefficients, first_coeff_fake_coords, *_ = compile_expression_dual_evaluation( expr, to_element, coffee=False) assert first_coeff_fake_coords is True
def test_conditional(mode, compile_args): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) x = ufl.SpatialCoordinate(cell) condition = ufl.Or(ufl.ge(ufl.real(x[0] + x[1]), 0.1), ufl.ge(ufl.real(x[1] + x[1]**2), 0.1)) c1 = ufl.conditional(condition, 2.0, 1.0) a = c1 * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx x1x2 = ufl.real(x[0] + ufl.as_ufl(2) * x[1]) c2 = ufl.conditional(ufl.ge(x1x2, 0), 6.0, 0.0) b = c2 * ufl.conj(v) * ufl.dx forms = [a, b] compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}, cffi_extra_compile_args=compile_args) form0 = compiled_forms[0][0].create_cell_integral(-1) form1 = compiled_forms[1][0].create_cell_integral(-1) ffi = cffi.FFI() c_type, np_type = float_to_type(mode) A1 = np.zeros((3, 3), dtype=np_type) w1 = np.array([1.0, 1.0, 1.0], dtype=np_type) c = np.array([], dtype=np.float64) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.array([[2, -1, -1], [-1, 1, 0], [-1, 0, 1]], dtype=np_type) assert np.allclose(A1, expected_result) A2 = np.zeros(3, dtype=np_type) w2 = np.array([1.0, 1.0, 1.0], dtype=np_type) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form1.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.ones(3, dtype=np_type) assert np.allclose(A2, expected_result)
def test_assemble_functional_dx(mode): mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) M = form(1.0 * dx(domain=mesh)) value = assemble_scalar(M) value = mesh.comm.allreduce(value, op=MPI.SUM) assert value == pytest.approx(1.0, 1e-12) x = ufl.SpatialCoordinate(mesh) M = form(x[0] * dx(domain=mesh)) value = assemble_scalar(M) value = mesh.comm.allreduce(value, op=MPI.SUM) assert value == pytest.approx(0.5, 1e-12)
def to_reference_coordinates(ufl_coordinate_element): # Set up UFL form cell = ufl_coordinate_element.cell() domain = ufl.Mesh(ufl_coordinate_element) K = ufl.JacobianInverse(domain) x = ufl.SpatialCoordinate(domain) x0_element = ufl.VectorElement("Real", cell, 0) x0 = ufl.Coefficient(ufl.FunctionSpace(domain, x0_element)) expr = ufl.dot(K, x - x0) # Translation to GEM C = ufl_utils.coordinate_coefficient(domain) expr = ufl_utils.preprocess_expression(expr) expr = ufl_utils.replace_coordinates(expr, C) expr = ufl_utils.simplify_abs(expr) builder = firedrake_interface.KernelBuilderBase() builder._coefficient(C, "C") builder._coefficient(x0, "x0") dim = cell.topological_dimension() point = gem.Variable('X', (dim, )) context = tsfc.fem.GemPointContext( interface=builder, ufl_cell=cell, precision=parameters["precision"], point_indices=(), point_expr=point, ) translator = tsfc.fem.Translator(context) ir = map_expr_dag(translator, expr) # Unroll result ir = [gem.Indexed(ir, alpha) for alpha in numpy.ndindex(ir.shape)] # Unroll IndexSums max_extent = parameters["unroll_indexsum"] if max_extent: def predicate(index): return index.extent <= max_extent ir = gem.optimise.unroll_indexsum(ir, predicate=predicate) # Translate to COFFEE ir = impero_utils.preprocess_gem(ir) return_variable = gem.Variable('dX', (dim, )) assignments = [(gem.Indexed(return_variable, (i, )), e) for i, e in enumerate(ir)] impero_c = impero_utils.compile_gem(assignments, ()) body = tsfc.coffee.generate(impero_c, {}, parameters["precision"]) body.open_scope = False return body
def test_assemble_functional_dx(mode): mesh = UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) M = 1.0 * dx(domain=mesh) value = dolfinx.fem.assemble_scalar(M) value = mesh.mpi_comm().allreduce(value, op=MPI.SUM) assert value == pytest.approx(1.0, 1e-12) x = ufl.SpatialCoordinate(mesh) M = x[0] * dx(domain=mesh) value = dolfinx.fem.assemble_scalar(M) value = mesh.mpi_comm().allreduce(value, op=MPI.SUM) assert value == pytest.approx(0.5, 1e-12)
def transfer_form(F, newmesh, transfer=firedrake.prolong, replace_map={}): """ Given a form defined on some mesh, generate a new form with all the same components, but transferred onto a different mesh. :arg F: the form to be transferred :arg newmesh: the mesh to transfer the form to :kwarg transfer: the transfer operator to use :kwarg replace_map: user-provided replace map """ f = 0 # We replace at least the coordinate map replace_map = { ufl.SpatialCoordinate(F.ufl_domain()): ufl.SpatialCoordinate(newmesh) } # Test and trial functions are also replaced if len(F.arguments()) > 0: Vold = F.arguments()[0].function_space() Vnew = firedrake.FunctionSpace(newmesh, Vold.ufl_element()) replace_map[firedrake.TestFunction(Vold)] = firedrake.TestFunction( Vnew) replace_map[firedrake.TrialFunction(Vold)] = firedrake.TrialFunction( Vnew) # As well as any spatially varying coefficients for c in F.coefficients(): if isinstance(c, firedrake.Function) and c not in replace_map: replace_map[c] = firedrake.Function( firedrake.FunctionSpace(newmesh, c.ufl_element())) transfer(c, replace_map[c]) # The form is reconstructed by cell type for cell_type, dX in zip(("cell", "exterior_facet", "interior_facet"), (ufl.dx, ufl.ds, ufl.dS)): for integral in F.integrals_by_type(cell_type): differential = dX(integral.subdomain_id(), domain=newmesh) f += ufl.replace(integral.integrand(), replace_map) * differential return f
def SpatialCoordinate(mesh: cpp.mesh.Mesh) -> ufl.SpatialCoordinate: """Return symbolic physical coordinates for given mesh. *Example of usage* .. code-block:: python mesh = UnitSquare(4,4) x = SpatialCoordinate(mesh) """ return ufl.SpatialCoordinate(mesh.ufl_domain())
def test_projection(): mesh = dolfin.UnitCubeMesh(dolfin.MPI.comm_world, 4, 4, 4) V = dolfin.function.FunctionSpace(mesh, ("CG", 1)) x = ufl.SpatialCoordinate(mesh) expr = x[0]**2 f = dolfin.project(expr, V) integral = dolfin.fem.assemble_scalar(f * ufl.dx) integral = dolfin.MPI.sum(mesh.mpi_comm(), integral) integral_analytic = 1.0 / 3 assert integral == pytest.approx(integral_analytic, rel=1.e-6, abs=1.e-12)
def test_complex_assembly(): """Test assembly of complex matrices and vectors""" mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 10, 10) P2 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 2) V = dolfinx.function.FunctionSpace(mesh, P2) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) g = -2 + 3.0j j = 1.0j a_real = inner(u, v) * dx L1 = inner(g, v) * dx b = dolfinx.fem.assemble_vector(L1) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) bnorm = b.norm(PETSc.NormType.N1) b_norm_ref = abs(-2 + 3.0j) assert bnorm == pytest.approx(b_norm_ref) A = dolfinx.fem.assemble_matrix(a_real) A.assemble() A0_norm = A.norm(PETSc.NormType.FROBENIUS) x = ufl.SpatialCoordinate(mesh) a_imag = j * inner(u, v) * dx f = 1j * ufl.sin(2 * np.pi * x[0]) L0 = inner(f, v) * dx A = dolfinx.fem.assemble_matrix(a_imag) A.assemble() A1_norm = A.norm(PETSc.NormType.FROBENIUS) assert A0_norm == pytest.approx(A1_norm) b = dolfinx.fem.assemble_vector(L0) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) b1_norm = b.norm(PETSc.NormType.N2) a_complex = (1 + j) * inner(u, v) * dx f = ufl.sin(2 * np.pi * x[0]) L2 = inner(f, v) * dx A = dolfinx.fem.assemble_matrix(a_complex) A.assemble() A2_norm = A.norm(PETSc.NormType.FROBENIUS) assert A1_norm == pytest.approx(A2_norm / np.sqrt(2)) b = dolfinx.fem.assemble_vector(L2) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) b2_norm = b.norm(PETSc.NormType.N2) assert b2_norm == pytest.approx(b1_norm)
def test_complex_assembly_solve(): """Solve a positive definite helmholtz problem and verify solution with the method of manufactured solutions """ degree = 3 mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 20, 20) P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), degree) V = dolfinx.function.FunctionSpace(mesh, P) x = ufl.SpatialCoordinate(mesh) # Define source term A = 1.0 + 2.0 * (2.0 * np.pi)**2 f = (1. + 1j) * A * ufl.cos(2 * np.pi * x[0]) * ufl.cos(2 * np.pi * x[1]) # Variational problem u = ufl.TrialFunction(V) v = ufl.TestFunction(V) C = 1.0 + 1.0j a = C * inner(grad(u), grad(v)) * dx + C * inner(u, v) * dx L = inner(f, v) * dx # Assemble A = dolfinx.fem.assemble_matrix(a) A.assemble() b = dolfinx.fem.assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Create solver solver = PETSc.KSP().create(mesh.mpi_comm()) solver.setOptionsPrefix("test_lu_") opts = PETSc.Options("test_lu_") opts["ksp_type"] = "preonly" opts["pc_type"] = "lu" solver.setFromOptions() x = A.createVecRight() solver.setOperators(A) solver.solve(b, x) # Reference Solution def ref_eval(x): return np.cos(2 * np.pi * x[0]) * np.cos(2 * np.pi * x[1]) u_ref = dolfinx.function.Function(V) u_ref.interpolate(ref_eval) diff = (x - u_ref.vector).norm(PETSc.NormType.N2) assert diff == pytest.approx(0.0, abs=1e-1)
def test_vector_interpolation_spatial(order, dim, affine): if dim == 2: ct = CellType.triangle if affine else CellType.quadrilateral mesh = create_unit_square(MPI.COMM_WORLD, 3, 4, ct) elif dim == 3: ct = CellType.tetrahedron if affine else CellType.hexahedron mesh = create_unit_cube(MPI.COMM_WORLD, 3, 2, 2, ct) V = VectorFunctionSpace(mesh, ("Lagrange", order)) u = Function(V) x = ufl.SpatialCoordinate(mesh) # The expression (x,y,z)^n is contained in space f = ufl.as_vector([x[i]**order for i in range(dim)]) u.interpolate(Expression(f, V.element.interpolation_points)) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(u - f, u - f) * ufl.dx))), 0)
def SpatialCoordinate(mesh): """Return symbolic physical coordinates for given mesh. *Arguments* mesh a :py:class:`Mesh <dolfin.cpp.Mesh>`. *Example of usage* .. code-block:: python mesh = UnitSquare(4,4) x = SpatialCoordinate(mesh) """ return ufl.SpatialCoordinate(_mesh2domain(mesh))
def methods(self,code): predefined = {} x = ufl.SpatialCoordinate(ufl.triangle) # NOTE: to do get right dimension predefined[x] = self.spatialCoordinate('x') self.predefineCoefficients(predefined, False) codegen.generateMethod(code, self.expr, 'typename FunctionSpaceType::RangeType', 'evaluate', returnResult=False, args=['const Point &x'], targs=['class Point'], const=True, predefined=predefined) if checks.is_globally_constant(self.expr): code.append( Method('void', 'jacobian', targs=['class Point'], args=['const Point &x','typename FunctionSpaceType::JacobianRangeType &result'], code=['result=typename FunctionSpaceType::JacobianRangeType(0);'], const=True)) code.append( Method('void', 'hessian', targs=['class Point'], args=['const Point &x','typename FunctionSpaceType::HessianRangeType &result'], code=['result=typename FunctionSpaceType::HessianRangeType(0);'], const=True)) else: try: codegen.generateMethod(code, ufl.grad(self.expr), 'typename FunctionSpaceType::JacobianRangeType', 'jacobian', returnResult=False, args=['const Point &x'], targs=['class Point'], const=True, predefined=predefined) except Exception as e: code.append( Method('void', 'jacobian', targs=['class Point'], args=['const Point &x','typename FunctionSpaceType::JacobianRangeType &result'], code=['DUNE_THROW(Dune::NotImplemented,"jacobian method could not be generated for local function ('+repr(e)+').");', 'result=typename FunctionSpaceType::JacobianRangeType(0);'], const=True)) pass try: codegen.generateMethod(code, ufl.grad(ufl.grad(self.expr)), 'typename FunctionSpaceType::HessianRangeType', 'hessian', returnResult=False, args=['const Point &x'], targs=['class Point'], const=True, predefined=predefined) except Exception as e: code.append( Method('void', 'hessian', targs=['class Point'], args=['const Point &x','typename FunctionSpaceType::HessianRangeType &result'], code=['DUNE_THROW(Dune::NotImplemented,"hessian method could not be generated for local function ('+repr(e)+')");', 'result=typename FunctionSpaceType::HessianRangeType(0);'], const=True)) pass
def test_mpc_assembly(master_point, degree, celltype, get_assemblers): # noqa: F811 _, assemble_vector = get_assemblers # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 3, 5, celltype) V = fem.FunctionSpace(mesh, ("Lagrange", degree)) # Generate reference vector v = ufl.TestFunction(V) x = ufl.SpatialCoordinate(mesh) f = ufl.sin(2 * ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) rhs = ufl.inner(f, v) * ufl.dx linear_form = fem.form(rhs) def l2b(li): return np.array(li, dtype=np.float64).tobytes() s_m_c = { l2b([1, 0]): { l2b([0, 1]): 0.43, l2b([1, 1]): 0.11 }, l2b([0, 0]): { l2b(master_point): 0.69 } } mpc = dolfinx_mpc.MultiPointConstraint(V) mpc.create_general_constraint(s_m_c) mpc.finalize() b = assemble_vector(linear_form, mpc) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) # Reduce system with global matrix K after assembly L_org = fem.petsc.assemble_vector(linear_form) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) root = 0 comm = mesh.comm with Timer("~TEST: Compare"): dolfinx_mpc.utils.compare_mpc_rhs(L_org, b, mpc, root=root) list_timings(comm, [TimingType.wall])
def test_diff(): f = dolfinx.fem.Function(CG1) f.vector.set(1.0) f.vector.ghostUpdate() x = ufl.SpatialCoordinate(mesh) expr = x[0] + x[1] + f h_project = dolfinx.fem.Function(CG1) dolfiny.projection.project(expr, h_project) h_interp = dolfinx.fem.Function(CG1) dolfiny.interpolation.interpolate(expr, h_interp) diff = dolfinx.fem.Function(CG1) dolfiny.interpolation.interpolate(h_interp - h_project, diff) assert diff.vector.norm(3) < 1.0e-3
def get_tangent(self): if self.Chom_ is None: self.Chom_ = np.zeros((self.nvoigt, self.nvoigt)) dy = ufl.Measure("dx", self.mesh) vol = df.assemble(df.Constant(1.0) * dy) y = ufl.SpatialCoordinate(self.mesh) Eps = df.Constant(((0., 0.), (0., 0.))) # just placeholder form = self.multiscale_model(self.mesh, self.sigma_law, Eps, self.others) a, f, bcs, W = form() start = timer() A = mp.block_assemble(a) if len(bcs) > 0: bcs.apply(A) # decompose just once, since the matrix A is the same in every solve solver = df.PETScLUSolver("superlu") sol = mp.BlockFunction(W) end = timer() print("time assembling system", end - start) for i in range(self.nvoigt): start = timer() Eps.assign(df.Constant(self.macro_strain(i))) F = mp.block_assemble(f) if len(bcs) > 0: bcs.apply(F) solver.solve(A, sol.block_vector(), F) sol.block_vector().block_function().apply("to subfunctions") sig_mu = self.sigma_law(df.dot(Eps, y) + sol[0]) sigma_hom = self.integrate(sig_mu, dy, (2, 2)) / vol self.Chom_[:, i] = sigma_hom.flatten()[[0, 3, 1]] end = timer() print("time in solving system", end - start) return self.Chom_
def test_2D_lagrange_to_curl(order): mesh = create_unit_square(MPI.COMM_WORLD, 3, 4) V = FunctionSpace(mesh, ("N1curl", order)) u = Function(V) W = FunctionSpace(mesh, ("Lagrange", order)) u0 = Function(W) u0.interpolate(lambda x: -x[1]) u1 = Function(W) u1.interpolate(lambda x: x[0]) f = ufl.as_vector((u0, u1)) f_expr = Expression(f, V.element.interpolation_points) u.interpolate(f_expr) x = ufl.SpatialCoordinate(mesh) f_ex = ufl.as_vector((-x[1], x[0])) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(u - f_ex, u - f_ex) * ufl.dx))), 0)
def dg_injection_kernel(Vf, Vc, ncell): from firedrake import Tensor, AssembledVector, TestFunction, TrialFunction from firedrake.slate.slac import compile_expression macro_builder = MacroKernelBuilder(ScalarType_c, ncell) f = ufl.Coefficient(Vf) macro_builder.set_coefficients([f]) macro_builder.set_coordinates(Vf.mesh()) Vfe = create_element(Vf.ufl_element()) macro_quadrature_rule = make_quadrature( Vfe.cell, estimate_total_polynomial_degree(ufl.inner(f, f))) index_cache = {} parameters = default_parameters() integration_dim, entity_ids = lower_integral_type(Vfe.cell, "cell") macro_cfg = dict(interface=macro_builder, ufl_cell=Vf.ufl_cell(), precision=parameters["precision"], integration_dim=integration_dim, entity_ids=entity_ids, index_cache=index_cache, quadrature_rule=macro_quadrature_rule) fexpr, = fem.compile_ufl(f, **macro_cfg) X = ufl.SpatialCoordinate(Vf.mesh()) C_a, = fem.compile_ufl(X, **macro_cfg) detJ = ufl_utils.preprocess_expression( abs(ufl.JacobianDeterminant(f.ufl_domain()))) macro_detJ, = fem.compile_ufl(detJ, **macro_cfg) Vce = create_element(Vc.ufl_element()) coarse_builder = firedrake_interface.KernelBuilder("cell", "otherwise", 0, ScalarType_c) coarse_builder.set_coordinates(Vc.mesh()) argument_multiindices = (Vce.get_indices(), ) argument_multiindex, = argument_multiindices return_variable, = coarse_builder.set_arguments((ufl.TestFunction(Vc), ), argument_multiindices) integration_dim, entity_ids = lower_integral_type(Vce.cell, "cell") # Midpoint quadrature for jacobian on coarse cell. quadrature_rule = make_quadrature(Vce.cell, 0) coarse_cfg = dict(interface=coarse_builder, ufl_cell=Vc.ufl_cell(), precision=parameters["precision"], integration_dim=integration_dim, entity_ids=entity_ids, index_cache=index_cache, quadrature_rule=quadrature_rule) X = ufl.SpatialCoordinate(Vc.mesh()) K = ufl_utils.preprocess_expression(ufl.JacobianInverse(Vc.mesh())) C_0, = fem.compile_ufl(X, **coarse_cfg) K, = fem.compile_ufl(K, **coarse_cfg) i = gem.Index() j = gem.Index() C_0 = gem.Indexed(C_0, (j, )) C_0 = gem.index_sum(C_0, quadrature_rule.point_set.indices) C_a = gem.Indexed(C_a, (j, )) X_a = gem.Sum(C_0, gem.Product(gem.Literal(-1), C_a)) K_ij = gem.Indexed(K, (i, j)) K_ij = gem.index_sum(K_ij, quadrature_rule.point_set.indices) X_a = gem.index_sum(gem.Product(K_ij, X_a), (j, )) C_0, = quadrature_rule.point_set.points C_0 = gem.Indexed(gem.Literal(C_0), (i, )) # fine quad points in coarse reference space. X_a = gem.Sum(C_0, gem.Product(gem.Literal(-1), X_a)) X_a = gem.ComponentTensor(X_a, (i, )) # Coarse basis function evaluated at fine quadrature points phi_c = fem.fiat_to_ufl( Vce.point_evaluation(0, X_a, (Vce.cell.get_dimension(), 0)), 0) tensor_indices = tuple(gem.Index(extent=d) for d in f.ufl_shape) phi_c = gem.Indexed(phi_c, argument_multiindex + tensor_indices) fexpr = gem.Indexed(fexpr, tensor_indices) quadrature_weight = macro_quadrature_rule.weight_expression expr = gem.Product(gem.IndexSum(gem.Product(phi_c, fexpr), tensor_indices), gem.Product(macro_detJ, quadrature_weight)) quadrature_indices = macro_builder.indices + macro_quadrature_rule.point_set.indices reps = spectral.Integrals([expr], quadrature_indices, argument_multiindices, parameters) assignments = spectral.flatten([(return_variable, reps)], index_cache) return_variables, expressions = zip(*assignments) expressions = impero_utils.preprocess_gem(expressions, **spectral.finalise_options) assignments = list(zip(return_variables, expressions)) impero_c = impero_utils.compile_gem(assignments, quadrature_indices + argument_multiindex, remove_zeros=True) index_names = [] def name_index(index, name): index_names.append((index, name)) if index in index_cache: for multiindex, suffix in zip(index_cache[index], string.ascii_lowercase): name_multiindex(multiindex, name + suffix) def name_multiindex(multiindex, name): if len(multiindex) == 1: name_index(multiindex[0], name) else: for i, index in enumerate(multiindex): name_index(index, name + str(i)) name_multiindex(quadrature_indices, 'ip') for multiindex, name in zip(argument_multiindices, ['j', 'k']): name_multiindex(multiindex, name) index_names.extend(zip(macro_builder.indices, ["entity"])) body = generate_coffee(impero_c, index_names, parameters["precision"], ScalarType_c) retarg = ast.Decl(ScalarType_c, ast.Symbol("R", rank=(Vce.space_dimension(), ))) local_tensor = coarse_builder.local_tensor local_tensor.init = ast.ArrayInit( numpy.zeros(Vce.space_dimension(), dtype=ScalarType_c)) body.children.insert(0, local_tensor) args = [retarg] + macro_builder.kernel_args + [ macro_builder.coordinates_arg, coarse_builder.coordinates_arg ] # Now we have the kernel that computes <f, phi_c>dx_c # So now we need to hit it with the inverse mass matrix on dx_c u = TrialFunction(Vc) v = TestFunction(Vc) expr = Tensor(ufl.inner(u, v) * ufl.dx).inv * AssembledVector( ufl.Coefficient(Vc)) Ainv, = compile_expression(expr) Ainv = Ainv.kinfo.kernel A = ast.Symbol(local_tensor.sym.symbol) R = ast.Symbol("R") body.children.append( ast.FunCall(Ainv.name, R, coarse_builder.coordinates_arg.sym, A)) from coffee.base import Node assert isinstance(Ainv._code, Node) return op2.Kernel(ast.Node([ Ainv._code, ast.FunDecl("void", "pyop2_kernel_injection_dg", args, body, pred=["static", "inline"]) ]), name="pyop2_kernel_injection_dg", cpp=True, include_dirs=Ainv._include_dirs, headers=Ainv._headers)
import ufl from ufl import grad, div, dot, dx, ds, inner, sin, cos, pi, exp, sqrt import dune.ufl import dune.grid import dune.fem endTime = 0.1 saveInterval = 1 # for VTK gridView = dune.grid.structuredGrid([-1,-1],[1,1],[40,40]) space = dune.fem.space.lagrange(gridView, order=1) u = ufl.TrialFunction(space) phi = ufl.TestFunction(space) x = ufl.SpatialCoordinate(space) dt = dune.ufl.Constant(5e-2, "timeStep") t = dune.ufl.Constant(0.0, "time") # define storage for discrete solutions uh = space.interpolate(0, name="uh") uh_old = uh.copy() # initial solution initial = 0 # problem definition # moving oven ROven = 0.6 omegaOven = 0.01 * pi * t P = ufl.as_vector([ROven*cos(omegaOven*t), ROven*sin(omegaOven*t)])
# =========================== # In the previous sections we have considered CG-1 spaces, which have a # 1-1 correspondence with the vertices of the geometry. To be able to # plot higher order function spaces, both CG and DG spaces, we have to # adjust our plotting technique. # We start by projecting a discontinuous function into a second order DG # space Note that we use the `cell_tags` from the previous section to # restrict the integration domain on the RHS. dx = ufl.Measure("dx", subdomain_data=cell_tags) V = dolfinx.FunctionSpace(mesh, ("DG", 2)) uh = dolfinx.Function(V) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) x = ufl.SpatialCoordinate(mesh) a = ufl.inner(u, v) * dx L = ufl.inner(x[0], v) * dx(1) + ufl.inner(0.01, v) * dx(0) problem = dolfinx.fem.LinearProblem(a, L, u=uh, petsc_options={ "ksp_type": "preonly", "pc_type": "lu" }) problem.solve() # To get a topology that has a 1-1 correspondence with the degrees of # freedom in the function space, we call # `dolfinx.plot.create_vtk_topology`. We obtain the geometry for # the dofs owned on this process by tabulation of the dof coordinates.
spiral_b = 0.02 spiral_eps = 0.02 spiral_D = 1. / 100 def spiral_h(u, v): return u - v else: spiral_a = 0.75 spiral_b = 0.0006 spiral_eps = 0.08 def spiral_h(u, v): return u**3 - v x = ufl.SpatialCoordinate(ufl.triangle) initial_u = ufl.conditional(x[1] > 1.25, 1, 0) initial_v = ufl.conditional(x[0] < 1.25, 0.5, 0) # <markdowncell> # Now we set up the reference domain, the Lagrange finite element space (second order), and discrete functions for $(u^n,v^n($, $(u^{n+1},v^{n+1})$: # <codecell> gridView = dune.grid.structuredGrid([0, 0], [2.5, 2.5], [30, 30]) space = dune.fem.space.lagrange(gridView, dimRange=dimRange, order=1) uh = space.interpolate(initial_u, name="u") uh_n = uh.copy() vh = space.interpolate(initial_v, name="v") vh_n = vh.copy()
def test_pipeline(u_from_mpc): # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) # Solve Problem without MPC for reference u = ufl.TrialFunction(V) v = ufl.TestFunction(V) d = fem.Constant(mesh, PETSc.ScalarType(0.01)) x = ufl.SpatialCoordinate(mesh) f = ufl.sin(2 * ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx - d * ufl.inner(u, v) * ufl.dx rhs = ufl.inner(f, v) * ufl.dx bilinear_form = fem.form(a) linear_form = fem.form(rhs) # Generate reference matrices A_org = fem.petsc.assemble_matrix(bilinear_form) A_org.assemble() L_org = fem.petsc.assemble_vector(linear_form) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) # Create multipoint constraint def periodic_relation(x): out_x = np.copy(x) out_x[0] = 1 - x[0] return out_x def PeriodicBoundary(x): return np.isclose(x[0], 1) facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, PeriodicBoundary) arg_sort = np.argsort(facets) mt = meshtags(mesh, mesh.topology.dim - 1, facets[arg_sort], np.full(len(facets), 2, dtype=np.int32)) mpc = dolfinx_mpc.MultiPointConstraint(V) mpc.create_periodic_constraint_topological(V, mt, 2, periodic_relation, [], 1) mpc.finalize() if u_from_mpc: uh = fem.Function(mpc.function_space) problem = dolfinx_mpc.LinearProblem(bilinear_form, linear_form, mpc, bcs=[], u=uh, petsc_options={"ksp_type": "preonly", "pc_type": "lu"}) problem.solve() root = 0 dolfinx_mpc.utils.compare_mpc_lhs(A_org, problem.A, mpc, root=root) dolfinx_mpc.utils.compare_mpc_rhs(L_org, problem.b, mpc, root=root) # Gather LHS, RHS and solution on one process A_csr = dolfinx_mpc.utils.gather_PETScMatrix(A_org, root=root) K = dolfinx_mpc.utils.gather_transformation_matrix(mpc, root=root) L_np = dolfinx_mpc.utils.gather_PETScVector(L_org, root=root) u_mpc = dolfinx_mpc.utils.gather_PETScVector(uh.vector, root=root) if MPI.COMM_WORLD.rank == root: KTAK = K.T * A_csr * K reduced_L = K.T @ L_np # Solve linear system d = scipy.sparse.linalg.spsolve(KTAK, reduced_L) # Back substitution to full solution vector uh_numpy = K @ d assert np.allclose(uh_numpy, u_mpc) else: uh = fem.Function(V) with pytest.raises(ValueError): problem = dolfinx_mpc.LinearProblem(bilinear_form, linear_form, mpc, bcs=[], u=uh, petsc_options={"ksp_type": "preonly", "pc_type": "lu"}) problem.solve()
def derivative(form, u, du=None, coefficient_derivatives=None): """Compute the derivative of a form. Given a form, this computes its linearization with respect to the provided :class:`.Function`. The resulting form has one additional :class:`Argument` in the same finite element space as the Function. :arg form: a :class:`~ufl.classes.Form` to compute the derivative of. :arg u: a :class:`.Function` to compute the derivative with respect to. :arg du: an optional :class:`Argument` to use as the replacement in the new form (constructed automatically if not provided). :arg coefficient_derivatives: an optional :class:`dict` to provide the derivative of a coefficient function. :raises ValueError: If any of the coefficients in ``form`` were obtained from ``u.split()``. UFL doesn't notice that these are related to ``u`` and so therefore the derivative is wrong (instead one should have written ``split(u)``). See also :func:`ufl.derivative`. """ # TODO: What about Constant? u_is_x = isinstance(u, ufl.SpatialCoordinate) if not u_is_x and len(u.split()) > 1 and set( extract_coefficients(form)) & set(u.split()): raise ValueError( "Taking derivative of form wrt u, but form contains coefficients from u.split()." "\nYou probably meant to write split(u) when defining your form.") mesh = form.ufl_domain() is_dX = u_is_x or u is mesh.coordinates args = form.arguments() def argument(V): if du is None: n = max(a.number() for a in args) if args else -1 return Argument(V, n + 1) else: return du if is_dX: coords = mesh.coordinates u = ufl.SpatialCoordinate(mesh) V = coords.function_space() du = argument(V) cds = {coords: du} if coefficient_derivatives is not None: cds.update(coefficient_derivatives) coefficient_derivatives = cds elif isinstance(u, firedrake.Function): V = u.function_space() du = argument(V) elif isinstance(u, firedrake.Constant): if u.ufl_shape != (): raise ValueError( "Real function space of vector elements not supported") V = firedrake.FunctionSpace(mesh, "Real", 0) du = argument(V) else: raise RuntimeError("Can't compute derivative for form") return ufl.derivative(form, u, du, coefficient_derivatives)