def test_basic_assembly_constant(mode): """Tests assembly with Constant The following test should be sensitive to order of flattening the matrix-valued constant. """ mesh = UnitSquareMesh(MPI.COMM_WORLD, 5, 5, ghost_mode=mode) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) c = fem.Constant(mesh, [[1.0, 2.0], [5.0, 3.0]]) a = inner(c[1, 0] * u, v) * dx + inner(c[1, 0] * u, v) * ds L = inner(c[1, 0], v) * dx + inner(c[1, 0], v) * ds # Initial assembly A1 = dolfinx.fem.assemble_matrix(a) A1.assemble() b1 = dolfinx.fem.assemble_vector(L) b1.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) c.value = [[1.0, 2.0], [3.0, 4.0]] A2 = dolfinx.fem.assemble_matrix(a) A2.assemble() b2 = dolfinx.fem.assemble_vector(L) b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) assert (A1 * 3.0 - A2 * 5.0).norm() == pytest.approx(0.0) assert (b1 * 3.0 - b2 * 5.0).norm() == pytest.approx(0.0)
def test_lambda_assembler(): """Tests assembly with a lambda function """ mesh = UnitSquareMesh(MPI.COMM_WORLD, 5, 5) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx # Initial assembly a_form = fem.Form(a) rdata = [] cdata = [] vdata = [] def mat_insert(rows, cols, vals): vdata.append(vals) rdata.append(numpy.repeat(rows, len(cols))) cdata.append(numpy.tile(cols, len(rows))) return 0 dolfinx.cpp.fem.assemble_matrix(mat_insert, a_form._cpp_object, []) vdata = numpy.array(vdata).flatten() cdata = numpy.array(cdata).flatten() rdata = numpy.array(rdata).flatten() mat = scipy.sparse.coo_matrix((vdata, (rdata, cdata))) v = numpy.ones(mat.shape[1]) s = MPI.COMM_WORLD.allreduce(mat.dot(v).sum(), MPI.SUM) assert numpy.isclose(s, 1.0)
def create_cg1_function_space(mesh, sh): r = len(sh) if r == 0: V = fem.FunctionSpace(mesh, ("CG", 1)) elif r == 1: V = fem.VectorFunctionSpace(mesh, ("CG", 1), dim=sh[0]) else: V = fem.TensorFunctionSpace(mesh, ("CG", 1), shape=sh) return V
def assemble(mesh, space, k): V = fem.FunctionSpace(mesh, (space, k)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) dx = ufl.Measure("dx", domain=mesh) a = fem.form(ufl.inner(u, v) * dx) A = fem.petsc.assemble_matrix(a) A.assemble() return A
def test_nonlinear_pde_snes(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 15) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) u = fem.Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = fem.Function(V) with u_bc.vector.localForm() as u_local: u_local.set(1.0) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDE_SNESProblem(F, u, bc) with u.vector.localForm() as u_local: u_local.set(0.9) b = dolfinx.cpp.la.create_vector(V.dofmap.index_map, V.dofmap.index_map_bs) J = dolfinx.cpp.fem.create_matrix(problem.a_comp._cpp_object) # Create Newton solver and solve snes = PETSc.SNES().create() snes.setFunction(problem.F, b) snes.setJacobian(problem.J, J) snes.setTolerances(rtol=1.0e-9, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().setTolerances(rtol=1.0e-9) snes.getKSP().getPC().setType("lu") snes.getKSP().getPC().setFactorSolverType("superlu_dist") snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6 # Modify boundary condition and solve again with u_bc.vector.localForm() as u_local: u_local.set(0.5) snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6
def finalize(self) -> None: """ Finializes the multi point constraint. After this function is called, no new constraints can be added to the constraint. This function creates a map from the cells (local to index) to the slave degrees of freedom and builds a new index map and function space where unghosted master dofs are added as ghosts. """ self._already_finalized() # Initialize C++ object and create slave->cell maps self._cpp_object = dolfinx_mpc.cpp.mpc.MultiPointConstraint( self.V._cpp_object, self._slaves, self._masters, self._coeffs, self._owners, self._offsets) # Replace function space self.V = _fem.FunctionSpace(None, self.V.ufl_element(), self._cpp_object.function_space) self.finalized = True # Delete variables that are no longer required del (self._slaves, self._masters, self._coeffs, self._owners, self._offsets)
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_basic_interior_facet_assembly(): mesh = dolfinx.RectangleMesh( MPI.COMM_WORLD, [numpy.array([0.0, 0.0, 0.0]), numpy.array([1.0, 1.0, 0.0])], [5, 5], cell_type=dolfinx.cpp.mesh.CellType.triangle, ghost_mode=dolfinx.cpp.mesh.GhostMode.shared_facet) V = fem.FunctionSpace(mesh, ("DG", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = ufl.inner(ufl.avg(u), ufl.avg(v)) * ufl.dS A = dolfinx.fem.assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) L = ufl.conj(ufl.avg(v)) * ufl.dS b = dolfinx.fem.assemble_vector(L) b.assemble() assert isinstance(b, PETSc.Vec)
def test_nonlinear_pde(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 5) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) u = dolfinx.fem.Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = fem.Function(V) with u_bc.vector.localForm() as u_local: u_local.set(1.0) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve with u.vector.localForm() as u_local: u_local.set(0.9) solver = dolfinx.cpp.nls.NewtonSolver(MPI.COMM_WORLD) solver.setF(problem.F, problem.vector()) solver.setJ(problem.J, problem.matrix()) solver.set_form(problem.form) n, converged = solver.solve(u.vector) assert converged assert n < 6 # Modify boundary condition and solve again with u_bc.vector.localForm() as u_local: u_local.set(0.5) n, converged = solver.solve(u.vector) assert converged assert n < 6
def test_slave_on_same_cell(master_point, degree, celltype, get_assemblers): # noqa: F811 assemble_matrix, _ = get_assemblers # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 1, 8, celltype) V = fem.FunctionSpace(mesh, ("Lagrange", degree)) # Build master slave map s_m_c = { np.array([1, 0], dtype=np.float64).tobytes(): { np.array([0, 1], dtype=np.float64).tobytes(): 0.43, np.array([1, 1], dtype=np.float64).tobytes(): 0.11 }, np.array([0, 0], dtype=np.float64).tobytes(): { np.array(master_point, dtype=np.float64).tobytes(): 0.69 } } with Timer("~TEST: MPC INIT"): mpc = dolfinx_mpc.MultiPointConstraint(V) mpc.create_general_constraint(s_m_c) mpc.finalize() # Test against generated code and general assembler u = ufl.TrialFunction(V) v = ufl.TestFunction(V) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx bilinear_form = fem.form(a) with Timer("~TEST: Assemble matrix"): A_mpc = assemble_matrix(bilinear_form, mpc) with Timer("~TEST: Compare with numpy"): # Create globally reduced system A_org = fem.petsc.assemble_matrix(bilinear_form) A_org.assemble() dolfinx_mpc.utils.compare_mpc_lhs(A_org, A_mpc, mpc) list_timings(mesh.comm, [TimingType.wall])
def test_mpc_assembly(master_point, degree, celltype, get_assemblers): # noqa: F811 assemble_matrix, _ = get_assemblers # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 5, 3, celltype) V = fem.FunctionSpace(mesh, ("Lagrange", degree)) # Test against generated code and general assembler u = ufl.TrialFunction(V) v = ufl.TestFunction(V) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx bilinear_form = fem.form(a) 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() with Timer("~TEST: Assemble matrix"): A_mpc = assemble_matrix(bilinear_form, mpc) with Timer("~TEST: Compare with numpy"): # Create globally reduced system A_org = fem.petsc.assemble_matrix(bilinear_form) A_org.assemble() dolfinx_mpc.utils.compare_mpc_lhs(A_org, A_mpc, mpc)
def test_pipeline(master_point, get_assemblers): # noqa: F811 assemble_matrix, assemble_vector = get_assemblers # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 3, 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(1.5)) c = fem.Constant(mesh, PETSc.ScalarType(2)) x = ufl.SpatialCoordinate(mesh) f = c * ufl.sin(2 * ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) g = fem.Function(V) g.interpolate(lambda x: np.sin(x[0]) * x[1]) h = fem.Function(V) h.interpolate(lambda x: 2 + x[1] * x[0]) a = d * g * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx rhs = h * 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 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() A = assemble_matrix(bilinear_form, mpc) b = assemble_vector(linear_form, mpc) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) 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 = b.copy() uh.set(0) solver.solve(b, uh) uh.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) mpc.backsubstitution(uh) root = 0 comm = mesh.comm with Timer("~TEST: Compare"): dolfinx_mpc.utils.compare_mpc_lhs(A_org, A, mpc, root=root) dolfinx_mpc.utils.compare_mpc_rhs(L_org, 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, 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) list_timings(comm, [TimingType.wall])
def test_cell_domains(get_assemblers): # noqa: F811 """ Periodic MPC conditions over integral with different cell subdomains """ assemble_matrix, assemble_vector = get_assemblers N = 5 # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 15, N) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) def left_side(x): return x[0] < 0.5 tdim = mesh.topology.dim num_cells = mesh.topology.index_map(tdim).size_local cell_midpoints = compute_midpoints(mesh, tdim, range(num_cells)) values = np.ones(num_cells, dtype=np.intc) # All cells on right side marked one, all other with 1 values += left_side(cell_midpoints.T) ct = meshtags(mesh, mesh.topology.dim, np.arange(num_cells, dtype=np.int32), values) # Solve Problem without MPC for reference u = ufl.TrialFunction(V) v = ufl.TestFunction(V) x = ufl.SpatialCoordinate(mesh) c1 = fem.Constant(mesh, PETSc.ScalarType(2)) c2 = fem.Constant(mesh, PETSc.ScalarType(10)) dx = ufl.Measure("dx", domain=mesh, subdomain_data=ct) a = c1 * ufl.inner(ufl.grad(u), ufl.grad(v)) * dx(1) +\ c2 * ufl.inner(ufl.grad(u), ufl.grad(v)) * dx(2)\ + 0.01 * ufl.inner(u, v) * dx(1) rhs = ufl.inner(x[1], v) * dx(1) + \ ufl.inner(fem.Constant(mesh, PETSc.ScalarType(1)), v) * dx(2) 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) def l2b(li): return np.array(li, dtype=np.float64).tobytes() s_m_c = {} for i in range(0, N + 1): s_m_c[l2b([1, i / N])] = {l2b([0, i / N]): 1} mpc = dolfinx_mpc.MultiPointConstraint(V) mpc.create_general_constraint(s_m_c) mpc.finalize() # Setup MPC system with Timer("~TEST: Assemble matrix old"): A = assemble_matrix(bilinear_form, mpc) with Timer("~TEST: Assemble vector"): b = assemble_vector(linear_form, mpc) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) 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 = b.copy() uh.set(0) solver.solve(b, uh) uh.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) mpc.backsubstitution(uh) root = 0 comm = mesh.comm with Timer("~TEST: Compare"): dolfinx_mpc.utils.compare_mpc_lhs(A_org, A, mpc, root=root) dolfinx_mpc.utils.compare_mpc_rhs(L_org, 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, 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) list_timings(comm, [TimingType.wall])
def test_assembly_solve_taylor_hood(mesh): """Assemble Stokes problem with Taylor-Hood elements and solve.""" P2 = fem.VectorFunctionSpace(mesh, ("Lagrange", 2)) P1 = fem.FunctionSpace(mesh, ("Lagrange", 1)) def boundary0(x): """Define boundary x = 0""" return x[0] < 10 * numpy.finfo(float).eps def boundary1(x): """Define boundary x = 1""" return x[0] > (1.0 - 10 * numpy.finfo(float).eps) # Locate facets on boundaries facetdim = mesh.topology.dim - 1 bndry_facets0 = dolfinx.mesh.locate_entities_boundary( mesh, facetdim, boundary0) bndry_facets1 = dolfinx.mesh.locate_entities_boundary( mesh, facetdim, boundary1) bdofs0 = dolfinx.fem.locate_dofs_topological(P2, facetdim, bndry_facets0) bdofs1 = dolfinx.fem.locate_dofs_topological(P2, facetdim, bndry_facets1) u0 = dolfinx.Function(P2) u0.vector.set(1.0) u0.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) bc0 = dolfinx.DirichletBC(u0, bdofs0) bc1 = dolfinx.DirichletBC(u0, bdofs1) u, p = ufl.TrialFunction(P2), ufl.TrialFunction(P1) v, q = ufl.TestFunction(P2), ufl.TestFunction(P1) a00 = inner(ufl.grad(u), ufl.grad(v)) * dx a01 = ufl.inner(p, ufl.div(v)) * dx a10 = ufl.inner(ufl.div(u), q) * dx a11 = None p00 = a00 p01, p10 = None, None p11 = inner(p, q) * dx # FIXME # We need zero function for the 'zero' part of L p_zero = dolfinx.Function(P1) f = dolfinx.Function(P2) L0 = ufl.inner(f, v) * dx L1 = ufl.inner(p_zero, q) * dx def nested_solve(): """Nested solver""" A = dolfinx.fem.assemble_matrix_nest([[a00, a01], [a10, a11]], [bc0, bc1], [["baij", "aij"], ["aij", ""]]) A.assemble() P = dolfinx.fem.assemble_matrix_nest([[p00, p01], [p10, p11]], [bc0, bc1], [["aij", "aij"], ["aij", ""]]) P.assemble() b = dolfinx.fem.assemble_vector_nest([L0, L1]) dolfinx.fem.apply_lifting_nest(b, [[a00, a01], [a10, a11]], [bc0, bc1]) for b_sub in b.getNestSubVecs(): b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) bcs = dolfinx.cpp.fem.bcs_rows( dolfinx.fem.assemble._create_cpp_form([L0, L1]), [bc0, bc1]) dolfinx.fem.set_bc_nest(b, bcs) b.assemble() ksp = PETSc.KSP() ksp.create(mesh.mpi_comm()) ksp.setOperators(A, P) nested_IS = P.getNestISs() ksp.setType("minres") pc = ksp.getPC() pc.setType("fieldsplit") pc.setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]]) ksp_u, ksp_p = pc.getFieldSplitSubKSP() ksp_u.setType("preonly") ksp_u.getPC().setType('lu') ksp_p.setType("preonly") def monitor(ksp, its, rnorm): # print("Num it, rnorm:", its, rnorm) pass ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setMonitor(monitor) ksp.setFromOptions() x = b.copy() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), nest_matrix_norm(A), nest_matrix_norm(P) def blocked_solve(): """Blocked (monolithic) solver""" A = dolfinx.fem.assemble_matrix_block([[a00, a01], [a10, a11]], [bc0, bc1]) A.assemble() P = dolfinx.fem.assemble_matrix_block([[p00, p01], [p10, p11]], [bc0, bc1]) P.assemble() b = dolfinx.fem.assemble_vector_block([L0, L1], [[a00, a01], [a10, a11]], [bc0, bc1]) ksp = PETSc.KSP() ksp.create(mesh.mpi_comm()) ksp.setOperators(A, P) ksp.setType("minres") pc = ksp.getPC() pc.setType('lu') ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setFromOptions() x = A.createVecRight() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), A.norm(), P.norm() def monolithic_solve(): """Monolithic (interleaved) solver""" P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2_el * P1_el W = dolfinx.FunctionSpace(mesh, TH) (u, p) = ufl.TrialFunctions(W) (v, q) = ufl.TestFunctions(W) a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx a01 = ufl.inner(p, ufl.div(v)) * dx a10 = ufl.inner(ufl.div(u), q) * dx a = a00 + a01 + a10 p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx p11 = ufl.inner(p, q) * dx p_form = p00 + p11 f = dolfinx.Function(W.sub(0).collapse()) p_zero = dolfinx.Function(W.sub(1).collapse()) L0 = inner(f, v) * dx L1 = inner(p_zero, q) * dx L = L0 + L1 bdofsW0_P2_0 = dolfinx.fem.locate_dofs_topological( (W.sub(0), P2), facetdim, bndry_facets0) bdofsW0_P2_1 = dolfinx.fem.locate_dofs_topological( (W.sub(0), P2), facetdim, bndry_facets1) bc0 = dolfinx.DirichletBC(u0, bdofsW0_P2_0, W.sub(0)) bc1 = dolfinx.DirichletBC(u0, bdofsW0_P2_1, W.sub(0)) A = dolfinx.fem.assemble_matrix(a, [bc0, bc1]) A.assemble() P = dolfinx.fem.assemble_matrix(p_form, [bc0, bc1]) P.assemble() b = dolfinx.fem.assemble_vector(L) dolfinx.fem.apply_lifting(b, [a], [[bc0, bc1]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) dolfinx.fem.set_bc(b, [bc0, bc1]) ksp = PETSc.KSP() ksp.create(mesh.mpi_comm()) ksp.setOperators(A, P) ksp.setType("minres") pc = ksp.getPC() pc.setType('lu') def monitor(ksp, its, rnorm): # print("Num it, rnorm:", its, rnorm) pass ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setMonitor(monitor) ksp.setFromOptions() x = A.createVecRight() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), A.norm(), P.norm() bnorm0, xnorm0, Anorm0, Pnorm0 = nested_solve() bnorm1, xnorm1, Anorm1, Pnorm1 = blocked_solve() bnorm2, xnorm2, Anorm2, Pnorm2 = monolithic_solve() assert bnorm1 == pytest.approx(bnorm0, 1.0e-12) assert xnorm1 == pytest.approx(xnorm0, 1.0e-8) assert Anorm1 == pytest.approx(Anorm0, 1.0e-12) assert Pnorm1 == pytest.approx(Pnorm0, 1.0e-12) assert bnorm2 == pytest.approx(bnorm0, 1.0e-12) assert xnorm2 == pytest.approx(xnorm0, 1.0e-8) assert Anorm2 == pytest.approx(Anorm0, 1.0e-12) assert Pnorm2 == pytest.approx(Pnorm0, 1.0e-12)
v = TestFunction(V) du = TrialFunction(V) WCv = TensorElement( "Quadrature", mesh.ufl_cell(), degree=metadata["quadrature_degree"], quad_scheme="default", ) Ws = TensorElement( "Quadrature", mesh.ufl_cell(), degree=metadata["quadrature_degree"], quad_scheme="default", ) VCv = fem.FunctionSpace(mesh, WCv) VS = fem.FunctionSpace(mesh, Ws) CCv = fem.Function(VCv, name="Cv") Cvn = fem.Function(VCv, name="Cvn") C_quart = fem.Function(VCv, name="C_quarter") C_thr_quart = fem.Function(VCv, name="C_thr_quarter") C_half = fem.Function(VCv, name="C_half") C = fem.Function(VCv, name="C") Cn = fem.Function(VCv, name="Cn") Cv_iter = fem.Function(VCv, name="Cv_iter") del_Cv = fem.Function(VCv, name="delCv") S = fem.Function(VS, name="S") # cache to hold intermediate states k_cache = [fem.Function(VCv, name=f"k{i:d}") for i in range(1, 7)]
def test_lifting(get_assemblers): # noqa: F811 """ Test MPC lifting operation on a single cell """ assemble_matrix, assemble_vector = get_assemblers # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 1, 1, CellType.quadrilateral) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) # Solve Problem without MPC for reference u = ufl.TrialFunction(V) v = ufl.TestFunction(V) x = ufl.SpatialCoordinate(mesh) f = x[1] * ufl.sin(2 * ufl.pi * x[0]) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx rhs = ufl.inner(f, v) * ufl.dx bilinear_form = fem.form(a) linear_form = fem.form(rhs) # Create Dirichlet boundary condition u_bc = fem.Function(V) with u_bc.vector.localForm() as u_local: u_local.set(2.3) def dirichletboundary(x): return np.isclose(x[0], 1) mesh.topology.create_connectivity(2, 1) geometrical_dofs = fem.locate_dofs_geometrical(V, dirichletboundary) bc = fem.dirichletbc(u_bc, geometrical_dofs) bcs = [bc] # Generate reference matrices A_org = fem.petsc.assemble_matrix(bilinear_form, bcs=bcs) A_org.assemble() L_org = fem.petsc.assemble_vector(linear_form) fem.petsc.apply_lifting(L_org, [bilinear_form], [bcs]) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) fem.petsc.set_bc(L_org, bcs) # Create multipoint constraint def l2b(li): return np.array(li, dtype=np.float64).tobytes() s_m_c = {l2b([0, 0]): {l2b([0, 1]): 1}} mpc = dolfinx_mpc.MultiPointConstraint(V) mpc.create_general_constraint(s_m_c) mpc.finalize() A = assemble_matrix(bilinear_form, mpc, bcs=bcs) b = assemble_vector(linear_form, mpc) dolfinx_mpc.apply_lifting(b, [bilinear_form], [bcs], mpc) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) fem.petsc.set_bc(b, bcs) 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 = b.copy() uh.set(0) solver.solve(b, uh) uh.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) mpc.backsubstitution(uh) V_mpc = mpc.function_space u_out = fem.Function(V_mpc) u_out.vector.array[:] = uh.array root = 0 comm = mesh.comm with Timer("~TEST: Compare"): dolfinx_mpc.utils.compare_mpc_lhs(A_org, A, mpc, root=root) dolfinx_mpc.utils.compare_mpc_rhs(L_org, 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, root=root) # constants = dolfinx_mpc.utils.gather_contants(mpc, root=root) if MPI.COMM_WORLD.rank == root: KTAK = K.T * A_csr * K reduced_L = K.T @ (L_np) # - constants) # Solve linear system d = scipy.sparse.linalg.spsolve(KTAK, reduced_L) # Back substitution to full solution vecto uh_numpy = K @ (d) # + constants) assert np.allclose(uh_numpy, u_mpc) list_timings(comm, [TimingType.wall])
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()
# - # We begin by using {py:func}`create_rectangle # <dolfinx.mesh.create_rectangle>` to create a rectangular # {py:class}`Mesh <dolfinx.mesh.Mesh>` of the domain, and creating a # finite element {py:class}`FunctionSpace <dolfinx.fem.FunctionSpace>` # $V$ on the mesh. # + msh = mesh.create_rectangle( comm=MPI.COMM_WORLD, points=((0.0, 0.0), (2.0, 1.0)), n=(32, 16), cell_type=mesh.CellType.triangle, ) V = fem.FunctionSpace(msh, ("Lagrange", 1)) # - # The second argument to {py:class}`FunctionSpace # <dolfinx.fem.FunctionSpace>` is a tuple consisting of `(family, # degree)`, where `family` is the finite element family, and `degree` # specifies the polynomial degree. in this case `V` consists of # first-order, continuous Lagrange finite element functions. # # Next, we locate the mesh facets that lie on the boundary $\Gamma_D$. # We do this using using {py:func}`locate_entities_boundary # <dolfinx.mesh.locate_entities_boundary>` and providing a marker # function that returns `True` for points `x` on the boundary and # `False` otherwise. facets = mesh.locate_entities_boundary(
mesh, ft = dolfinx_mpc.utils.gmsh_model_to_mesh(gmsh.model, facet_data=True, gdim=2) gmsh.finalize() return mesh, ft # ------------------- Mesh and function space creation ------------------------ mesh, mt = create_mesh_gmsh(res=0.1) fdim = mesh.topology.dim - 1 # Create the function space P2 = VectorElement("Lagrange", mesh.ufl_cell(), 2) P1 = FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2 * P1 W = fem.FunctionSpace(mesh, TH) V, V_to_W = W.sub(0).collapse() Q, _ = W.sub(1).collapse() def inlet_velocity_expression(x: NDArray[np.float64]) -> NDArray[np.bool_]: return np.stack((np.sin(np.pi * np.sqrt(x[0]**2 + x[1]**2)), 5 * x[1] * np.sin(np.pi * np.sqrt(x[0]**2 + x[1]**2)))) # ----------------------Defining boundary conditions---------------------- # Inlet velocity Dirichlet BC inlet_velocity = fem.Function(V) inlet_velocity.interpolate(inlet_velocity_expression) inlet_velocity.x.scatter_forward() W0 = W.sub(0)
def test_linearproblem(master_point): # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 3, 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(1.5)) c = fem.Constant(mesh, PETSc.ScalarType(2)) x = ufl.SpatialCoordinate(mesh) f = c * ufl.sin(2 * ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) g = fem.Function(V) g.interpolate(lambda x: np.sin(x[0]) * x[1]) h = fem.Function(V) h.interpolate(lambda x: 2 + x[1] * x[0]) a = d * g * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx rhs = h * ufl.inner(f, v) * ufl.dx # Generate reference matrices A_org = fem.petsc.assemble_matrix(fem.form(a)) A_org.assemble() L_org = fem.petsc.assemble_vector(fem.form(rhs)) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) # Create multipoint constraint 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() problem = dolfinx_mpc.LinearProblem(a, rhs, mpc, bcs=[], petsc_options={ "ksp_type": "preonly", "pc_type": "lu" }) uh = problem.solve() root = 0 comm = mesh.comm with Timer("~TEST: Compare"): 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) list_timings(comm, [TimingType.wall])
it_skip = 1 EPS.setMonitor(lambda eps, it, nconv, eig, err: monitor_EPS_short( eps, it, nconv, eig, err, it_skip)) # parse command line options EPS.setFromOptions() # Display all options (including those of ST object) # EPS.view() EPS.solve() EPS_print_results(EPS) return EPS # Create mesh and finite element N = 50 mesh = create_unit_square(MPI.COMM_WORLD, N, N) V = fem.FunctionSpace(mesh, ("CG", 1)) # Create Dirichlet boundary condition u_bc = fem.Function(V) with u_bc.vector.localForm() as u_local: u_local.set(0.0) def dirichletboundary(x): return np.logical_or(np.isclose(x[1], 0), np.isclose(x[1], 1)) fdim = mesh.topology.dim - 1 facets = locate_entities_boundary(mesh, fdim, dirichletboundary) topological_dofs = fem.locate_dofs_topological(V, fdim, facets) bc = fem.dirichletbc(u_bc, topological_dofs)