def get_error(wh, subdomains=subdomains, exact=exact): u1h, uh = wh sigma_exact, u_exact, p_exact, I_exact = exact V = uh.function_space() mesh = V.mesh() # # Recover the transmembrane potential by postprocessing # V = uh.function_space() mesh = V.mesh() interface_mesh = BoundaryMesh(mesh, 'exterior') V = FunctionSpace(interface_mesh, 'CG', 1) Tu1 = PETScMatrix(trace_mat_no_restrict(u1h.function_space(), V)) * u1h.vector() Tu = PETScMatrix(trace_mat_no_restrict(uh.function_space(), V)) * uh.vector() vh = Function(V, Tu1 - Tu) # On finer #V = FunctionSpace(interface_mesh, 'CG', 3) # Hs = matrix_fromHs(HsNorm(V, s=0.5)) ## Use interpolate #vh = interpolate(vh, V) return ( sqrt(H1_norm(u_exact[0], u1h)**2 + H1_norm(u_exact[1], uh)**2), sqrt(L2_norm(u_exact[0], u1h)**2 + L2_norm(u_exact[1], uh)**2), #Aerror(Hs, V, p_exact, vh)) L2_norm(p_exact, vh))
def get_diff(u_ext, u_int): V = u_int.function_space() mesh = V.mesh() interface_mesh = BoundaryMesh(mesh, 'exterior') V = FunctionSpace(interface_mesh, 'CG', 1) Tu_ext = PETScMatrix(trace_mat_no_restrict(u_ext.function_space(), V))*u_ext.vector() Tu_int = PETScMatrix(trace_mat_no_restrict(u_int.function_space(), V))*u_int.vector() vh = Function(V, Tu_ext - Tu_int) return vh
def test_trace(n, f, true=None): '''Surface integral (for benchmark problem)''' omega = UnitCubeMesh(n, n, n) # 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) # What we want to extend f3 = interpolate(f, V3) T = PETScMatrix(trace_mat_no_restrict(V3, V2)) x = T * f3.vector() f2 = Function(V2, x) if true is None: true = f error = sqrt(abs(assemble(inner(true - f2, true - f2) * dx))) return gamma.hmin(), error, f2
def test_DLT(): '''Injection of DLT dofs''' for n in (4, 8, 16, 32, 64): mesh = UnitSquareMesh(n, n) V = FunctionSpace(mesh, 'Discontinuous Lagrange Trace', 0) v = TestFunction(V) f = Expression('x[0]+2*x[1]', degree=1) fV = Function(V) assemble((1 / FacetArea(mesh)) * inner(f, v) * ds, tensor=fV.vector()) facet_f = MeshFunction('size_t', mesh, 1, 0) DomainBoundary().mark(facet_f, 1) trace_mesh = EmbeddedMesh(facet_f, 1) TV = FunctionSpace(trace_mesh, 'DG', 0) T = PETScMatrix(trace_mat_no_restrict(V, TV, trace_mesh)) gTV = Function(TV) gTV.vector()[:] = T * fV.vector() assert sqrt(abs(assemble(inner(gTV - f, gTV - f) * ds))) < 1E-13
def test_vec_trace(): mesh = UnitSquareMesh(10, 10) bdry = MeshFunction('size_t', mesh, 1, 0) DomainBoundary().mark(bdry, 1) bmesh = EmbeddedMesh(bdry, 1) V = FunctionSpace(mesh, 'CG', 2) TV = FunctionSpace(bmesh, 'CG', 2) Trace = PETScMatrix(trace_mat_no_restrict(V, TV, bmesh)) f = Expression('sin(pi*(x[0]+x[1]))', degree=3) v = interpolate(f, V) Tv0 = interpolate(f, TV) Tv = Function(TV) Trace.mult(v.vector(), Tv.vector()) Tv0.vector().axpy(-1, Tv.vector()) assert Tv0.vector().norm('linf') < 1E-13
def check(ncells, Qelm): mesh = UnitSquareMesh(*(ncells, ) * 2) bmesh = BoundaryMesh(mesh, 'exterior') V = FunctionSpace(mesh, 'CG', 1) Q = FunctionSpace(bmesh, Qelm(bmesh.ufl_cell())) u = TrialFunction(V) q = TestFunction(Q) n = FacetNormal(mesh) # Want grad(u).n * q v = TestFunction(V) a = inner(dot(grad(u), n), v) * ds A = assemble(a) # Now take it from testV to test Q T = PETScMatrix(trace_mat_no_restrict(V, Q, bmesh)) B = ii_convert(T * A) # Now we should be able to integrate linear function exactly x, y = SpatialCoordinate(mesh) f = 2 * x + y g = x - 3 * y truth = assemble(inner(dot(grad(f), n), g) * ds) fV = interpolate(Expression('x[1] + 2*x[0]', degree=1), V) gQ = interpolate(Expression('x[0] - 3*x[1]', degree=1), Q) me = gQ.vector().inner(B * fV.vector()) return abs(truth - me)
def get_error(wh, subdomains=subdomains, exact=exact, mms=mms_data, params=params): u1h, uh, ph = wh sigma_exact, u_exact, p_exact, I_exact = exact # Mutliplier error mesh = ph.function_space().mesh() Q = FunctionSpace(mesh, 'CG', 3) cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) # Spaces on pieces for tag, subd in enumerate(subdomains, 1): CompiledSubDomain(subd, tol=1E-10).mark(cell_f, tag) dx = Measure('dx', domain=mesh, subdomain_data=cell_f) p, q = TrialFunction(Q), TestFunction(Q) a = inner(p, q) * dx L = sum( inner(I_exact_i, q) * dx(i) for i, I_exact_i in enumerate(I_exact, 1)) I_exact = Function(Q) A, b = map(assemble, (a, L)) solve(A, I_exact.vector(), b) V = uh.function_space() mesh = V.mesh() # # Recover the transmembrane potential by postprocessing # V = uh.function_space() mesh = V.mesh() interface_mesh = BoundaryMesh(mesh, 'exterior') V = FunctionSpace(interface_mesh, 'CG', 1) Tu1 = PETScMatrix(trace_mat_no_restrict(u1h.function_space(), V)) * u1h.vector() Tu = PETScMatrix(trace_mat_no_restrict(uh.function_space(), V)) * uh.vector() vh = Function(V, Tu1 - Tu) # Now using flux we have Q = ph.function_space() mesh = Q.mesh() cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) # Spaces on pieces for tag, subd in enumerate(subdomains, 1): CompiledSubDomain(subd, tol=1E-10).mark(cell_f, tag) dx = Measure('dx', domain=mesh, subdomain_data=cell_f) p, q = TrialFunction(Q), TestFunction(Q) gGamma = mms.rhs[3] a = inner(p, q) * dx L = inner(params.eps * ph, q) * dx + sum( inner(gi, q) * dx(i) for i, gi in enumerate(gGamma, 1)) A, b = map(assemble, (a, L)) vh_P = Function(Q) # Since we project solve(A, vh_P.vector(), b) vh_I = subdomain_interpolate(zip(gGamma, subdomains), Q) vh_I.vector().axpy(params.eps, ph.vector()) # Simply by interpolation return (sqrt(H1_norm(u_exact[0], u1h)**2 + H1_norm(u_exact[1], uh)**2), L2_norm(p_exact, vh), L2_norm(p_exact, vh_P), L2_norm(p_exact, vh_I))
def solve_problem(ncells, eps, solver_params): '''Optim problem on [0, 1]^2''' # Made up f = Expression('x[0] + x[1]', degree=1) mesh = UnitSquareMesh(*(ncells, ) * 2) bmesh = BoundaryMesh(mesh, 'exterior') Q = FunctionSpace(mesh, 'DG', 0) V = FunctionSpace(mesh, 'CG', 1) B = FunctionSpace(mesh, 'CG', 1) W = [Q, V, B] p, u, lmbda = list(map(TrialFunction, W)) q, v, beta = list(map(TestFunction, W)) Tu = Trace(u, bmesh) Tv = Trace(v, bmesh) # The line integral dxGamma = Measure('dx', domain=bmesh) a = [[0] * len(W) for _ in range(len(W))] a[0][0] = Constant(eps) * inner(p, q) * dx a[0][2] = inner(q, lmbda) * dx # We put zero on the diagonal temporarily and then replace by # the fractional laplacian a[1][1] = 0 a[1][2] = inner(grad(v), grad(lmbda)) * dx + inner(v, lmbda) * dx a[2][0] = inner(p, beta) * dx a[2][1] = inner(grad(u), grad(beta)) * dx + inner(u, beta) * dx L = [ inner(Constant(0), q) * dx, inner(Constant(0), v) * dx, # Same replacement idea here inner(Constant(0), beta) * dx ] # All but (1, 1) and 1 are final AA, bb = list(map(ii_assemble, (a, L))) # Now I want and operator which corresponds to (Tv, (-Delta^{0.5} T_u))_bdry TV = FunctionSpace(bmesh, 'CG', 1) T = PETScMatrix(trace_mat_no_restrict(V, TV)) # The fractional laplacian nodal->dual fDelta = HsNorm(TV, s=0.5) # This should be it A11 = block_transpose(T) * fDelta * T # Now, while here we can also comute the rhs contribution # (Tv, (-Delta^{0.5}, f)) f_vec = interpolate(f, V).vector() b1 = A11 * f_vec bb[1] = b1 AA[1][1] = A11 wh = ii_Function(W) # Direct solve if not solver_params: AAm, bbm = list(map(ii_convert, (AA, bb))) LUSolver('umfpack').solve(AAm, wh.vector(), bbm) return wh, -1 # Magne like precond if False: # Preconditioner like in the L2 case but with L2 bdry replaced b00 = Constant(eps) * inner(p, q) * dx B00 = LumpedInvDiag(ii_assemble(b00)) H1 = ii_assemble(inner(grad(v), grad(u)) * dx + inner(v, u) * dx) # From dual to nodal R = LumpedInvDiag(ii_assemble(inner(u, v) * dx)) # The whole matrix to be inverted is then (second term is H2 approx) B11 = collapse(A11 + eps * H1 * R * H1) # And the inverse B11 = AMG(B11, parameters={'pc_hypre_boomeramg_cycle_type': 'W'}) b22 = Constant(1. / eps) * inner(lmbda, beta) * dx B22 = LumpedInvDiag(ii_assemble(b22)) # A bit like SZ else: b00 = Constant(eps) * inner(p, q) * dx B00 = LumpedInvDiag(ii_assemble(b00)) # L2 \cap eps H1 H1 = assemble( Constant(eps) * (inner(grad(v), grad(u)) * dx + inner(v, u) * dx)) B11 = AMG(collapse(A11 + H1)) # (1./eps)*L2 \cap 1./sqrt(eps)H1 a = Constant(1./eps)*inner(beta, lmbda)*dx + \ Constant(1./sqrt(eps))*(inner(grad(beta), grad(lmbda))*dx + inner(beta, lmbda)*dx) B22 = AMG(assemble(a)) BB = block_diag_mat([B00, B11, B22]) # Want the iterations to start from random (iterative) wh.block_vec().randomize() # Default is minres if '-ksp_type' not in solver_params: solver_params['-ksp_type'] = 'minres' opts = PETSc.Options() for key, value in solver_params.items(): opts.setValue(key, None if value == 'none' else value) ksp = PETSc.KSP().create() ksp.setOperators(ii_PETScOperator(AA)) ksp.setPC(ii_PETScPreconditioner(BB, ksp)) ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED) ksp.setFromOptions() ksp.solve(as_petsc_nest(bb), wh.petsc_vec()) niters = ksp.getIterationNumber() return wh, niters
def solve_problem(ncells, eps, solver_params): '''Optim problem on [0, 1]^2''' # Made up f = Expression('x[0] + x[1]', degree=1) mesh = UnitSquareMesh(*(ncells, )*2) bmesh = BoundaryMesh(mesh, 'exterior') Q = FunctionSpace(mesh, 'DG', 0) V = FunctionSpace(mesh, 'CG', 1) B = FunctionSpace(mesh, 'CG', 1) W = [Q, V, B] p, u, lmbda = map(TrialFunction, W) q, v, beta = map(TestFunction, W) Tu = Trace(u, bmesh) Tv = Trace(v, bmesh) # The line integral dxGamma = Measure('dx', domain=bmesh) a = [[0]*len(W) for _ in range(len(W))] a[0][0] = Constant(eps)*inner(p, q)*dx a[0][2] = inner(q, lmbda)*dx # We put zero on the diagonal temporarily and then replace by # the fractional laplacian a[1][1] = 0 a[1][2] = inner(grad(v), grad(lmbda))*dx + inner(v, lmbda)*dx a[2][0] = inner(p, beta)*dx a[2][1] = inner(grad(u), grad(beta))*dx + inner(u, beta)*dx L = [inner(Constant(0), q)*dx, inner(Constant(0), v)*dx, # Same replacement idea here inner(Constant(0), beta)*dx] # All but (1, 1) and 1 are final AA, bb = map(ii_assemble, (a, L)) # Now I want and operator which corresponds to (Tv, (-Delta^{0.5} T_u))_bdry TV = FunctionSpace(bmesh, 'CG', 1) T = PETScMatrix(trace_mat_no_restrict(V, TV)) # The fractional laplacian nodal->dual fDelta = HsNorm(TV, s=0.5) # This should be it A11 = block_transpose(T)*fDelta*T # Now, while here we can also comute the rhs contribution # (Tv, (-Delta^{0.5}, f)) f_vec = interpolate(f, V).vector() b1 = A11*f_vec bb[1] = b1 AA[1][1] = A11 wh = ii_Function(W) # Direct solve if not solver_params: AAm, bbm = map(ii_convert, (AA, bb)) LUSolver('umfpack').solve(AAm, wh.vector(), bbm) return wh, -1 # Magne like precond if False: # Preconditioner like in the L2 case but with L2 bdry replaced b00 = Constant(eps)*inner(p, q)*dx B00 = LumpedInvDiag(ii_assemble(b00)) H1 = ii_assemble(inner(grad(v), grad(u))*dx + inner(v, u)*dx) # From dual to nodal R = LumpedInvDiag(ii_assemble(inner(u, v)*dx)) # The whole matrix to be inverted is then (second term is H2 approx) B11 = collapse(A11 + eps*H1*R*H1) # And the inverse B11 = AMG(B11, parameters={'pc_hypre_boomeramg_cycle_type': 'W'}) b22 = Constant(1./eps)*inner(lmbda, beta)*dx B22 = LumpedInvDiag(ii_assemble(b22)) # A bit like SZ else: b00 = Constant(eps)*inner(p, q)*dx B00 = LumpedInvDiag(ii_assemble(b00)) # L2 \cap eps H1 H1 = assemble(Constant(eps)*(inner(grad(v), grad(u))*dx + inner(v, u)*dx)) B11 = AMG(collapse(A11 + H1)) # (1./eps)*L2 \cap 1./sqrt(eps)H1 a = Constant(1./eps)*inner(beta, lmbda)*dx + \ Constant(1./sqrt(eps))*(inner(grad(beta), grad(lmbda))*dx + inner(beta, lmbda)*dx) B22 = AMG(assemble(a)) BB = block_diag_mat([B00, B11, B22]) # Want the iterations to start from random (iterative) wh.block_vec().randomize() # Default is minres if '-ksp_type' not in solver_params: solver_params['-ksp_type'] = 'minres' opts = PETSc.Options() for key, value in solver_params.iteritems(): opts.setValue(key, None if value == 'none' else value) ksp = PETSc.KSP().create() ksp.setOperators(ii_PETScOperator(AA)) ksp.setPC(ii_PETScPreconditioner(BB, ksp)) ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED) ksp.setFromOptions() ksp.solve(as_petsc_nest(bb), wh.petsc_vec()) niters = ksp.getIterationNumber() return wh, niters