def run_scalar_test(mesh, V, degree): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ 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) a = form(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) L = form(L) u_bc = Function(V) u_bc.interpolate(lambda x: x[1]**degree) # Create Dirichlet boundary condition facetdim = mesh.topology.dim - 1 mesh.topology.create_connectivity(facetdim, mesh.topology.dim) bndry_facets = np.where( np.array(compute_boundary_facets(mesh.topology)) == 1)[0] bdofs = locate_dofs_topological(V, facetdim, bndry_facets) bc = dirichletbc(u_bc, bdofs) b = assemble_vector(L) apply_lifting(b, [a], bcs=[[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) a = form(a) A = assemble_matrix(a, bcs=[bc]) 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) uh = Function(V) solver.solve(b, uh.vector) uh.x.scatter_forward() M = (u_exact - uh)**2 * dx M = form(M) error = mesh.comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
def test_manufactured_vector2(family, degree, filename, datadir): """Projection into H(div/curl) spaces""" # Skip slowest tests if "tetra" in filename and degree > 2: return with XDMFFile(MPI.comm_world, os.path.join(datadir, filename)) as xdmf: mesh = xdmf.read_mesh(GhostMode.none) # FIXME: these test are currently failing on unordered meshes if "tetra" in filename: if family == "N1curl": Ordering.order_simplex(mesh) V = FunctionSpace(mesh, (family, degree + 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx xp = np.array([0.33, 0.33, 0.0]) tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim) cells = geometry.compute_first_entity_collision(tree, mesh, xp) # Source term x = SpatialCoordinate(mesh) u_ref = x[0]**degree L = inner(u_ref, v[0]) * dx b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a) A.assemble() # Create LU linear solver (Note: need to use a solver that # re-orders to handle pivots, e.g. not the PETSc built-in LU # solver) solver = PETSc.KSP().create(MPI.comm_world) solver.setType("preonly") solver.getPC().setType('lu') solver.setOperators(A) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) up = uh.eval(xp, cells[0]) print("test0:", up) print("test1:", xp[0]**degree) u_exact = np.zeros(mesh.geometry.dim) u_exact[0] = xp[0]**degree assert np.allclose(up, u_exact)
def codeDG(self): code = self._code() u = self.trialFunction ubar = Coefficient(u.ufl_function_space()) penalty = self.penalty if penalty is None: penalty = 1 if isinstance(penalty, Expr): if penalty.ufl_shape == (): penalty = as_vector([penalty]) try: penalty = expand_indices( expand_derivatives(expand_compounds(penalty))) except: pass assert penalty.ufl_shape == u.ufl_shape dmPenalty = as_vector([ replace( expand_derivatives(diff(replace(penalty, {u: ubar}), ubar))[i, i], {ubar: u}) for i in range(u.ufl_shape[0]) ]) else: dmPenalty = None code.append(AccessModifier("public")) x = SpatialCoordinate(self.space.cell()) predefined = {} self.predefineCoefficients(predefined, x) spatial = Variable('const auto', 'y') predefined.update({ x: UnformattedExpression( 'auto', 'entity().geometry().global( Dune::Fem::coordinate( x ) )') }) generateMethod(code, penalty, 'RRangeType', 'penalty', args=['const Point &x', 'const DRangeType &u'], targs=['class Point', 'class DRangeType'], static=False, const=True, predefined=predefined) generateMethod(code, dmPenalty, 'RRangeType', 'linPenalty', args=['const Point &x', 'const DRangeType &u'], targs=['class Point', 'class DRangeType'], static=False, const=True, predefined=predefined) return code
def test_manufactured_vector1(family, degree, filename, datadir): """Projection into H(div/curl) spaces""" 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, (family, degree)) W = VectorFunctionSpace(mesh, ("CG", degree)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx # Source term x = SpatialCoordinate(mesh) u_ref = x[0]**degree L = inner(u_ref, v[0]) * dx b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a) A.assemble() # Create LU linear solver (Note: need to use a solver that # re-orders to handle pivots, e.g. not the PETSc built-in LU # solver) solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType("preonly") solver.getPC().setType('lu') solver.setOperators(A) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) u_exact = Function(W) u_exact.interpolate(lambda x: np.array([ x[0]**degree if i == 0 else 0 * x[0] for i in range(mesh.topology.dim) ])) M = inner(uh - u_exact, uh - u_exact) * 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_vector1(family, degree, filename, datadir): """Projection into H(div/curl) spaces""" 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, (family, degree)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx # Source term x = SpatialCoordinate(mesh) u_ref = x[0]**degree L = inner(u_ref, v[0]) * dx b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a) A.assemble() # Create LU linear solver (Note: need to use a solver that # re-orders to handle pivots, e.g. not the PETSc built-in LU # solver) solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType("preonly") solver.getPC().setType('lu') solver.setOperators(A) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) xp = np.array([0.33, 0.33, 0.0]) tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim) cells = geometry.compute_first_entity_collision(tree, mesh, xp) up = uh.eval(xp, cells[0]) print("test0:", up) print("test1:", xp[0]**degree) u_exact = np.zeros(mesh.geometry.dim) u_exact[0] = xp[0]**degree assert np.allclose(up, u_exact)
def run_vector_test(mesh, V, degree): """Projection into H(div/curl) spaces""" u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx # Source term x = SpatialCoordinate(mesh) u_exact = x[0]**degree L = inner(u_exact, v[0]) * dx with common.Timer("Assemble vector"): b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) with common.Timer("Assemble matrix"): A = assemble_matrix(a) A.assemble() with common.Timer("Solve"): # Create LU linear solver (Note: need to use a solver that # re-orders to handle pivots, e.g. not the PETSc built-in LU solver) solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType("preonly") solver.getPC().setType('lu') solver.setOperators(A) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) with common.Timer("Error functional compile"): # Calculate error M = (u_exact - uh[0])**2 * dx for i in range(1, mesh.topology.dim): M += uh[i]**2 * dx M = fem.Form(M) with common.Timer("Error assembly"): error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) common.list_timings(MPI.COMM_WORLD, [common.TimingType.wall]) assert np.absolute(error) < 1.0e-14
def create_box_mesh(nxs, lxs, pxs, bcs): assert (len(nxs) == len(lxs)) assert (len(nxs) == len(pxs)) assert (len(nxs) == len(bcs)) pxs = np.array(pxs, dtype=np.float32) lxs = np.array(lxs, dtype=np.float32) nxs = np.array(nxs, dtype=np.int32) mesh = SingleBlockMesh(nxs, bcs) xs = SpatialCoordinate(mesh) newcoords = Function(mesh.coordinates.function_space(), name='newcoords') xlist = [] for i in range(len(pxs)): xlist.append(xs[i] * Constant(lxs[i]) + Constant(pxs[i]) - Constant(lxs[i]) / 2.) newcoords.interpolate(as_vector(xlist)) mesh.coordinates.assign(newcoords) return mesh
def run_vector_test(mesh, V, degree): """Projection into H(div/curl) spaces""" u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = form(inner(u, v) * dx) # Source term x = SpatialCoordinate(mesh) u_exact = x[0]**degree L = form(inner(u_exact, v[0]) * dx) b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a) A.assemble() # Create LU linear solver (Note: need to use a solver that # re-orders to handle pivots, e.g. not the PETSc built-in LU solver) solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType("preonly") solver.getPC().setType('lu') solver.setOperators(A) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.x.scatter_forward() # Calculate error M = (u_exact - uh[0])**2 * dx for i in range(1, mesh.topology.dim): M += uh[i]**2 * dx M = form(M) error = mesh.comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
def initialize(self, obj): A, P = obj.getOperators() prefix = obj.getOptionsPrefix() V = get_function_space(obj.getDM()) mesh = V.mesh() family = str(V.ufl_element().family()) degree = V.ufl_element().degree() if family != 'Raviart-Thomas' or degree != 1: raise ValueError( "Hypre ADS requires lowest order RT elements! (not %s of degree %d)" % (family, degree)) P1 = FunctionSpace(mesh, "Lagrange", 1) NC1 = FunctionSpace(mesh, "N1curl", 1) # DiscreteGradient G = Interpolator(grad(TestFunction(P1)), NC1).callable().handle # DiscreteCurl C = Interpolator(curl(TestFunction(NC1)), V).callable().handle pc = PETSc.PC().create(comm=obj.comm) pc.incrementTabLevel(1, parent=obj) pc.setOptionsPrefix(prefix + "hypre_ads_") pc.setOperators(A, P) pc.setType('hypre') pc.setHYPREType('ads') pc.setHYPREDiscreteGradient(G) pc.setHYPREDiscreteCurl(C) V = VectorFunctionSpace(mesh, "Lagrange", 1) linear_coordinates = interpolate(SpatialCoordinate(mesh), V).dat.data_ro.copy() pc.setCoordinates(linear_coordinates) pc.setUp() self.pc = pc
def demo_periodic3D(celltype: CellType): # Create mesh and finite element if celltype == CellType.tetrahedron: # Tet setup N = 10 mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N) V = fem.VectorFunctionSpace(mesh, ("CG", 1)) else: # Hex setup N = 10 mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N, CellType.hexahedron) V = fem.VectorFunctionSpace(mesh, ("CG", 2)) def dirichletboundary(x: NDArray[np.float64]) -> NDArray[np.bool_]: return np.logical_or( np.logical_or(np.isclose(x[1], 0), np.isclose(x[1], 1)), np.logical_or(np.isclose(x[2], 0), np.isclose(x[2], 1))) # Create Dirichlet boundary condition zero = PETSc.ScalarType([0, 0, 0]) geometrical_dofs = fem.locate_dofs_geometrical(V, dirichletboundary) bc = fem.dirichletbc(zero, geometrical_dofs, V) bcs = [bc] 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)) def periodic_relation(x): out_x = np.zeros(x.shape) out_x[0] = 1 - x[0] out_x[1] = x[1] out_x[2] = x[2] return out_x with Timer("~~Periodic: Compute mpc condition"): mpc = dolfinx_mpc.MultiPointConstraint(V) mpc.create_periodic_constraint_topological(V.sub(0), mt, 2, periodic_relation, bcs, 1) mpc.finalize() # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx x = SpatialCoordinate(mesh) dx_ = x[0] - 0.9 dy_ = x[1] - 0.5 dz_ = x[2] - 0.1 f = as_vector((x[0] * sin(5.0 * pi * x[1]) + 1.0 * exp(-(dx_ * dx_ + dy_ * dy_ + dz_ * dz_) / 0.02), 0.1 * dx_ * dz_, 0.1 * dx_ * dy_)) rhs = inner(f, v) * dx petsc_options: Dict[str, Union[str, float, int]] if complex_mode: rtol = 1e-16 petsc_options = {"ksp_type": "preonly", "pc_type": "lu"} else: rtol = 1e-8 petsc_options = { "ksp_type": "cg", "ksp_rtol": rtol, "pc_type": "hypre", "pc_hypre_typ": "boomeramg", "pc_hypre_boomeramg_max_iter": 1, "pc_hypre_boomeramg_cycle_type": "v", "pc_hypre_boomeramg_print_statistics": 1 } problem = LinearProblem(a, rhs, mpc, bcs, petsc_options=petsc_options) u_h = problem.solve() # --------------------VERIFICATION------------------------- print("----Verification----") u_ = fem.Function(V) u_.x.array[:] = 0 org_problem = fem.petsc.LinearProblem(a, rhs, u=u_, bcs=bcs, petsc_options=petsc_options) with Timer("~Periodic: Unconstrained solve"): org_problem.solve() it = org_problem.solver.getIterationNumber() print(f"Unconstrained solver iterations: {it}") # Write solutions to file ext = "tet" if celltype == CellType.tetrahedron else "hex" u_.name = "u_" + ext + "_unconstrained" # NOTE: Workaround as tabulate dof coordinates does not like extra ghosts u_out = fem.Function(V) old_local = u_out.x.map.size_local * u_out.x.bs old_ghosts = u_out.x.map.num_ghosts * u_out.x.bs mpc_local = u_h.x.map.size_local * u_h.x.bs assert (old_local == mpc_local) u_out.x.array[:old_local + old_ghosts] = u_h.x.array[:mpc_local + old_ghosts] u_out.name = "u_" + ext fname = f"results/demo_periodic3d_{ext}.bp" out_periodic = VTXWriter(MPI.COMM_WORLD, fname, u_out) out_periodic.write(0) out_periodic.close() root = 0 with Timer("~Demo: Verification"): dolfinx_mpc.utils.compare_mpc_lhs(org_problem.A, problem.A, mpc, root=root) dolfinx_mpc.utils.compare_mpc_rhs(org_problem.b, problem.b, mpc, root=root) # Gather LHS, RHS and solution on one process A_csr = dolfinx_mpc.utils.gather_PETScMatrix(org_problem.A, root=root) K = dolfinx_mpc.utils.gather_transformation_matrix(mpc, root=root) L_np = dolfinx_mpc.utils.gather_PETScVector(org_problem.b, root=root) u_mpc = dolfinx_mpc.utils.gather_PETScVector(u_h.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, rtol=rtol)
def compute(space, epsilon, weakBnd, skeleton, mol=None): u = TrialFunction(space) v = TestFunction(space) n = FacetNormal(space) he = avg(CellVolume(space)) / FacetArea(space) hbnd = CellVolume(space) / FacetArea(space) x = SpatialCoordinate(space) exact = uflFunction(space.gridView, name="exact", order=3, ufl=sin(x[0] * x[1])) uh = space.interpolate(exact, name="solution") # diffusion factor eps = Constant(epsilon, "eps") # transport direction and upwind flux b = as_vector([1, 0]) hatb = (dot(b, n) + abs(dot(b, n))) / 2.0 # characteristic function for left/right boundary dD = conditional((1 + x[0]) * (1 - x[0]) < 1e-10, 1, 0) # penalty parameter beta = Constant(20 * space.order**2, "beta") rhs = -(div(eps * grad(exact) - b * exact)) * v * dx aInternal = dot(eps * grad(u) - b * u, grad(v)) * dx aInternal -= eps * dot(grad(exact), n) * v * (1 - dD) * ds diffSkeleton = eps*beta/he*jump(u)*jump(v)*dS -\ eps*dot(avg(grad(u)),n('+'))*jump(v)*dS -\ eps*jump(u)*dot(avg(grad(v)),n('+'))*dS if weakBnd: diffSkeleton += eps*beta/hbnd*(u-exact)*v*dD*ds -\ eps*dot(grad(exact),n)*v*dD*ds advSkeleton = jump(hatb * u) * jump(v) * dS if weakBnd: advSkeleton += (hatb * u + (dot(b, n) - hatb) * exact) * v * dD * ds if skeleton: form = aInternal + diffSkeleton + advSkeleton else: form = aInternal if weakBnd and skeleton: strongBC = None else: strongBC = DirichletBC(space, exact, dD) if space.storage[0] == "numpy": solver = { "solver": ("suitesparse", "umfpack"), "parameters": { "newton.verbose": True, "newton.linear.verbose": False, "newton.linear.tolerance": 1e-5, } } else: solver = { "solver": "bicgstab", "parameters": { "newton.linear.preconditioning.method": "ilu", "newton.linear.tolerance": 1e-13, "newton.verbose": True, "newton.linear.verbose": False } } if mol == 'mol': scheme = molSolutionScheme([form == rhs, strongBC], **solver) else: scheme = solutionScheme([form == rhs, strongBC], **solver) eoc = [] info = scheme.solve(target=uh) error = dot(uh - exact, uh - exact) error0 = math.sqrt(integrate(gridView, error, order=5)) print(error0, " # output", flush=True) for i in range(3): gridView.hierarchicalGrid.globalRefine(1) uh.interpolate(exact) scheme.solve(target=uh) error = dot(uh - exact, uh - exact) error1 = math.sqrt(integrate(gridView, error, order=5)) eoc += [math.log(error1 / error0) / math.log(0.5)] print(i, error0, error1, eoc, " # output", flush=True) error0 = error1 # print(space.order,epsilon,eoc) if (eoc[-1] - (space.order + 1)) < -0.1: print("ERROR:", space.order, epsilon, eoc) return eoc
from __future__ import print_function, division from ufl import as_vector, dot, grad, cos, pi, SpatialCoordinate, triangle from dune.grid import structuredGrid, gridFunction from dune.fem.space import lagrange, combined, product x = SpatialCoordinate(triangle) exact = as_vector([cos(2. * pi * x[0]) * cos(2. * pi * x[1]), dot(x, x)]) grid = structuredGrid([0, 0], [1, 1], [16, 16]) spc1 = lagrange(grid, dimRange=1, order=1) spc2 = lagrange(grid, dimRange=1, order=2) test1 = spc1.interpolate(exact[0], name="test") test2 = spc2.interpolate(exact[1], name="test") spc = combined(spc1, spc2) solution = spc.interpolate(exact, name="solution") space = product(spc1, spc2, components=["p", "s"]) df = space.interpolate(exact, name="df") # print(df.dofVector.size,solution.dofVector.size, # df.components[0].dofVector.size,df.p.dofVector.size,test1.dofVector.size) assert df.components[0].dofVector.size == test1.dofVector.size assert df.s.dofVector.size == test2.dofVector.size assert df.dofVector.size == solution.dofVector.size df.interpolate(solution) solution.interpolate(df) test1.interpolate(df.p) df.s.interpolate(test2) df.components[0].interpolate(solution[0]) df.p.interpolate(solution[0])
def demo_elasticity(): mesh = create_unit_square(MPI.COMM_WORLD, 10, 10) V = fem.VectorFunctionSpace(mesh, ("Lagrange", 1)) # Generate Dirichlet BC on lower boundary (Fixed) def boundaries(x): return np.isclose(x[0], np.finfo(float).eps) facets = locate_entities_boundary(mesh, 1, boundaries) topological_dofs = fem.locate_dofs_topological(V, 1, facets) bc = fem.dirichletbc(np.array([0, 0], dtype=PETSc.ScalarType), topological_dofs, V) bcs = [bc] # Define variational problem u = TrialFunction(V) v = TestFunction(V) # Elasticity parameters E = PETSc.ScalarType(1.0e4) nu = 0.0 mu = fem.Constant(mesh, E / (2.0 * (1.0 + nu))) lmbda = fem.Constant(mesh, 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(len(v))) x = SpatialCoordinate(mesh) # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(sigma(u), grad(v)) * dx rhs = inner(as_vector((0, (x[0] - 0.5) * 10**4 * x[1])), v) * dx # Create MPC def l2b(li): return np.array(li, dtype=np.float64).tobytes() s_m_c = {l2b([1, 0]): {l2b([1, 1]): 0.9}} mpc = MultiPointConstraint(V) mpc.create_general_constraint(s_m_c, 1, 1) mpc.finalize() # Solve Linear problem petsc_options = {"ksp_type": "preonly", "pc_type": "lu"} problem = LinearProblem(a, rhs, mpc, bcs=bcs, petsc_options=petsc_options) u_h = problem.solve() u_h.name = "u_mpc" with XDMFFile(MPI.COMM_WORLD, "results/demo_elasticity.xdmf", "w") as outfile: outfile.write_mesh(mesh) outfile.write_function(u_h) # Solve the MPC problem using a global transformation matrix # and numpy solvers to get reference values bilinear_form = fem.form(a) A_org = fem.petsc.assemble_matrix(bilinear_form, bcs) A_org.assemble() linear_form = fem.form(rhs) 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) solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType(PETSc.KSP.Type.PREONLY) solver.getPC().setType(PETSc.PC.Type.LU) solver.setOperators(A_org) u_ = fem.Function(V) solver.solve(L_org, u_.vector) u_.x.scatter_forward() u_.name = "u_unconstrained" with XDMFFile(MPI.COMM_WORLD, "results/demo_elasticity.xdmf", "a") as outfile: outfile.write_function(u_) outfile.close() root = 0 with Timer("~Demo: Verification"): 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(u_h.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) # Print out master-slave connectivity for the first slave master_owner = None master_data = None slave_owner = None if mpc.num_local_slaves > 0: slave_owner = MPI.COMM_WORLD.rank bs = mpc.function_space.dofmap.index_map_bs slave = mpc.slaves[0] print("Constrained: {0:.5e}\n Unconstrained: {1:.5e}".format( u_h.x.array[slave], u_.vector.array[slave])) master_owner = mpc._cpp_object.owners.links(slave)[0] _masters = mpc.masters master = _masters.links(slave)[0] glob_master = mpc.function_space.dofmap.index_map.local_to_global( [master // bs])[0] coeffs, offs = mpc.coefficients() master_data = [ glob_master * bs + master % bs, coeffs[offs[slave]:offs[slave + 1]][0] ] # If master not on proc send info to this processor if MPI.COMM_WORLD.rank != master_owner: MPI.COMM_WORLD.send(master_data, dest=master_owner, tag=1) else: print("Master*Coeff: {0:.5e}".format( coeffs[offs[slave]:offs[slave + 1]][0] * u_h.x.array[_masters.links(slave)[0]])) # As a processor with a master is not aware that it has a master, # Determine this so that it can receive the global dof and coefficient master_recv = MPI.COMM_WORLD.allgather(master_owner) for master in master_recv: if master is not None: master_owner = master break if slave_owner != master_owner and MPI.COMM_WORLD.rank == master_owner: dofmap = mpc.function_space.dofmap bs = dofmap.index_map_bs in_data = MPI.COMM_WORLD.recv(source=MPI.ANY_SOURCE, tag=1) num_local = dofmap.index_map.size_local + dofmap.index_map.num_ghosts l2g = dofmap.index_map.local_to_global( np.arange(num_local, dtype=np.int32)) l_index = np.flatnonzero(l2g == in_data[0] // bs)[0] print("Master*Coeff (on other proc): {0:.5e}".format( u_h.x.array[l_index * bs + in_data[0] % bs] * in_data[1]))
def _compileUFL(integrands, form, *args, tempVars=True): if isinstance(form, Equation): form = form.lhs - form.rhs if not isinstance(form, Form): raise ValueError("ufl.Form or ufl.Equation expected.") # added for dirichlet treatment same as conservationlaw model dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)] uflExpr = [form] + [bc.ufl_value for bc in dirichletBCs] if len(form.arguments()) < 2: raise ValueError( "Integrands model requires form with at least two arguments.") x = SpatialCoordinate(form.ufl_cell()) n = FacetNormal(form.ufl_cell()) cellVolume = CellVolume(form.ufl_cell()) maxCellEdgeLength = MaxCellEdgeLength(form.ufl_cell()) minCellEdgeLength = MinCellEdgeLength(form.ufl_cell()) facetArea = FacetArea(form.ufl_cell()) maxFacetEdgeLength = MaxFacetEdgeLength(form.ufl_cell()) minFacetEdgeLength = MinFacetEdgeLength(form.ufl_cell()) phi, u = form.arguments() ubar = Coefficient(u.ufl_function_space()) derivatives = gatherDerivatives(form, [phi, u]) derivatives_phi = derivatives[0] derivatives_u = derivatives[1] derivatives_ubar = map_expr_dags(Replacer({u: ubar}), derivatives_u) try: integrands.field = u.ufl_function_space().field except AttributeError: pass integrals = splitForm(form, [phi]) dform = apply_derivatives(derivative(action(form, ubar), ubar, u)) linearizedIntegrals = splitForm(dform, [phi, u]) if not set( integrals.keys()) <= {'cell', 'exterior_facet', 'interior_facet'}: raise Exception('unknown integral encountered in ' + str(set(integrals.keys())) + '.') if 'cell' in integrals.keys(): arg = Variable(integrands.domainValueTuple, 'u') predefined = { derivatives_u[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) integrands.predefineCoefficients(predefined, False) integrands.interior = generateUnaryCode(predefined, derivatives_phi, integrals['cell'], tempVars=tempVars) predefined = { derivatives_ubar[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) integrands.predefineCoefficients(predefined, False) integrands.linearizedInterior = generateUnaryLinearizedCode( predefined, derivatives_phi, derivatives_u, linearizedIntegrals.get('cell'), tempVars=tempVars) if 'exterior_facet' in integrals.keys(): arg = Variable(integrands.domainValueTuple, 'u') predefined = { derivatives_u[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[n] = integrands.facetNormal('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, False) integrands.boundary = generateUnaryCode(predefined, derivatives_phi, integrals['exterior_facet'], tempVars=tempVars) predefined = { derivatives_ubar[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[n] = integrands.facetNormal('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, False) integrands.linearizedBoundary = generateUnaryLinearizedCode( predefined, derivatives_phi, derivatives_u, linearizedIntegrals.get('exterior_facet'), tempVars=tempVars) if 'interior_facet' in integrals.keys(): argIn = Variable(integrands.domainValueTuple, 'uIn') argOut = Variable(integrands.domainValueTuple, 'uOut') predefined = { derivatives_u[i](s): arg[i] for i in range(len(derivatives_u)) for s, arg in (('+', argIn), ('-', argOut)) } predefined[x] = integrands.spatialCoordinate('xIn') predefined[n('+')] = integrands.facetNormal('xIn') predefined[cellVolume('+')] = integrands.cellVolume('Side::in') predefined[cellVolume('-')] = integrands.cellVolume('Side::out') predefined[maxCellEdgeLength('+')] = maxEdgeLength( integrands.cellGeometry('Side::in')) predefined[maxCellEdgeLength('-')] = maxEdgeLength( integrands.cellGeometry('Side::out')) predefined[minCellEdgeLength('+')] = minEdgeLength( integrands.cellGeometry('Side::in')) predefined[minCellEdgeLength('-')] = minEdgeLength( integrands.cellGeometry('Side::out')) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, True) integrands.skeleton = generateBinaryCode(predefined, derivatives_phi, integrals['interior_facet'], tempVars=tempVars) predefined = { derivatives_ubar[i](s): arg[i] for i in range(len(derivatives_u)) for s, arg in (('+', argIn), ('-', argOut)) } predefined[x] = integrands.spatialCoordinate('xIn') predefined[n('+')] = integrands.facetNormal('xIn') predefined[cellVolume('+')] = integrands.cellVolume('Side::in') predefined[cellVolume('-')] = integrands.cellVolume('Side::out') predefined[maxCellEdgeLength('+')] = maxEdgeLength( integrands.cellGeometry('Side::in')) predefined[maxCellEdgeLength('-')] = maxEdgeLength( integrands.cellGeometry('Side::out')) predefined[minCellEdgeLength('+')] = minEdgeLength( integrands.cellGeometry('Side::in')) predefined[minCellEdgeLength('-')] = minEdgeLength( integrands.cellGeometry('Side::out')) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, True) integrands.linearizedSkeleton = generateBinaryLinearizedCode( predefined, derivatives_phi, derivatives_u, linearizedIntegrals.get('interior_facet'), tempVars=tempVars) if dirichletBCs: integrands.hasDirichletBoundary = True predefined = {} # predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + integrands.arg_x.name + ' ) )') predefined[x] = UnformattedExpression( 'auto', 'intersection.geometry().center( )') integrands.predefineCoefficients(predefined, False) maxId = 0 codeDomains = [] bySubDomain = dict() neuman = [] wholeDomain = None for bc in dirichletBCs: if bc.subDomain in bySubDomain: raise Exception( 'Multiply defined Dirichlet boundary for subdomain ' + str(bc.subDomain)) if not isinstance(bc.functionSpace, (FunctionSpace, FiniteElementBase)): raise Exception( 'Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement' ) if isinstance(bc.functionSpace, FunctionSpace) and ( bc.functionSpace != u.ufl_function_space()): raise Exception( 'Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet' ) if isinstance(bc.functionSpace, FiniteElementBase) and ( bc.functionSpace != u.ufl_element()): raise Exception( 'Cannot handle boundary conditions on subspaces, yet') if isinstance(bc.value, list): neuman = [i for i, x in enumerate(bc.value) if x == None] else: neuman = [] value = ExprTensor(u.ufl_shape) for key in value.keys(): value[key] = Indexed( bc.ufl_value, MultiIndex(tuple(FixedIndex(k) for k in key))) if bc.subDomain is None: wholeDomain = value, neuman elif isinstance(bc.subDomain, int): bySubDomain[bc.subDomain] = value, neuman maxId = max(maxId, bc.subDomain) else: domain = ExprTensor(()) for key in domain.keys(): domain[key] = Indexed( bc.subDomain, MultiIndex(tuple(FixedIndex(k) for k in key))) codeDomains.append((value, neuman, domain)) defaultCode = [] if len(codeDomains) > 0: defaultCode.append(Declaration(Variable('int', 'domainId'))) # defaultCode.append(Declaration(Variable('auto', 'x'), # initializer=UnformattedExpression('auto','intersection.geometry().center()'))) for i, v in enumerate(codeDomains): block = Block() block.append( generateDirichletDomainCode(predefined, v[2], tempVars=tempVars)) block.append('if (domainId)') ifBlock = UnformattedBlock() ifBlock.append( 'std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId + i + 2) + ' );') if len(v[1]) > 0: [ ifBlock.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1] ] ifBlock.append('return true;') block.append(ifBlock) defaultCode.append(block) if wholeDomain is not None: block = UnformattedBlock() block.append( 'std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId + 1) + ' );') if len(wholeDomain[1]) > 0: [ block.append('dirichletComponent[' + str(c) + '] = 0;') for c in wholeDomain[1] ] block.append('return true;') defaultCode.append(block) defaultCode.append(return_(False)) bndId = Variable('const int', 'bndId') getBndId = UnformattedExpression( 'int', 'BoundaryIdProviderType::boundaryId( ' + integrands.arg_i.name + ' )') # getBndId = UnformattedExpression('int', 'boundaryIdGetter_.boundaryId( ' + integrands.arg_i.name + ' )') switch = SwitchStatement(bndId, default=defaultCode) for i, v in bySubDomain.items(): code = [] if len(v[1]) > 0: [ code.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1] ] code.append(return_(True)) switch.append(i, code) integrands.isDirichletIntersection = [ Declaration(bndId, initializer=getBndId), UnformattedBlock( 'std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + bndId.name + ' );'), switch ] predefined[x] = UnformattedExpression( 'auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + integrands.arg_x.name + ' ) )') if wholeDomain is None: defaultCode = assign(integrands.arg_r, construct("RRangeType", 0)) else: defaultCode = generateDirichletCode(predefined, wholeDomain[0], tempVars=tempVars) switch = SwitchStatement(integrands.arg_bndId, default=defaultCode) for i, v in bySubDomain.items(): switch.append( i, generateDirichletCode(predefined, v[0], tempVars=tempVars)) for i, v in enumerate(codeDomains): switch.append( i + maxId + 2, generateDirichletCode(predefined, v[0], tempVars=tempVars)) integrands.dirichlet = [switch] return integrands
def test_manufactured_poisson(degree, filename, datadir): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ with XDMFFile(MPI.comm_world, os.path.join(datadir, filename)) as xdmf: mesh = xdmf.read_mesh(GhostMode.none) V = FunctionSpace(mesh, ("Lagrange", degree)) u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u), grad(v)) * dx # Get quadrature degree for bilinear form integrand (ignores effect # of non-affine map) a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1}) a.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a) # Source term x = SpatialCoordinate(mesh) u_exact = x[1]**degree f = -div(grad(u_exact)) # Set quadrature degree for linear form integrand (ignores effect of # non-affine map) L = inner(f, v) * dx(metadata={"quadrature_degree": -1}) L.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L) t0 = time.time() L = fem.Form(L) t1 = time.time() print("Linear form compile time:", t1 - t0) u_bc = Function(V) u_bc.interpolate(lambda x: x[1]**degree) # Create Dirichlet boundary condition mesh.create_connectivity_all() facetdim = mesh.topology.dim - 1 bndry_facets = np.where( np.array(mesh.topology.on_boundary(facetdim)) == 1)[0] bdofs = locate_dofs_topological(V, facetdim, bndry_facets) assert (len(bdofs) < V.dim()) bc = DirichletBC(u_bc, bdofs) t0 = time.time() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) t1 = time.time() print("Vector assembly time:", t1 - t0) t0 = time.time() a = fem.Form(a) t1 = time.time() print("Bilinear form compile time:", t1 - t0) t0 = time.time() A = assemble_matrix(a, [bc]) A.assemble() t1 = time.time() print("Matrix assembly time:", t1 - t0) # Create LU linear solver solver = PETSc.KSP().create(MPI.comm_world) solver.setType(PETSc.KSP.Type.PREONLY) solver.getPC().setType(PETSc.PC.Type.LU) solver.setOperators(A) # Solve t0 = time.time() uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) t1 = time.time() print("Linear solver time:", t1 - t0) M = (u_exact - uh)**2 * dx t0 = time.time() M = fem.Form(M) t1 = time.time() print("Error functional compile time:", t1 - t0) t0 = time.time() error = assemble_scalar(M) error = MPI.sum(mesh.mpi_comm(), error) t1 = time.time() print("Error assembly time:", t1 - t0) assert np.absolute(error) < 1.0e-14
def test_manufactured_poisson_dg(degree, filename, datadir): """ Manufactured Poisson problem, solving u = x[component]**n, where n 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, ("DG", degree)) 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) error = mesh.mpi_comm().allreduce(assemble_scalar((u_exact - uh)**2 * dx), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
plt.savefig("stretchesVisco.png") plt.close() # stabilization parameters h = FacetArea(mesh) h_avg = avg(h) # new variable name to take derivatives FF = Identity(3) + grad(u) CC = FF.T * FF Fv = variable(FF) S = diff(freeEnergy(Fv.T * Fv, CCv), Fv) # first PK stress dl_interp(CC, C) dl_interp(CC, Cn) my_identity = grad(SpatialCoordinate(mesh)) dl_interp(my_identity, CCv) dl_interp(my_identity, Cvn) dl_interp(my_identity, C_quart) dl_interp(my_identity, C_thr_quart) dl_interp(my_identity, C_half) a_uv = (derivative(freeEnergy(CC, CCv), u, v) * dx + qvals / h_avg * dot(jump(u), jump(v)) * dS) jac = derivative(a_uv, u, du) # assign DirichletBC left_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, left) right_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, right) bottom_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, bottom)
[30, 30, 60]) from dune.alugrid import aluSimplexGrid as leafGridView3d gridView3d = leafGridView3d(domain3d) # <markdowncell> # As before we solve a simple Laplace problem # <codecell> from dune.fem.space import lagrange as solutionSpace from dune.fem.scheme import galerkin as solutionScheme from ufl import TrialFunction, TestFunction, SpatialCoordinate, dot, grad, dx, conditional, sqrt space3d = solutionSpace(gridView3d, order=1) u = TrialFunction(space3d) v = TestFunction(space3d) x = SpatialCoordinate(space3d) scheme3d = solutionScheme((dot(grad(u), grad(v)) + u * v) * dx == conditional(dot(x, x) < .01, 100, 0) * v * dx, solver='cg') uh3d = space3d.interpolate([0], name="solution") info = scheme3d.solve(target=uh3d) # <markdowncell> # Instead of plotting this using paraview we want to only study the # solution along a single line. This requires findings points # $x_i = x_0+\frac{i}{N}(x1-x0)$ for $i=0,\dots,N$ within the unstructured # grid. This would be expensive to compute on the Python so we implement # this algorithm in C++ using the `LineSegmentSampler` class available in # `Dune-Fem`. The resulting `algorithm` returns a pair of two lists with # coordinates $x_i$ and the values of the grid function at these points: #
order = 2 grid = create.grid("ALUCube", constructor=cartesianDomain([0, 0], [3, 1], [30, 10])) spcU = create.space("lagrange", grid, dimRange=grid.dimension, order=order, storage="fem") spcP = create.space("lagrange", grid, dimRange=1, order=order - 1, storage="fem") cell = spcU.cell() x = SpatialCoordinate(cell) mu = Constant(0, "mu") nu = Constant(0, "nu") u = TrialFunction(spcU) v = TestFunction(spcU) p = TrialFunction(spcP) q = TestFunction(spcP) exact_u = as_vector([x[1] * (1. - x[1]), 0]) exact_p = as_vector([(-2 * x[0] + 2) * mu]) f = as_vector([ 0, ] * grid.dimension) f += nu * exact_u mainModel = (nu * dot(u, v) + mu * inner(grad(u) + grad(u).T, grad(v)) - dot(f, v)) * dx gradModel = -inner(p[0] * Identity(grid.dimension), grad(v)) * dx
from matplotlib import pyplot # <markdowncell> # ## Setting up the Mesh # <codecell> from dune.grid import structuredGrid as leafGridView gridView = leafGridView([0, 0], [1, 1], [4, 4]) # <markdowncell> # ## Grid Functions # We can integrate grid function # <codecell> from ufl import SpatialCoordinate, triangle x = SpatialCoordinate(triangle) exact = 1/2*(x[0]**2+x[1]**2) - 1/3*(x[0]**3 - x[1]**3) + 1 from dune.fem.function import integrate mass = integrate(gridView, exact, order=5) print(mass) # <markdowncell> # and plot them using matplotlib or write a vtk file for postprocessing # <codecell> from dune.fem.plotting import plotPointData as plot plot(exact, grid=gridView) gridView.writeVTK('exact', pointdata={'exact': exact})
def bench_elasticity_edge(tetra: bool = True, r_lvl: int = 0, out_hdf5=None, xdmf: bool = False, boomeramg: bool = False, kspview: bool = False, degree: int = 1, info: bool = False): N = 3 for i in range(r_lvl): N *= 2 ct = CellType.tetrahedron if tetra else CellType.hexahedron mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N, ct) # Get number of unknowns on each edge V = VectorFunctionSpace(mesh, ("Lagrange", int(degree))) # Generate Dirichlet BC (Fixed) u_bc = Function(V) with u_bc.vector.localForm() as u_local: u_local.set(0.0) def boundaries(x): return np.isclose(x[0], np.finfo(float).eps) fdim = mesh.topology.dim - 1 facets = locate_entities_boundary(mesh, fdim, boundaries) topological_dofs = locate_dofs_topological(V, fdim, facets) bc = dirichletbc(u_bc, topological_dofs) bcs = [bc] def PeriodicBoundary(x): return np.logical_and(np.isclose(x[0], 1), np.isclose(x[2], 0)) def periodic_relation(x): out_x = np.zeros(x.shape) out_x[0] = x[0] out_x[1] = x[1] out_x[2] = x[2] + 1 return out_x with Timer("~Elasticity: Initialize MPC"): edim = mesh.topology.dim - 2 edges = locate_entities_boundary(mesh, edim, PeriodicBoundary) arg_sort = np.argsort(edges) periodic_mt = meshtags(mesh, edim, edges[arg_sort], np.full(len(edges), 2, dtype=np.int32)) mpc = MultiPointConstraint(V) mpc.create_periodic_constraint_topological(V, periodic_mt, 2, periodic_relation, bcs, scale=0.5) mpc.finalize() # Create traction meshtag def traction_boundary(x): return np.isclose(x[0], 1) t_facets = locate_entities_boundary(mesh, fdim, traction_boundary) facet_values = np.ones(len(t_facets), dtype=np.int32) arg_sort = np.argsort(t_facets) mt = meshtags(mesh, fdim, t_facets[arg_sort], facet_values) # Elasticity parameters E = PETSc.ScalarType(1.0e4) nu = 0.1 mu = Constant(mesh, E / (2.0 * (1.0 + nu))) lmbda = Constant(mesh, E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))) g = Constant(mesh, PETSc.ScalarType((0, 0, -1e2))) x = SpatialCoordinate(mesh) f = Constant(mesh, PETSc.ScalarType(1e3)) * as_vector((0, -(x[2] - 0.5)**2, (x[1] - 0.5)**2)) # Stress computation def epsilon(v): return sym(grad(v)) def sigma(v): return (2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(len(v))) # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(sigma(u), grad(v)) * dx rhs = inner(g, v) * ds(domain=mesh, subdomain_data=mt, subdomain_id=1) + inner(f, v) * dx # Setup MPC system if info: log_info(f"Run {r_lvl}: Assembling matrix and vector") bilinear_form = form(a) linear_form = form(rhs) with Timer("~Elasticity: Assemble LHS and RHS"): A = assemble_matrix(bilinear_form, mpc, bcs=bcs) b = assemble_vector(linear_form, mpc) # Create nullspace for elasticity problem and assign to matrix null_space = rigid_motions_nullspace(mpc.function_space) A.setNearNullSpace(null_space) # Apply boundary conditions apply_lifting(b, [bilinear_form], [bcs], mpc) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b, bcs) opts = PETSc.Options() if boomeramg: opts["ksp_type"] = "cg" opts["ksp_rtol"] = 1.0e-5 opts["pc_type"] = "hypre" opts['pc_hypre_type'] = 'boomeramg' opts["pc_hypre_boomeramg_max_iter"] = 1 opts["pc_hypre_boomeramg_cycle_type"] = "v" # opts["pc_hypre_boomeramg_print_statistics"] = 1 else: opts["ksp_rtol"] = 1.0e-8 opts["pc_type"] = "gamg" opts["pc_gamg_type"] = "agg" opts["pc_gamg_coarse_eq_limit"] = 1000 opts["pc_gamg_sym_graph"] = True opts["mg_levels_ksp_type"] = "chebyshev" opts["mg_levels_pc_type"] = "jacobi" opts["mg_levels_esteig_ksp_type"] = "cg" opts["matptap_via"] = "scalable" opts["pc_gamg_square_graph"] = 2 opts["pc_gamg_threshold"] = 0.02 # opts["help"] = None # List all available options # opts["ksp_view"] = None # List progress of solver # Setup PETSc solver solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setFromOptions() if info: log_info(f"Run {r_lvl}: Solving") with Timer("~Elasticity: Solve problem") as timer: solver.setOperators(A) uh = b.copy() uh.set(0) solver.solve(b, uh) uh.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) mpc.backsubstitution(uh) solver_time = timer.elapsed() if kspview: solver.view() mem = sum(MPI.COMM_WORLD.allgather(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)) it = solver.getIterationNumber() num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs if out_hdf5 is not None: d_set = out_hdf5.get("its") d_set[r_lvl] = it d_set = out_hdf5.get("num_dofs") d_set[r_lvl] = num_dofs d_set = out_hdf5.get("num_slaves") d_set[r_lvl, MPI.COMM_WORLD.rank] = mpc.num_local_slaves d_set = out_hdf5.get("solve_time") d_set[r_lvl, MPI.COMM_WORLD.rank] = solver_time[0] if info: log_info(f"Lvl: {r_lvl}, Its: {it}, max Mem: {mem}, dim(V): {num_dofs}") if xdmf: # Write solution to file u_h = Function(mpc.function_space) u_h.vector.setArray(uh.array) u_h.name = "u_mpc" fname = f"results/bench_elasticity_edge_{r_lvl}.xdmf" with XDMFFile(MPI.COMM_WORLD, fname, "w") as outfile: outfile.write_mesh(mesh) outfile.write_function(u_h)
def test_div_grad_then_integrate_over_cells_and_boundary(): # Define 2D geometry n = 10 mesh = RectangleMesh( [numpy.array([0.0, 0.0, 0.0]), numpy.array([2.0, 3.0, 0.0])], 2 * n, 3 * n) x, y = SpatialCoordinate(mesh) xs = 0.1 + 0.8 * x / 2 # scaled to be within [0.1,0.9] # ys = 0.1 + 0.8 * y / 3 # scaled to be within [0.1,0.9] n = FacetNormal(mesh) # Define list of expressions to test, and configure accuracies # these expressions are known to pass with. The reason some # functions are less accurately integrated is likely that the # default choice of quadrature rule is not perfect F_list = [] def reg(exprs, acc=10): for expr in exprs: F_list.append((expr, acc)) # FIXME: 0*dx and 1*dx fails in the ufl-ffcx-jit framework somewhere # reg([Constant(0.0, cell=cell)]) # reg([Constant(1.0, cell=cell)]) monomial_list = [x**q for q in range(2, 6)] reg(monomial_list) reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list]) reg([xs**xs]) reg( [xs**(xs**2)], 8 ) # Note: Accuracies here are from 1D case, not checked against 2D results. reg([xs**(xs**3)], 6) reg([xs**(xs**4)], 2) # Special functions: reg([atan(xs)], 8) reg([sin(x), cos(x), exp(x)], 5) reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3) reg([asin(xs), acos(xs)], 1) reg([tan(xs)], 7) # To handle tensor algebra, make an x dependent input tensor # xx and square all expressions def reg2(exprs, acc=10): for expr in exprs: F_list.append((inner(expr, expr), acc)) xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]]) xxs = as_matrix([[2 * xs**2, 3 * xs**3], [11 * xs**5, 7 * xs**4]]) x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4]) cc = as_matrix([[2, 3], [4, 5]]) reg2( [xx] ) # TODO: Make unit test for UFL from this, results in listtensor with free indices reg2([x3v]) reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))]) reg2([xx.T]) reg2([tr(xx)]) reg2([det(xx)]) reg2([dot(xx, 0.1 * xx)]) reg2([outer(xx, xx.T)]) reg2([dev(xx)]) reg2([sym(xx)]) reg2([skew(xx)]) reg2([elem_mult(7 * xx, cc)]) reg2([elem_div(7 * xx, xx + cc)]) reg2([elem_pow(1e-3 * xxs, 1e-3 * cc)]) reg2([elem_pow(1e-3 * cc, 1e-3 * xx)]) reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2) # pretty inaccurate... # FIXME: Add tests for all UFL operators: # These cause discontinuities and may be harder to test in the # above fashion: # 'inv', 'cofac', # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not', # 'conditional', 'sign', # 'jump', 'avg', # 'LiftingFunction', 'LiftingOperator', # FIXME: Test other derivatives: (but algorithms for operator # derivatives are the same!): # 'variable', 'diff', # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative', # Run through all operators defined above and compare integrals debug = 0 if debug: F_list = F_list[1:] for F, acc in F_list: if debug: print('\n', "F:", str(F)) # Integrate over domain and its boundary int_dx = assemble(div(grad(F)) * dx(mesh)) # noqa int_ds = assemble(dot(grad(F), n) * ds(mesh)) # noqa if debug: print(int_dx, int_ds) # Compare results. Using custom relative delta instead of # decimal digits here because some numbers are >> 1. delta = min(abs(int_dx), abs(int_ds)) * 10**-acc assert int_dx - int_ds <= delta
def test_diff_then_integrate(): # Define 1D geometry n = 21 mesh = UnitIntervalMesh(MPI.COMM_WORLD, n) # Shift and scale mesh x0, x1 = 1.5, 3.14 mesh.coordinates()[:] *= (x1 - x0) mesh.coordinates()[:] += x0 x = SpatialCoordinate(mesh)[0] xs = 0.1 + 0.8 * x / x1 # scaled to be within [0.1,0.9] # Define list of expressions to test, and configure # accuracies these expressions are known to pass with. # The reason some functions are less accurately integrated is # likely that the default choice of quadrature rule is not perfect F_list = [] def reg(exprs, acc=10): for expr in exprs: F_list.append((expr, acc)) # FIXME: 0*dx and 1*dx fails in the ufl-ffcx-jit framework somewhere # reg([Constant(0.0, cell=cell)]) # reg([Constant(1.0, cell=cell)]) monomial_list = [x**q for q in range(2, 6)] reg(monomial_list) reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list]) reg([x**x]) reg([x**(x**2)], 8) reg([x**(x**3)], 6) reg([x**(x**4)], 2) # Special functions: reg([atan(xs)], 8) reg([sin(x), cos(x), exp(x)], 5) reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3) reg([asin(xs), acos(xs)], 1) reg([tan(xs)], 7) try: import scipy except ImportError: scipy = None if hasattr(math, 'erf') or scipy is not None: reg([erf(xs)]) else: print( "Warning: skipping test of erf, old python version and no scipy.") # if 0: # print("Warning: skipping tests of bessel functions, doesn't build on all platforms.") # elif scipy is None: # print("Warning: skipping tests of bessel functions, missing scipy.") # else: # for nu in (0, 1, 2): # # Many of these are possibly more accurately integrated, # # but 4 covers all and is sufficient for this test # reg([bessel_J(nu, xs), bessel_Y(nu, xs), bessel_I(nu, xs), bessel_K(nu, xs)], 4) # To handle tensor algebra, make an x dependent input tensor # xx and square all expressions def reg2(exprs, acc=10): for expr in exprs: F_list.append((inner(expr, expr), acc)) xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]]) x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4]) cc = as_matrix([[2, 3], [4, 5]]) reg2([xx]) reg2([x3v]) reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))]) reg2([xx.T]) reg2([tr(xx)]) reg2([det(xx)]) reg2([dot(xx, 0.1 * xx)]) reg2([outer(xx, xx.T)]) reg2([dev(xx)]) reg2([sym(xx)]) reg2([skew(xx)]) reg2([elem_mult(7 * xx, cc)]) reg2([elem_div(7 * xx, xx + cc)]) reg2([elem_pow(1e-3 * xx, 1e-3 * cc)]) reg2([elem_pow(1e-3 * cc, 1e-3 * xx)]) reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2) # pretty inaccurate... # FIXME: Add tests for all UFL operators: # These cause discontinuities and may be harder to test in the # above fashion: # 'inv', 'cofac', # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not', # 'conditional', 'sign', # 'jump', 'avg', # 'LiftingFunction', 'LiftingOperator', # FIXME: Test other derivatives: (but algorithms for operator # derivatives are the same!): # 'variable', 'diff', # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative', # Run through all operators defined above and compare integrals debug = 0 for F, acc in F_list: # Apply UFL differentiation f = diff(F, SpatialCoordinate(mesh))[..., 0] if debug: print(F) print(x) print(f) # Apply integration with DOLFINx # (also passes through form compilation and jit) M = f * dx f_integral = assemble_scalar(M) # noqa f_integral = mesh.mpi_comm().allreduce(f_integral, op=MPI.SUM) # Compute integral of f manually from anti-derivative F # (passes through pybind11 interface and uses UFL evaluation) F_diff = F((x1, )) - F((x0, )) # Compare results. Using custom relative delta instead # of decimal digits here because some numbers are >> 1. delta = min(abs(f_integral), abs(F_diff)) * 10**-acc assert f_integral - F_diff <= delta
def reference_periodic(tetra: bool, r_lvl: int = 0, out_hdf5: h5py.File = None, xdmf: bool = False, boomeramg: bool = False, kspview: bool = False, degree: int = 1): # Create mesh and finite element if tetra: # Tet setup N = 3 mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N) for i in range(r_lvl): mesh.topology.create_entities(mesh.topology.dim - 2) mesh = refine(mesh, redistribute=True) N *= 2 else: # Hex setup N = 3 for i in range(r_lvl): N *= 2 mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N, CellType.hexahedron) V = FunctionSpace(mesh, ("CG", degree)) # Create Dirichlet boundary condition def dirichletboundary(x): return np.logical_or( np.logical_or(np.isclose(x[1], 0), np.isclose(x[1], 1)), np.logical_or(np.isclose(x[2], 0), np.isclose(x[2], 1))) mesh.topology.create_connectivity(2, 1) geometrical_dofs = locate_dofs_geometrical(V, dirichletboundary) bc = dirichletbc(PETSc.ScalarType(0), geometrical_dofs, V) bcs = [bc] # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx x = SpatialCoordinate(mesh) dx_ = x[0] - 0.9 dy_ = x[1] - 0.5 dz_ = x[2] - 0.1 f = x[0] * sin(5.0 * pi * x[1]) + 1.0 * exp( -(dx_ * dx_ + dy_ * dy_ + dz_ * dz_) / 0.02) rhs = inner(f, v) * dx # Assemble rhs, RHS and apply lifting bilinear_form = form(a) linear_form = form(rhs) A_org = assemble_matrix(bilinear_form, bcs) A_org.assemble() L_org = assemble_vector(linear_form) apply_lifting(L_org, [bilinear_form], [bcs]) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(L_org, bcs) # Create PETSc nullspace nullspace = PETSc.NullSpace().create(constant=True) PETSc.Mat.setNearNullSpace(A_org, nullspace) # Set PETSc options opts = PETSc.Options() if boomeramg: opts["ksp_type"] = "cg" opts["ksp_rtol"] = 1.0e-5 opts["pc_type"] = "hypre" opts['pc_hypre_type'] = 'boomeramg' opts["pc_hypre_boomeramg_max_iter"] = 1 opts["pc_hypre_boomeramg_cycle_type"] = "v" # opts["pc_hypre_boomeramg_print_statistics"] = 1 else: opts["ksp_type"] = "cg" opts["ksp_rtol"] = 1.0e-12 opts["pc_type"] = "gamg" opts["pc_gamg_type"] = "agg" opts["pc_gamg_sym_graph"] = True # Use Chebyshev smoothing for multigrid opts["mg_levels_ksp_type"] = "richardson" opts["mg_levels_pc_type"] = "sor" # opts["help"] = None # List all available options # opts["ksp_view"] = None # List progress of solver # Initialize PETSc solver, set options and operator solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setFromOptions() solver.setOperators(A_org) # Solve linear problem u_ = Function(V) start = perf_counter() with Timer("Solve"): solver.solve(L_org, u_.vector) end = perf_counter() u_.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) if kspview: solver.view() it = solver.getIterationNumber() num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs if out_hdf5 is not None: d_set = out_hdf5.get("its") d_set[r_lvl] = it d_set = out_hdf5.get("num_dofs") d_set[r_lvl] = num_dofs d_set = out_hdf5.get("solve_time") d_set[r_lvl, MPI.COMM_WORLD.rank] = end - start if MPI.COMM_WORLD.rank == 0: print("Rlvl {0:d}, Iterations {1:d}".format(r_lvl, it)) # Output solution to XDMF if xdmf: ext = "tet" if tetra else "hex" fname = "results/reference_periodic_{0:d}_{1:s}.xdmf".format( r_lvl, ext) u_.name = "u_" + ext + "_unconstrained" with XDMFFile(MPI.COMM_WORLD, fname, "w") as out_periodic: out_periodic.write_mesh(mesh) out_periodic.write_function( u_, 0.0, "Xdmf/Domain/" + "Grid[@Name='{0:s}'][1]".format(mesh.name))
from ufl import SpatialCoordinate, dot from dune.grid import cartesianDomain from dune.alugrid import aluConformGrid as leafGridView from dune.fem.view import filteredGridView from dune.fem.space import lagrange gridView = leafGridView( cartesianDomain([0,0],[1,1],[16,16]) ) filteredView = filteredGridView(gridView, lambda e: e.geometry.center.two_norm > 0.5, domainId=1) space = lagrange(filteredView, order=2) x = SpatialCoordinate(space) solution = space.interpolate(dot(x,x),name="solution") solution.plot() print("number of dofs:", solution.size,\ "integral over filtered domain",solution.integrate()) filteredView = filteredGridView(gridView, lambda e: e.geometry.center.two_norm < 0.5, domainId=1, useFilteredIndexSet=True) space = lagrange(filteredView, order=2) x = SpatialCoordinate(space) solution = space.interpolate(dot(x,x),name="solution") solution.plot() print("number of dofs:", solution.size,\ "integral over filtered domain",solution.integrate()) space = lagrange(gridView, order=2) solution = space.interpolate(dot(x,x),name="solution") solution.plot() print("number of dofs:", solution.size,\ "integral over filtered domain",solution.integrate())
def run_scalar_test(mesh, V, degree): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ 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) with common.Timer("Linear form compile"): L = fem.Form(L) with common.Timer("Function interpolation"): 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) bc = DirichletBC(u_bc, bdofs) with common.Timer("Vector assembly"): b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) with common.Timer("Bilinear form compile"): a = fem.Form(a) with common.Timer("Matrix assembly"): A = assemble_matrix(a, [bc]) 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) with common.Timer("Solve"): uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) with common.Timer("Error functional compile"): M = (u_exact - uh)**2 * dx M = fem.Form(M) with common.Timer("Error assembly"): error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) common.list_timings(MPI.COMM_WORLD, [common.TimingType.wall]) assert np.absolute(error) < 1.0e-14
try: grid = create.grid("ALUConform", dune.grid.cartesianDomain([0, 0], [1, 1], [9, 9]), dimgrid=2) except: grid = create.grid("Yasp", dune.grid.cartesianDomain([0, 0], [1, 1], [9, 9]), dimgrid=2) d = 0.001 p = 1.7 uflSpace = Space((2, 2), 1) u = TrialFunction(uflSpace) v = TestFunction(uflSpace) x = SpatialCoordinate(uflSpace.cell()) rhs = (x[0] + x[1]) * v[0] a = (pow(d + inner(grad(u), grad(u)), (p - 2) / 2) * inner(grad(u), grad(v)) + grad(u[0])[0] * v[0]) * dx + 10 * inner(u, v) * ds b = rhs * dx + 10 * rhs * ds model = create.model("integrands", grid, a == b) def test(space): if test_numpy: numpySpace = create.space(space, grid, dimRange=1, order=1, storage='numpy')
def compileUFL(form, patch, *args, **kwargs): if isinstance(form, Equation): form = form.lhs - form.rhs if not isinstance(form, Form): raise Exception("ufl.Form expected.") if len(form.arguments()) < 2: raise Exception("ConservationLaw model requires form with at least two arguments.") phi_, u_ = form.arguments() if phi_.ufl_function_space().scalar: phi = TestFunction(phi_.ufl_function_space().toVectorSpace()) form = replace(form,{phi_:phi[0]}) else: phi = phi_ if u_.ufl_function_space().scalar: u = TrialFunction(u_.ufl_function_space().toVectorSpace()) form = replace(form,{u_:u[0]}) else: u = u_ _, coeff_ = extract_arguments_and_coefficients(form) coeff_ = set(coeff_) # added for dirichlet treatment same as conservationlaw model dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)] # remove the dirichletBCs arg = [arg for arg in args if not isinstance(arg, DirichletBC)] for dBC in dirichletBCs: _, coeff__ = extract_arguments_and_coefficients(dBC.ufl_value) coeff_ |= set(coeff__) if patch is not None: for a in patch: try: _, coeff__ = extract_arguments_and_coefficients(a) coeff_ |= set(coeff__) except: pass # a might be a float/int and not a ufl expression coeff = {c : c.toVectorCoefficient()[0] for c in coeff_ if len(c.ufl_shape) == 0 and not c.is_cellwise_constant()} form = replace(form,coeff) for bc in dirichletBCs: bc.ufl_value = replace(bc.ufl_value, coeff) if patch is not None: patch = [a if not isinstance(a, Expr) else replace(a,coeff) for a in patch] phi = form.arguments()[0] dimRange = phi.ufl_shape[0] u = form.arguments()[1] du = Grad(u) d2u = Grad(du) ubar = Coefficient(u.ufl_function_space()) dubar = Grad(ubar) d2ubar = Grad(dubar) dimDomain = u.ufl_shape[0] x = SpatialCoordinate(form.ufl_cell()) try: field = u.ufl_function_space().field except AttributeError: field = "double" # if exact solution is passed in subtract a(u,.) from the form if "exact" in kwargs: b = replace(form, {u: as_vector(kwargs["exact"])} ) form = form - b dform = apply_derivatives(derivative(action(form, ubar), ubar, u)) source, flux, boundarySource = splitUFLForm(form) linSource, linFlux, linBoundarySource = splitUFLForm(dform) fluxDivergence, _, _ = splitUFLForm(inner(source.as_ufl() - div(flux.as_ufl()), phi) * dx(0)) # split linNVSource off linSource # linSources = splitUFL2(u, du, d2u, linSource) # linNVSource = linSources[2] # linSource = linSources[0] + linSources[1] if patch is not None: model = ConservationLawModel(dimDomain, dimRange, u, modelSignature(form,*patch,*args)) else: model = ConservationLawModel(dimDomain, dimRange, u, modelSignature(form,None,*args)) model._replaceCoeff = coeff model.hasNeumanBoundary = not boundarySource.is_zero() #expandform = expand_indices(expand_derivatives(expand_compounds(equation.lhs))) #if expandform == adjoint(expandform): # model.symmetric = 'true' model.field = field dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)] # deprecated # if "dirichlet" in kwargs: # dirichletBCs += [DirichletBC(u.ufl_function_space(), as_vector(value), bndId) for bndId, value in kwargs["dirichlet"].items()] uflCoefficients = set(form.coefficients()) for bc in dirichletBCs: _, c = extract_arguments_and_coefficients(bc.ufl_value) uflCoefficients |= set(c) if patch is not None: for a in patch: if isinstance(a, Expr): _, c = extract_arguments_and_coefficients(a) uflCoefficients |= set(c) constants = dict() coefficients = dict() for coefficient in uflCoefficients: try: name = getattr(coefficient, "name") except AttributeError: name = str(coefficient) if coefficient.is_cellwise_constant(): try: parameter = getattr(coefficient, "parameter") except AttributeError: parameter = None if len(coefficient.ufl_shape) == 0: constants[coefficient] = model.addConstant('double', name=name, parameter=parameter) elif len(coefficient.ufl_shape) == 1: constants[coefficient] = model.addConstant('Dune::FieldVector< double, ' + str(coefficient.ufl_shape[0]) + ' >', name=name, parameter=parameter) else: Exception('Currently, only scalars and vectors are supported as constants') else: shape = coefficient.ufl_shape[0] try: coefficients[coefficient] = model.addCoefficient( shape, coefficient.cppTypeName, name=name, field=coefficient.ufl_function_space().field) except AttributeError: coefficients[coefficient] = model.addCoefficient( shape, coefficient.cppTypeName, name=name) model.coefficients = coefficients model.constants = constants tempVars = kwargs.get("tempVars", True) predefined = {u: model.arg_u, du: model.arg_du, d2u: model.arg_d2u} predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )') model.predefineCoefficients(predefined,'x') model.source = generateCode(predefined, source, tempVars=tempVars) model.flux = generateCode(predefined, flux, tempVars=tempVars) predefined.update({ubar: model.arg_ubar, dubar: model.arg_dubar, d2ubar: model.arg_d2ubar}) model.linSource = generateCode(predefined, linSource, tempVars=tempVars) model.linFlux = generateCode(predefined, linFlux, tempVars=tempVars) # model.linNVSource = generateCode({u: arg, du: darg, d2u: d2arg, ubar: argbar, dubar: dargbar, d2ubar: d2argbar}, linNVSource, model.coefficients, tempVars) predefined = {u: model.arg_u} predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )') model.predefineCoefficients(predefined,'x') model.alpha = generateCode(predefined, boundarySource, tempVars=tempVars) predefined.update({ubar: model.arg_ubar}) model.linAlpha = generateCode(predefined, linBoundarySource, tempVars=tempVars) predefined = {u: model.arg_u, du: model.arg_du, d2u: model.arg_d2u} predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )') model.predefineCoefficients(predefined,'x') model.fluxDivergence = generateCode(predefined, fluxDivergence, tempVars=tempVars) if dirichletBCs: model.hasDirichletBoundary = True predefined = {} predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )') model.predefineCoefficients(predefined,'x') maxId = 0 codeDomains = [] bySubDomain = dict() neuman = [] for bc in dirichletBCs: if bc.subDomain in bySubDomain: raise Exception('Multiply defined Dirichlet boundary for subdomain ' + str(bc.subDomain)) if not isinstance(bc.functionSpace, (FunctionSpace, FiniteElementBase)): raise Exception('Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement') if isinstance(bc.functionSpace, FunctionSpace) and (bc.functionSpace != u.ufl_function_space()): raise Exception('Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet') if isinstance(bc.functionSpace, FiniteElementBase) and (bc.functionSpace != u.ufl_element()): raise Exception('Cannot handle boundary conditions on subspaces, yet') if isinstance(bc.value, list): neuman = [i for i, x in enumerate(bc.value) if x == None] else: neuman = [] value = ExprTensor(u.ufl_shape) for key in value.keys(): value[key] = Indexed(bc.ufl_value, MultiIndex(tuple(FixedIndex(k) for k in key))) if isinstance(bc.subDomain,int): bySubDomain[bc.subDomain] = value,neuman maxId = max(maxId, bc.subDomain) else: domain = ExprTensor(()) for key in domain.keys(): domain[key] = Indexed(bc.subDomain, MultiIndex(tuple(FixedIndex(k) for k in key))) codeDomains.append( (value,neuman,domain) ) defaultCode = [] defaultCode.append(Declaration(Variable('int', 'domainId'))) defaultCode.append(Declaration(Variable('auto', 'tmp0'), initializer=UnformattedExpression('auto','intersection.geometry().center()'))) for i,v in enumerate(codeDomains): block = Block() defaultCode.append( generateDirichletDomainCode(predefined, v[2], tempVars=tempVars)) defaultCode.append('if (domainId)') block = UnformattedBlock() block.append('std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId+i+1) + ' );') if len(v[1])>0: [block.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1]] block.append('return true;') defaultCode.append(block) defaultCode.append(return_(False)) bndId = Variable('const int', 'bndId') getBndId = UnformattedExpression('int', 'BoundaryIdProviderType::boundaryId( ' + model.arg_i.name + ' )') switch = SwitchStatement(bndId, default=defaultCode) for i,v in bySubDomain.items(): code = [] if len(v[1])>0: [code.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1]] code.append(return_(True)) switch.append(i, code) model.isDirichletIntersection = [Declaration(bndId, initializer=getBndId), UnformattedBlock('std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + bndId.name + ' );'), switch ] switch = SwitchStatement(model.arg_bndId, default=assign(model.arg_r, construct("RRangeType", 0))) for i, v in bySubDomain.items(): switch.append(i, generateDirichletCode(predefined, v[0], tempVars=tempVars)) for i,v in enumerate(codeDomains): switch.append(i+maxId+1, generateDirichletCode(predefined, v[0], tempVars=tempVars)) model.dirichlet = [switch] return model
la.orthonormalize(ns) assert la.is_orthonormal(ns) return PETSc.NullSpace().create(vectors=ns) mesh = create_box(MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]), np.array([2.0, 1.0, 1.0])], [12, 12, 12], CellType.tetrahedron, GhostMode.shared_facet) # Rotation rate and mass density omega = 300.0 rho = 10.0 # Loading due to centripetal acceleration (rho*omega^2*x_i) x = SpatialCoordinate(mesh) f = as_vector((rho * omega**2 * x[0], rho * omega**2 * x[1], 0.0)) # Elasticity parameters E = 1.0e9 nu = 0.0 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym(grad(v))) * Identity( len(v)) # Create function space
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}) with common.Timer("Compile forms"): 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) with common.Timer("Assemble vector"): b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) with common.Timer("Assemble matrix"): A = assemble_matrix(a, []) A.assemble() with common.Timer("Solve"): # 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) with common.Timer("Error functional compile"): # Calculate error M = (u_exact - uh)**2 * dx M = fem.Form(M) with common.Timer("Error assembly"): error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) common.list_timings(MPI.COMM_WORLD, [common.TimingType.wall]) assert np.absolute(error) < 1.0e-14