def test_surf_approx(n, f, true=None): '''Surface integral (for benchmark problem)''' omega = UnitCubeMesh(n, n, 2 * n) A = np.array([0.5, 0.5, 0.0]) B = np.array([0.5, 0.5, 1.0]) gamma = StraightLineMesh(A, B, 2 * n) V3 = FunctionSpace(omega, 'CG', 1) V1 = FunctionSpace(gamma, 'CG', 1) f3 = interpolate(f, V3) shape = SquareRim(P=lambda x: np.array([0.25, 0.25, x[2]]), degree=10) Pi = average_matrix(V3, V1, shape=shape) x = Pi * f3.vector() f1 = Function(V1, x) if true is None: true = f error = sqrt(abs(assemble(inner(true - f1, true - f1) * dx))) return gamma.hmin(), error, f1
def test_id(n, f, align=True): '''Surface integral (for benchmark problem)''' omega = UnitCubeMesh(n, n, 2 * n) A = np.array([0.5, 0.5, 0.0]) B = np.array([0.5, 0.5, 1.0]) lmbda = StraightLineMesh(A, B, 2 * n if align else n) # The curve # Coupling surface walls = [ 'near((x[0]-0.25)*(x[0]-0.75), 0) && ((0.25-tol) < x[1]) && ((0.75+tol) > x[1])', 'near((x[1]-0.25)*(x[1]-0.75), 0) && ((0.25-tol) < x[0]) && ((0.75+tol) > x[0])' ] walls = ['( %s )' % w for w in walls] chi = CompiledSubDomain(' || '.join(walls), tol=1E-10) surfaces = MeshFunction('size_t', omega, 2, 0) chi.mark(surfaces, 1) gamma = EmbeddedMesh(surfaces, 1) V3 = FunctionSpace(omega, 'CG', 1) V2 = FunctionSpace(gamma, 'CG', 1) V1 = FunctionSpace(lmbda, 'CG', 1) # What we want to extend f1 = interpolate(f, V1) # To 2d E = uniform_extension_matrix(V1, V2) x = E * f1.vector() f2 = Function(V2, x) # Extend to 3d by harmonic extension u, v = TrialFunction(V3), TestFunction(V3) a, L = inner(grad(u), grad(v)) * dx, inner(Constant(0), v) * dx bcs = [DirichletBC(V3, f, 'on_boundary'), DirichletBC(V3, f, surfaces, 1)] A, b = assemble_system(a, L, bcs) f3 = Function(V3) solver = KrylovSolver('cg', 'hypre_amg') solver.parameters['relative_tolerance'] = 1E-13 solver.solve(A, f3.vector(), b) # Come back shape = SquareRim(P=lambda x: np.array([0.25, 0.25, x[2]]), degree=10) Pi = average_matrix(V3, V1, shape=shape) x = Pi * f3.vector() f10 = Function(V1, x) error = sqrt(abs(assemble(inner(f10 - f, f10 - f) * dx))) return gamma.hmin(), error, f10
def worker_(f, n, radius=radius, degree=8): '''Check integrals due to averaging operator''' from weak_bcs.paper_daq.utils import circle_3d1d_conform mesh, entity_fs = circle_3d1d_conform(n=n, rad=radius) line_mesh = EmbeddedMesh(entity_fs[1], 1) V = FunctionSpace(mesh, 'CG', 1) TV = FunctionSpace(line_mesh, 'DG', 1) f = interpolate(f, V) cylinder = Circle(radius, degree) Pi = PETScMatrix(average_matrix(V, TV, cylinder)) # print('\t', Pi.norm('linf'), max(len(Pi.getrow(i)[0]) for i in range(TV.dim()))) Pi_f = Function(TV) Pi.mult(f.vector(), Pi_f.vector()) return Pi_f
def worker(f, n, radius=0.3, degree=8): '''Check integrals due to averaging operator''' mesh = BoxMesh(Point(-1, -1, -1), Point(1, 1, 1), n, n, n) mf = MeshFunction('size_t', mesh, 1, 0) CompiledSubDomain('near(x[0], 0.0) && near(x[1], 0.0)').mark(mf, 1) line_mesh = EmbeddedMesh(mf, 1) V = FunctionSpace(mesh, 'CG', 1) TV = FunctionSpace(line_mesh, 'DG', 1) f = interpolate(f, V) cylinder = Circle(radius, degree) Pi = PETScMatrix(average_matrix(V, TV, cylinder)) # print('\t', Pi.norm('linf'), max(len(Pi.getrow(i)[0]) for i in range(TV.dim()))) Pi_f = Function(TV) Pi.mult(f.vector(), Pi_f.vector()) return Pi_f
# We assemble now into block_mat objects (not necessarily matrices) A, b = map(ii_assemble, (a, L)) # After the assembler pass; the block of A that involve coupling are not # represented as matrices. Instead they are matrix expressions. For example # the a[1][0] block is a product of M * Pi where Pi is the matrix representation # of the averaging operator from V to PiV space and M is the mass matrix # between PiV and Q _, PiMat = A[1][0].chain # Check that Pi really goes from V assert PiMat.size(1) == V.dim() # The PiV space is inferred by the assembler. If you are not happy with # it you can always get the matrix representation your self from xii.assembler.average_matrix import average_matrix # Here we get it map to DG0 on the line MyPiMat = average_matrix(V, FunctionSpace(mesh1d, 'DG', 0), shape=shape) # Whily before DG1 was used print 'inferred', PiMat.size(0), 'manual', MyPiMat.size(0) # Suppose now that there are also boundary conditions; we specify them # as a list for every subspace V_bcs = [DirichletBC(V, Constant(0), 'near(x[2], 0)')] Q_bcs = [] W_bcs = [V_bcs, Q_bcs] # Apply A, b = apply_bc(A, b, W_bcs) # Just checking if the off-diagonal block sane print '|A01| and |A10|', A[0][1].norm('linf'), A[1][0].norm('linf') print '# Unknowns', sum(Wi.dim() for Wi in W)