class Space: def __init__(self, mesh, N=0): # Define mesh parameters self.mesh = mesh self.cell_size = CellDiameter(mesh) self.normal_vector = FacetNormal(mesh) # Define measures inner_boundary = Inner_boundary() sub_domains = MeshFunction("size_t", mesh, mesh.topology().dim() - 1) sub_domains.set_all(0) inner_boundary.mark(sub_domains, 1) self.dx = Measure("dx", domain=mesh) self.ds = Measure("ds", domain=mesh, subdomain_data=sub_domains) # Define function spaces finite_element = FiniteElement("Lagrange", mesh.ufl_cell(), 1) self.function_space = FunctionSpace(mesh, finite_element * finite_element) self.function_space_split = [ self.function_space.sub(0).collapse(), self.function_space.sub(1).collapse(), ]
def project_gradient( f0, mesh=None, degree=None, debug=False, solver_type='gmres', preconditioner_type='default' ): """Find an approximation to f0 that has the same gradient Parameters: f0: the function to approximate mesh=None: the mesh on which to approximate it. If not provided, the mesh is extracted from f0. degree=None: degree of the polynomial approximation. extracted from f0 if not provided. solver_type='gmres': The linear solver type to use. preconditioner_type='default': Preconditioner type to use """ if not mesh: mesh = f0.function_space().mesh() element = f0.ufl_element() if not degree: degree = element.degree() CE = FiniteElement('CG', mesh.ufl_cell(), degree) CS = FunctionSpace(mesh, CE) DE = FiniteElement('DG', mesh.ufl_cell(), degree) DS = FunctionSpace(mesh, DE) CVE = VectorElement('CG', mesh.ufl_cell(), degree - 1) CV = FunctionSpace(mesh, CVE) RE = FiniteElement('R', mesh.ufl_cell(), 0) R = FunctionSpace(mesh, RE) CRE = MixedElement([CE, RE]) CR = FunctionSpace(mesh, CRE) f = fe.project(f0, CS, solver_type=solver_type, preconditioner_type= preconditioner_type) g = fe.project(fe.grad(f), CV, solver_type=solver_type, preconditioner_type= preconditioner_type) tf, tc = TrialFunction(CR) wf, wc = TestFunctions(CR) dx = Measure('dx', domain=mesh, metadata={'quadrature_degree': min(degree, 10)}) a = (fe.dot(fe.grad(tf), fe.grad(wf)) + tc * wf + tf * wc) * fe.dx L = (f * wc + fe.dot(g, fe.grad(wf))) * fe.dx igc = Function(CR) fe.solve(a == L, igc, solver_parameters={'linear_solver': solver_type, 'preconditioner': preconditioner_type} ) if debug: print('igc', igc.vector()[:]) assigner = FunctionAssigner(CS, CR.sub(0)) # ig = Function(CS) # assigner.assign(ig, igc.sub(0)) # fe.assign(ig, igc.sub(0)) # if debug: # print('ig', igc.sub(0).vector()[:]) igd = fe.project(igc.sub(0), DS, solver_type=solver_type, preconditioner_type=preconditioner_type) if debug: print('igd', igd.vector()[:]) return igd