def test_curl_curl(compile_args): V = ufl.FiniteElement("N1curl", "triangle", 2) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = ufl.inner(ufl.curl(u), ufl.curl(v)) * ufl.dx forms = [a] compiled_forms, module = ffcx.codegeneration.jit.compile_forms(forms, cffi_extra_compile_args=compile_args)
def HodgeLaplaceGradCurl(element, felement): tau, v = TestFunctions(element) sigma, u = TrialFunctions(element) f = Coefficient(felement) a = (inner(tau, sigma) - inner(grad(tau), u) + inner(v, grad(sigma)) + inner(curl(v), curl(u))) * dx L = inner(v, f) * dx return a, L
def norm(v, norm_type="L2", mesh=None): """Compute the norm of ``v``. :arg v: a :class:`.Function` to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: * L2 .. math:: ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x * H1 .. math:: ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x * Hdiv .. math:: ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x * Hcurl .. math:: ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x """ assert isinstance(v, function.Function) typ = norm_type.lower() mesh = v.function_space().mesh() dx = mesh._dx if typ == 'l2': form = inner(v, v)*dx elif typ == 'h1': form = inner(v, v)*dx + inner(grad(v), grad(v))*dx elif typ == "hdiv": form = inner(v, v)*dx + div(v)*div(v)*dx elif typ == "hcurl": form = inner(v, v)*dx + inner(curl(v), curl(v))*dx else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return sqrt(solving.assemble(form))
def norm(v, norm_type="L2", mesh=None): """Compute the norm of ``v``. :arg v: a :class:`.Function` to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: * L2 .. math:: ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x * H1 .. math:: ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x * Hdiv .. math:: ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x * Hcurl .. math:: ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x """ assert isinstance(v, function.Function) typ = norm_type.lower() mesh = v.function_space().mesh() dx = mesh._dx if typ == 'l2': form = inner(v, v)*dx elif typ == 'h1': form = inner(v, v)*dx + inner(grad(v), grad(v))*dx elif typ == "hdiv": form = inner(v, v)*dx + div(v)*div(v)*dx elif typ == "hcurl": form = inner(v, v)*dx + inner(curl(v), curl(v))*dx else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return sqrt(assemble(form))
def norm(v, norm_type="L2", degree=None): """Compute the norm of ``v``. :arg v: a ufl expression (:class:`~.ufl.classes.Expr`) to compute the norm of :arg norm_type: the type of norm to compute, see below for options. Available norm types are: * L2 .. math:: ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x * H1 .. math:: ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x * Hdiv .. math:: ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x * Hcurl .. math:: ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x """ if not degree == None: dxn = dx(2 * degree + 1) else: dxn = dx typ = norm_type.lower() if typ == 'l2': form = inner(v, v) * dxn elif typ == 'h1': form = inner(v, v) * dxn + inner(grad(v), grad(v)) * dxn elif typ == "hdiv": form = inner(v, v) * dxn + div(v) * div(v) * dxn elif typ == "hcurl": form = inner(v, v) * dxn + inner(curl(v), curl(v)) * dxn else: raise RuntimeError("Unknown norm type '%s'" % norm_type) normform = ZeroForm(form) return sqrt(normform.assembleform())
def r2_norm(v, func_degree=None, norm_type="L2", mesh=None): """ This function is a modification of FEniCS's built-in norm function that adopts the :math:`r^2dr` measure as opposed to the standard Cartesian :math:`dx` measure. For documentation and usage, see the original module <https://bitbucket.org/fenics-project/dolfin/src/master/python/dolfin/fem/norms.py>_. .. note:: Note the extra argument func_degree: this is used to interpolate the :math:`r^2` Expression to the same degree as used in the definition of the Trial and Test function spaces. """ # Get mesh from function if isinstance(v, cpp.function.Function) and mesh is None: mesh = v.function_space().mesh() # Define integration measure and domain dx = ufl.dx(mesh) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, Function)): # DS: HERE IS WHERE I MODIFY r2 = Expression('pow(x[0],2)', degree=func_degree) if norm_type.lower() == "l2": M = v**2 * r2 * dx elif norm_type.lower() == "h1": M = (v**2 + grad(v)**2) * r2 * dx elif norm_type.lower() == "h10": M = grad(v)**2 * r2 * dx elif norm_type.lower() == "hdiv": M = (v**2 + div(v)**2) * r2 * dx elif norm_type.lower() == "hdiv0": M = div(v)**2 * r2 * dx elif norm_type.lower() == "hcurl": M = (v**2 + curl(v)**2) * r2 * dx elif norm_type.lower() == "hcurl0": M = curl(v)**2 * r2 * dx else: raise ValueError("Unknown norm type {}".format(str(norm_type))) else: raise TypeError("Do not know how to compute norm of {}".format(str(v))) # Assemble value and return return sqrt(assemble(M))
def norm(v, norm_type="L2", mesh=None): """Compute the norm of ``v``. :arg v: a ufl expression (:class:`~.ufl.classes.Expr`) to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: * L2 .. math:: ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x * H1 .. math:: ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x * Hdiv .. math:: ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x * Hcurl .. math:: ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x """ typ = norm_type.lower() if typ == 'l2': form = inner(v, v)*dx elif typ == 'h1': form = inner(v, v)*dx + inner(grad(v), grad(v))*dx elif typ == "hdiv": form = inner(v, v)*dx + div(v)*div(v)*dx elif typ == "hcurl": form = inner(v, v)*dx + inner(curl(v), curl(v))*dx else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return sqrt(assemble(form))
def test_curl(space_type, order): """Test that curl is consistent for different cell permutations of a tetrahedron.""" tdim = cpp.mesh.cell_dim(CellType.tetrahedron) points = unit_cell_points(CellType.tetrahedron) spaces = [] results = [] cell = list(range(len(points))) # Assemble vector on 5 randomly numbered cells for i in range(5): shuffle(cell) domain = ufl.Mesh( ufl.VectorElement("Lagrange", cpp.mesh.to_string(CellType.tetrahedron), 1)) mesh = create_mesh(MPI.COMM_WORLD, [cell], points, domain) mesh.topology.create_connectivity_all() V = FunctionSpace(mesh, (space_type, order)) v = ufl.TestFunction(V) f = ufl.as_vector(tuple(1 if i == 0 else 0 for i in range(tdim))) form = ufl.inner(f, ufl.curl(v)) * ufl.dx result = fem.assemble_vector(form) spaces.append(V) results.append(result.array) # Check that all DOFs on edges agree V = spaces[0] result = results[0] connectivity = V.mesh.topology.connectivity(1, 0) for i, edge in enumerate(V.mesh.topology.connectivity(tdim, 1).links(0)): vertices = connectivity.links(edge) values = sorted([ result[V.dofmap.cell_dofs(0)[a]] for a in V.dofmap.dof_layout.entity_dofs(1, i) ]) for s, r in zip(spaces[1:], results[1:]): c = s.mesh.topology.connectivity(1, 0) for j, e in enumerate( s.mesh.topology.connectivity(tdim, 1).links(0)): if sorted(c.links(e)) == sorted(vertices): v = sorted([ r[s.dofmap.cell_dofs(0)[a]] for a in s.dofmap.dof_layout.entity_dofs(1, j) ]) assert np.allclose(values, v) break else: continue break
def split_vector_laplace(cell, degree): m = Mesh(VectorElement('CG', cell, 1)) if cell.cellname() in ['interval * interval', 'quadrilateral']: hcurl_element = FiniteElement('RTCE', cell, degree) elif cell.cellname() == 'triangle * interval': U0 = FiniteElement('RT', triangle, degree) U1 = FiniteElement('CG', triangle, degree) V0 = FiniteElement('CG', interval, degree) V1 = FiniteElement('DG', interval, degree - 1) Wa = HCurlElement(TensorProductElement(U0, V0)) Wb = HCurlElement(TensorProductElement(U1, V1)) hcurl_element = EnrichedElement(Wa, Wb) elif cell.cellname() == 'quadrilateral * interval': hcurl_element = FiniteElement('NCE', cell, degree) RT = FunctionSpace(m, hcurl_element) CG = FunctionSpace(m, FiniteElement('Q', cell, degree)) sigma = TrialFunction(CG) u = TrialFunction(RT) tau = TestFunction(CG) v = TestFunction(RT) return [dot(u, grad(tau))*dx, dot(grad(sigma), v)*dx, dot(curl(u), curl(v))*dx]
def norm(v, norm_type="L2", mesh=None): r"""Compute the norm of ``v``. :arg v: a ufl expression (:class:`~.ufl.classes.Expr`) to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: - Lp :math:`||v||_{L^p} = (\int |v|^p)^{\frac{1}{p}} \mathrm{d}x` - H1 :math:`||v||_{H^1}^2 = \int (v, v) + (\nabla v, \nabla v) \mathrm{d}x` - Hdiv :math:`||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\nabla\cdot v, \nabla \cdot v) \mathrm{d}x` - Hcurl :math:`||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\nabla \wedge v, \nabla \wedge v) \mathrm{d}x` """ typ = norm_type.lower() p = 2 if typ == 'l2': expr = inner(v, v) elif typ.startswith('l'): try: p = int(typ[1:]) if p < 1: raise ValueError except ValueError: raise ValueError("Don't know how to interpret %s-norm" % norm_type) expr = inner(v, v) elif typ == 'h1': expr = inner(v, v) + inner(grad(v), grad(v)) elif typ == "hdiv": expr = inner(v, v) + div(v)*div(v) elif typ == "hcurl": expr = inner(v, v) + inner(curl(v), curl(v)) else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return assemble((expr**(p/2))*dx)**(1/p)
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 rD_norm(v, D=None, func_degree=None, norm_type="L2", mesh=None): r""" This function is a modification of FEniCS's built-in norm function to adopt the :math:`r^2dr` measure as opposed to the standard Cartesian :math:`dx` one. For documentation and usage, see the `standard module <https://github.com/FEniCS/dolfin/blob/master/site-packages/dolfin/fem/norms.py>`_. .. note:: Note the extra argument func_degree: this is used to interpolate the :math:`r^2` Expression to the same degree as used in the definition of the Trial and Test function spaces. .. note:: I am manually implementing this bug fix that is not in the current FEniCS release: <https://bitbucket.org/fenics-project/dolfin/commits/c438724fa5d7f19504d4e0c48695e17b774b2c2d>_ """ if not isinstance(v, (GenericVector, GenericFunction)): cpp.dolfin_error("norms.py", "compute norm", "expected a GenericVector or GenericFunction") # Check arguments if not isinstance(norm_type, string_types): cpp.dolfin_error( "norms.py", "compute norm", "Norm type must be a string, not " + str(type(norm_type))) if mesh is not None and not isinstance(mesh, cpp.Mesh): cpp.dolfin_error("norms.py", "compute norm", "Expecting a Mesh, not " + str(type(mesh))) # Get mesh from function if isinstance(v, Function) and mesh is None: mesh = v.function_space().mesh() # Define integration measure and domain dx = ufl.dx(mesh) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)): # DS: HERE IS WHERE I MODIFY rD = Expression('pow(x[0],D-1)', D=D, degree=func_degree) if norm_type.lower() == "l2": M = v**2 * rD * dx elif norm_type.lower() == "h1": M = (v**2 + grad(v)**2) * rD * dx elif norm_type.lower() == "h10": M = grad(v)**2 * rD * dx elif norm_type.lower() == "hdiv": M = (v**2 + div(v)**2) * rD * dx elif norm_type.lower() == "hdiv0": M = div(v)**2 * rD * dx elif norm_type.lower() == "hcurl": M = (v**2 + curl(v)**2) * rD * dx elif norm_type.lower() == "hcurl0": M = curl(v)**2 * rD * dx else: cpp.dolfin_error( "norms.py", "compute norm", "Unknown norm type (\"%s\") for functions" % str(norm_type)) else: cpp.dolfin_error( "norms.py", "compute norm", "Unknown object type. Must be a vector or a function") # DS CHANGED: applied this bug fix: # https://bitbucket.org/fenics-project/dolfin/diff/site-packages/dolfin/fem/norms.py?diff2=c438724fa5d7&at=jan/general-discrete-gradient # Assemble value # r = assemble(M, form_compiler_parameters={"representation": "quadrature"}) r = assemble(M) # Check value if r < 0.0: cpp.dolfin_error( "norms.py", "compute norm", "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ # if not isinstance(v, (GenericVector, GenericFunction)): # cpp.dolfin_error("norms.py", # "compute norm", # "expected a GenericVector or GenericFunction") # Check arguments # if not isinstance(norm_type, string_types): # cpp.dolfin_error("norms.py", # "compute norm", # "Norm type must be a string, not " + # str(type(norm_type))) # if mesh is not None and not isinstance(mesh, cpp.Mesh): # cpp.dolfin_error("norms.py", # "compute norm", # "Expecting a Mesh, not " + str(type(mesh))) # Get mesh from function if isinstance(v, cpp.function.Function) and mesh is None: mesh = v.function_space().mesh() elif isinstance(v, MultiMeshFunction) and mesh is None: mesh = v.function_space().multimesh() # Define integration measure and domain if isinstance(v, MultiMeshFunction): dc = ufl.dx(mesh) + ufl.dC(mesh) assemble_func = functools.partial(assemble_multimesh, form_compiler_parameters={"representation": "quadrature"}) else: dc = ufl.dx(mesh) assemble_func = assemble # Select norm type if isinstance(v, cpp.la.GenericVector): return v.norm(norm_type.lower()) elif isinstance(v, ufl.Coefficient): if norm_type.lower() == "l2": M = v**2 * dc elif norm_type.lower() == "h1": M = (v**2 + grad(v)**2) * dc elif norm_type.lower() == "h10": M = grad(v)**2 * dc elif norm_type.lower() == "hdiv": M = (v**2 + div(v)**2) * dc elif norm_type.lower() == "hdiv0": M = div(v)**2 * dc elif norm_type.lower() == "hcurl": M = (v**2 + curl(v)**2) * dc elif norm_type.lower() == "hcurl0": M = curl(v)**2 * dc else: raise ValueError("Unknown norm type {}".format(str(norm_type))) else: raise TypeError("Do not know how to compute norm of {}".format(str(v))) # Assemble value and return return sqrt(assemble_func(M))
import ufl from ufl import inner, curl, dx from minidolfin.assembling import jit_compile_form # for fixing https://github.com/FEniCS/ffcx/pull/25 cell = ufl.tetrahedron element = ufl.FiniteElement("Nedelec 1st kind H(curl)", cell, 3) u = ufl.TrialFunction(element) v = ufl.TestFunction(element) a = inner(curl(u), curl(v)) * dx - inner(u, v) * dx jit_compile_form(a, { "compiler": "ffc", "max_preintegrated_unrolled_table_size": 2000 })
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ if not isinstance(v, (GenericVector, GenericFunction)): raise TypeError, "expected a GenericVector or GenericFunction" # Check arguments if not isinstance(norm_type, str): cpp.dolfin_error( "norms.py", "compute norm", "Norm type must be a string, not " + str(type(norm_type))) if mesh is not None and not isinstance(mesh, Mesh): cpp.dolfin_error("norms.py", "compute norm", "Expecting a Mesh, not " + str(type(mesh))) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)): if norm_type.lower() == "l2": M = inner(v, v) * dx() elif norm_type.lower() == "h1": M = inner(v, v) * dx() + inner(grad(v), grad(v)) * dx() elif norm_type.lower() == "h10": M = inner(grad(v), grad(v)) * dx() elif norm_type.lower() == "hdiv": M = inner(v, v) * dx() + div(v) * div(v) * dx() elif norm_type.lower() == "hdiv0": M = div(v) * div(v) * dx() elif norm_type.lower() == "hcurl": M = inner(v, v) * dx() + inner(curl(v), curl(v)) * dx() elif norm_type.lower() == "hcurl0": M = inner(curl(v), curl(v)) * dx() else: cpp.dolfin_error( "norms.py", "compute norm", "Unknown norm type (\"%s\") for functions" % str(norm_type)) else: cpp.dolfin_error( "norms.py", "compute norm", "Unknown object type. Must be a vector or a function") # Get mesh if isinstance(v, Function) and mesh is None: mesh = v.function_space().mesh() # Assemble value r = assemble(M, mesh=mesh, form_compiler_parameters={"representation": "quadrature"}) # Check value if r < 0.0: cpp.dolfin_error( "norms.py", "compute norm", "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
from minidolfin.meshing import build_unit_cube_mesh from minidolfin.dofmap import build_dofmap from minidolfin.dofmap import build_sparsity_pattern from minidolfin.dofmap import pattern_to_csr from minidolfin.petsc import create_matrix_from_csr from minidolfin.assembling import assemble import dijitso dijitso.set_log_level("debug") # UFL form element = ufl.FiniteElement("N1E", ufl.tetrahedron, 2) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) omega2 = 1e3 a = (ufl.inner(ufl.curl(u), ufl.curl(v)) - omega2 * ufl.dot(u, v)) * ufl.dx # Build mesh mesh = build_unit_cube_mesh(1, 1, 1) tdim = mesh.reference_cell.get_dimension() print('Number cells: {}'.format(mesh.num_entities(tdim))) # Build dofmap dofmap = build_dofmap(element, mesh) print('Number dofs: {}'.format(dofmap.dim)) # Build sparsity pattern pattern = build_sparsity_pattern(dofmap) i, j = pattern_to_csr(pattern) A = create_matrix_from_csr((i, j))
def norm(v, norm_type="L2", mesh=None, condition=None, boundary=False): r""" Overload Firedrake's ``norm`` function to allow for :math:`\ell^p` norms. Note that this version is case sensitive, i.e. ``'l2'`` and ``'L2'`` will give different results in general. :arg v: the :class:`Function` to take the norm of :kwarg norm_type: choose from 'l1', 'l2', 'linf', 'L2', 'Linf', 'H1', 'Hdiv', 'Hcurl', or any 'Lp' with :math:`p >= 1`. :kwarg mesh: the mesh that `v` is defined upon :kwarg condition: a UFL condition for specifying a subdomain to compute the norm over :kwarg boundary: should the norm be computed over the domain boundary? """ norm_codes = {"l1": 0, "l2": 2, "linf": 3} if norm_type in norm_codes or norm_type == "Linf": if boundary: raise NotImplementedError("lp errors on the boundary not yet implemented.") if condition is not None: v.interpolate(condition * v) if norm_type == "Linf": with v.dat.vec_ro as vv: return vv.max()[1] else: with v.dat.vec_ro as vv: return vv.norm(norm_codes[norm_type]) elif norm_type[0] == "l": raise NotImplementedError( "lp norm of order {:s} not supported.".format(norm_type[1:]) ) else: condition = condition or firedrake.Constant(1.0) dX = ufl.ds if boundary else ufl.dx if norm_type.startswith("L"): try: p = int(norm_type[1:]) if p < 1: raise ValueError(f"{norm_type} norm does not make sense.") except ValueError: raise ValueError(f"Don't know how to interpret {norm_type} norm.") return firedrake.assemble(condition * ufl.inner(v, v) ** (p / 2) * dX) ** ( 1 / p ) elif norm_type.lower() == "h1": return ufl.sqrt( firedrake.assemble( condition * (ufl.inner(v, v) + ufl.inner(ufl.grad(v), ufl.grad(v))) * dX ) ) elif norm_type.lower() == "hdiv": return ufl.sqrt( firedrake.assemble( condition * (ufl.inner(v, v) + ufl.div(v) * ufl.div(v)) * dX ) ) elif norm_type.lower() == "hcurl": return ufl.sqrt( firedrake.assemble( condition * (ufl.inner(v, v) + ufl.inner(ufl.curl(v), ufl.curl(v))) * dX ) ) else: raise ValueError(f"Unknown norm type {norm_type}")
def test_curl(space_type, order): """Test that curl is consistent for different cell permutations of a tetrahedron.""" tdim = cpp.mesh.cell_dim(CellType.tetrahedron) points = unit_cell_points(CellType.tetrahedron) spaces = [] results = [] cell = list(range(len(points))) random.seed(2) # Assemble vector on 5 randomly numbered cells for i in range(5): random.shuffle(cell) domain = ufl.Mesh( ufl.VectorElement("Lagrange", cpp.mesh.to_string(CellType.tetrahedron), 1)) mesh = create_mesh(MPI.COMM_WORLD, [cell], points, domain) V = FunctionSpace(mesh, (space_type, order)) v = ufl.TestFunction(V) f = ufl.as_vector(tuple(1 if i == 0 else 0 for i in range(tdim))) form = ufl.inner(f, ufl.curl(v)) * ufl.dx result = fem.assemble_vector(form) spaces.append(V) results.append(result.array) # Set data for first space V0 = spaces[0] c10_0 = V.mesh.topology.connectivity(1, 0) # Check that all DOFs on edges agree # Loop over cell edges for i, edge in enumerate(V0.mesh.topology.connectivity(tdim, 1).links(0)): # Get the edge vertices vertices0 = c10_0.links(edge) # Need to map back # Get assembled values on edge values0 = sorted([ result[V0.dofmap.cell_dofs(0)[a]] for a in V0.dofmap.dof_layout.entity_dofs(1, i) ]) for V, result in zip(spaces[1:], results[1:]): # Get edge->vertex connectivity c10 = V.mesh.topology.connectivity(1, 0) # Loop over cell edges for j, e in enumerate( V.mesh.topology.connectivity(tdim, 1).links(0)): if sorted(c10.links(e)) == sorted( vertices0): # need to map back c.links(e) values = sorted([ result[V.dofmap.cell_dofs(0)[a]] for a in V.dofmap.dof_layout.entity_dofs(1, j) ]) assert np.allclose(values0, values) break else: continue break
def norm(v, norm_type="L2", mesh=None): r""" Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ # if not isinstance(v, (GenericVector, GenericFunction)): # cpp.dolfin_error("norms.py", # "compute norm", # "expected a GenericVector or GenericFunction") # Check arguments # if not isinstance(norm_type, string_types): # cpp.dolfin_error("norms.py", # "compute norm", # "Norm type must be a string, not " + # str(type(norm_type))) # if mesh is not None and not isinstance(mesh, cpp.Mesh): # cpp.dolfin_error("norms.py", # "compute norm", # "Expecting a Mesh, not " + str(type(mesh))) # Get mesh from function if isinstance(v, cpp.function.Function) and mesh is None: mesh = v.function_space().mesh() elif isinstance(v, MultiMeshFunction) and mesh is None: mesh = v.function_space().multimesh() # Define integration measure and domain if isinstance(v, MultiMeshFunction): dc = ufl.dx(mesh) + ufl.dC(mesh) assemble_func = functools.partial(assemble_multimesh, form_compiler_parameters={"representation": "quadrature"}) else: dc = ufl.dx(mesh) assemble_func = assemble # Select norm type if isinstance(v, cpp.la.GenericVector): return v.norm(norm_type.lower()) elif isinstance(v, ufl.Coefficient): if norm_type.lower() == "l2": M = v**2 * dc elif norm_type.lower() == "h1": M = (v**2 + grad(v)**2) * dc elif norm_type.lower() == "h10": M = grad(v)**2 * dc elif norm_type.lower() == "hdiv": M = (v**2 + div(v)**2) * dc elif norm_type.lower() == "hdiv0": M = div(v)**2 * dc elif norm_type.lower() == "hcurl": M = (v**2 + curl(v)**2) * dc elif norm_type.lower() == "hcurl0": M = curl(v)**2 * dc else: raise ValueError("Unknown norm type {}".format(str(norm_type))) else: raise TypeError("Do not know how to compute norm of {}".format(str(v))) # Assemble value and return return sqrt(assemble_func(M))
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ # if not isinstance(v, (GenericVector, GenericFunction)): # cpp.dolfin_error("norms.py", # "compute norm", # "expected a GenericVector or GenericFunction") # Check arguments # if not isinstance(norm_type, string_types): # cpp.dolfin_error("norms.py", # "compute norm", # "Norm type must be a string, not " + # str(type(norm_type))) # if mesh is not None and not isinstance(mesh, cpp.Mesh): # cpp.dolfin_error("norms.py", # "compute norm", # "Expecting a Mesh, not " + str(type(mesh))) # Get mesh from function if isinstance(v, cpp.function.Function) and mesh is None: mesh = v.function_space().mesh() # Define integration measure and domain dx = ufl.dx(mesh) # Select norm type if isinstance(v, cpp.la.GenericVector): return v.norm(norm_type.lower()) elif isinstance(v, ufl.Coefficient): if norm_type.lower() == "l2": M = v**2*dx elif norm_type.lower() == "h1": M = (v**2 + grad(v)**2)*dx elif norm_type.lower() == "h10": M = grad(v)**2*dx elif norm_type.lower() == "hdiv": M = (v**2 + div(v)**2)*dx elif norm_type.lower() == "hdiv0": M = div(v)**2*dx elif norm_type.lower() == "hcurl": M = (v**2 + curl(v)**2)*dx elif norm_type.lower() == "hcurl0": M = curl(v)**2*dx # else: # cpp.dolfin_error("norms.py", # "compute norm", # "Unknown norm type (\"%s\") for functions" # % str(norm_type)) # else: # cpp.dolfin_error("norms.py", # "compute norm", # "Unknown object type. Must be a vector or a function") # Assemble value r = assemble(M) # Check value if r < 0.0: pass # cpp.dolfin_error("norms.py", # "compute norm", # "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ if not isinstance(v, (GenericVector, GenericFunction)): raise TypeError, "expected a GenericVector or GenericFunction" # Check arguments if not isinstance(norm_type, str): cpp.dolfin_error("norms.py", "compute norm", "Norm type must be a string, not " + str(type(norm_type))) if mesh is not None and not isinstance(mesh, Mesh): cpp.dolfin_error("norms.py", "compute norm", "Expecting a Mesh, not " + str(type(mesh))) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)): if norm_type.lower() == "l2": M = inner(v, v)*dx() elif norm_type.lower() == "h1": M = inner(v, v)*dx() + inner(grad(v), grad(v))*dx() elif norm_type.lower() == "h10": M = inner(grad(v), grad(v))*dx() elif norm_type.lower() == "hdiv": M = inner(v, v)*dx() + div(v)*div(v)*dx() elif norm_type.lower() == "hdiv0": M = div(v)*div(v)*dx() elif norm_type.lower() == "hcurl": M = inner(v, v)*dx() + inner(curl(v), curl(v))*dx() elif norm_type.lower() == "hcurl0": M = inner(curl(v), curl(v))*dx() else: cpp.dolfin_error("norms.py", "compute norm", "Unknown norm type (\"%s\") for functions" % str(norm_type)) else: cpp.dolfin_error("norms.py", "compute norm", "Unknown object type. Must be a vector or a function") # Get mesh if isinstance(v, Function) and mesh is None: mesh = v.function_space().mesh() # Assemble value r = assemble(M, mesh=mesh, form_compiler_parameters={"representation": "quadrature"}) # Check value if r < 0.0: cpp.dolfin_error("norms.py", "compute norm", "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
def test_curl_curl_eigenvalue(family, order): """curl curl eigenvalue problem. Solved using H(curl)-conforming finite element method. See https://www-users.cse.umn.edu/~arnold/papers/icm2002.pdf for details. """ slepc4py = pytest.importorskip("slepc4py") # noqa: F841 from slepc4py import SLEPc mesh = create_rectangle( MPI.COMM_WORLD, [np.array([0.0, 0.0]), np.array([np.pi, np.pi])], [24, 24], CellType.triangle) element = ufl.FiniteElement(family, ufl.triangle, order) V = FunctionSpace(mesh, element) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) a = inner(ufl.curl(u), ufl.curl(v)) * dx b = inner(u, v) * dx boundary_facets = locate_entities_boundary( mesh, mesh.topology.dim - 1, lambda x: np.full(x.shape[1], True, dtype=bool)) boundary_dofs = locate_dofs_topological(V, mesh.topology.dim - 1, boundary_facets) zero_u = Function(V) zero_u.x.array[:] = 0.0 bcs = [dirichletbc(zero_u, boundary_dofs)] a, b = form(a), form(b) A = assemble_matrix(a, bcs=bcs) A.assemble() B = assemble_matrix(b, bcs=bcs, diagonal=0.01) B.assemble() eps = SLEPc.EPS().create() eps.setOperators(A, B) PETSc.Options()["eps_type"] = "krylovschur" PETSc.Options()["eps_gen_hermitian"] = "" PETSc.Options()["eps_target_magnitude"] = "" PETSc.Options()["eps_target"] = 5.0 PETSc.Options()["eps_view"] = "" PETSc.Options()["eps_nev"] = 12 eps.setFromOptions() eps.solve() num_converged = eps.getConverged() eigenvalues_unsorted = np.zeros(num_converged, dtype=np.complex128) for i in range(0, num_converged): eigenvalues_unsorted[i] = eps.getEigenvalue(i) assert np.isclose(np.imag(eigenvalues_unsorted), 0.0).all() eigenvalues_sorted = np.sort(np.real(eigenvalues_unsorted))[:-1] eigenvalues_sorted = eigenvalues_sorted[np.logical_not( eigenvalues_sorted < 1E-8)] eigenvalues_exact = np.array([1.0, 1.0, 2.0, 4.0, 4.0, 5.0, 5.0, 8.0, 9.0]) assert np.isclose(eigenvalues_sorted[0:eigenvalues_exact.shape[0]], eigenvalues_exact, rtol=1E-2).all()