Source code for ufl.functionspace
# -*- coding: utf-8 -*-
"Types for representing function spaces."
# Copyright (C) 2015-2016 Martin Sandve Alnæs
#
# This file is part of UFL (https://www.fenicsproject.org)
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Modified by Massimiliano Leoni, 2016
# Modified by Cecile Daversin-Catty, 2018
from ufl.log import error
from ufl.core.ufl_type import attach_operators_from_hash_data
from ufl.domain import join_domains
# Export list for ufl.classes
__all_classes__ = [
"AbstractFunctionSpace",
"FunctionSpace",
"MixedFunctionSpace",
"TensorProductFunctionSpace",
]
[docs]class AbstractFunctionSpace(object):
[docs] def ufl_sub_spaces(self):
raise NotImplementedError("Missing implementation of IFunctionSpace.ufl_sub_spaces in %s." % self.__class__.__name__)
[docs]@attach_operators_from_hash_data
class FunctionSpace(AbstractFunctionSpace):
def __init__(self, domain, element):
if domain is None:
# DOLFIN hack
# TODO: Is anything expected from element.cell() in this case?
pass
else:
try:
domain_cell = domain.ufl_cell()
except AttributeError:
error("Expected non-abstract domain for initalization of function space.")
else:
if element.cell() != domain_cell:
error("Non-matching cell of finite element and domain.")
AbstractFunctionSpace.__init__(self)
self._ufl_domain = domain
self._ufl_element = element
[docs] def ufl_sub_spaces(self):
"Return ufl sub spaces."
return ()
[docs] def ufl_domain(self):
"Return ufl domain."
return self._ufl_domain
[docs] def ufl_element(self):
"Return ufl element."
return self._ufl_element
[docs] def ufl_domains(self):
"Return ufl domains."
domain = self.ufl_domain()
if domain is None:
return ()
else:
return (domain,)
def _ufl_hash_data_(self):
domain = self.ufl_domain()
element = self.ufl_element()
if domain is None:
ddata = None
else:
ddata = domain._ufl_hash_data_()
if element is None:
edata = None
else:
edata = element._ufl_hash_data_()
return ("FunctionSpace", ddata, edata)
def _ufl_signature_data_(self, renumbering):
domain = self.ufl_domain()
element = self.ufl_element()
if domain is None:
ddata = None
else:
ddata = domain._ufl_signature_data_(renumbering)
if element is None:
edata = None
else:
edata = element._ufl_signature_data_()
return ("FunctionSpace", ddata, edata)
def __repr__(self):
r = "FunctionSpace(%s, %s)" % (repr(self._ufl_domain), repr(self._ufl_element))
return r
[docs]@attach_operators_from_hash_data
class TensorProductFunctionSpace(AbstractFunctionSpace):
def __init__(self, *function_spaces):
AbstractFunctionSpace.__init__(self)
self._ufl_function_spaces = function_spaces
[docs] def ufl_sub_spaces(self):
return self._ufl_function_spaces
def _ufl_hash_data_(self):
return ("TensorProductFunctionSpace",) + tuple(V._ufl_hash_data_() for V in self.ufl_sub_spaces())
def _ufl_signature_data_(self, renumbering):
return ("TensorProductFunctionSpace",) + tuple(V._ufl_signature_data_(renumbering) for V in self.ufl_sub_spaces())
def __repr__(self):
r = "TensorProductFunctionSpace(*%s)" % repr(self._ufl_function_spaces)
return r
[docs]@attach_operators_from_hash_data
class MixedFunctionSpace(AbstractFunctionSpace):
def __init__(self, *args):
AbstractFunctionSpace.__init__(self)
self._ufl_function_spaces = args
self._ufl_elements = list()
for fs in args:
if isinstance(fs, FunctionSpace):
self._ufl_elements.append(fs.ufl_element())
else:
error("Expecting FunctionSpace objects")
[docs] def ufl_sub_spaces(self):
"Return ufl sub spaces."
return self._ufl_function_spaces
[docs] def ufl_sub_space(self, i):
"Return i-th ufl sub space."
return self._ufl_function_spaces[i]
[docs] def ufl_elements(self):
"Return ufl elements."
return self._ufl_elements
[docs] def ufl_element(self):
if len(self._ufl_elements) == 1:
return self._ufl_elements[0]
else:
error("""Found multiple elements. Cannot return only one.
Consider building a FunctionSpace from a MixedElement
in case of homogeneous dimension.""")
[docs] def ufl_domains(self):
"Return ufl domains."
domainlist = []
for s in self._ufl_function_spaces:
domainlist.extend(s.ufl_domains())
return join_domains(domainlist)
[docs] def ufl_domain(self):
"Return ufl domain."
domains = self.ufl_domains()
if len(domains) == 1:
return domains[0]
elif domains:
error("Found multiple domains, cannot return just one.")
else:
return None
[docs] def num_sub_spaces(self):
return len(self._ufl_function_spaces)
def _ufl_hash_data_(self):
return ("MixedFunctionSpace",) + tuple(V._ufl_hash_data_() for V in self.ufl_sub_spaces())
def _ufl_signature_data_(self, renumbering):
return ("MixedFunctionSpace",) + tuple(V._ufl_signature_data_(renumbering) for V in self.ufl_sub_spaces())
def __repr__(self):
r = "MixedFunctionSpace(*%s)" % repr(self._ufl_function_spaces)
return r