From 0d80c4c247a46897920171e3876f1cbd5336988d Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 31 Aug 2017 17:09:34 +0100 Subject: [PATCH 01/11] create reference cycle between Context and Translator --- tsfc/fem.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tsfc/fem.py b/tsfc/fem.py index f341bc64..401ef622 100644 --- a/tsfc/fem.py +++ b/tsfc/fem.py @@ -99,6 +99,11 @@ def entity_selector(self, callback, restriction): def index_cache(self): return {} + @cached_property + def translator(self): + # NOTE: reference cycle! + return Translator(self) + class PointSetContext(ContextBase): """Context for compile-time known evaluation points.""" @@ -153,12 +158,17 @@ def basis_evaluation(self, finat_element, local_derivatives, entity_id): class Translator(MultiFunction, ModifiedTerminalMixin, ufl2gem.Mixin): - """Contains all the context necessary to translate UFL into GEM.""" + """Multifunction for translating UFL -> GEM. Incorporates ufl2gem.Mixin, and + dispatches on terminal type when reaching modified terminals.""" def __init__(self, context): + # MultiFunction.__init__ does not call further __init__ + # methods, but ufl2gem.Mixin must be initialised. + # (ModifiedTerminalMixin requires no initialisation.) MultiFunction.__init__(self) ufl2gem.Mixin.__init__(self) + # Need context during translation! self.context = context def modified_terminal(self, o): @@ -414,8 +424,7 @@ def compile_ufl(expression, interior_facet=False, point_sum=False, **kwargs): expressions = [expression] # Translate UFL to GEM, lowering finite element specific nodes - translator = Translator(context) - result = map_expr_dags(translator, expressions) + result = map_expr_dags(context.translator, expressions) if point_sum: result = [gem.index_sum(expr, context.point_indices) for expr in result] return result From d71b0054dcdea20ae269163b64a75c981889691f Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 16:19:46 +0100 Subject: [PATCH 02/11] remove long deprecated coefficient mode argument --- tsfc/kernel_interface/ufc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsfc/kernel_interface/ufc.py b/tsfc/kernel_interface/ufc.py index 7cdfb092..252399d5 100644 --- a/tsfc/kernel_interface/ufc.py +++ b/tsfc/kernel_interface/ufc.py @@ -62,11 +62,10 @@ def set_arguments(self, arguments, multiindices): self.apply_glue(prepare) return expressions - def set_coordinates(self, coefficient, mode=None): + def set_coordinates(self, coefficient): """Prepare the coordinate field. :arg coefficient: :class:`ufl.Coefficient` - :arg mode: (ignored) """ self.coordinates_args, expression = prepare_coordinates( coefficient, "coordinate_dofs", interior_facet=self.interior_facet) From 05b2d8c3b18baf09b3454386ef39cfd0c31807eb Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 17:05:00 +0100 Subject: [PATCH 03/11] accept more modified geometric terminals --- tsfc/modified_terminals.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tsfc/modified_terminals.py b/tsfc/modified_terminals.py index 85712069..07e9a40a 100644 --- a/tsfc/modified_terminals.py +++ b/tsfc/modified_terminals.py @@ -24,8 +24,8 @@ from ufl.classes import (ReferenceValue, ReferenceGrad, NegativeRestricted, PositiveRestricted, - Restricted, FacetAvg, CellAvg, - ConstantValue) + Restricted, FacetAvg, CellAvg, ConstantValue, + Jacobian, SpatialCoordinate) class ModifiedTerminal(object): @@ -157,12 +157,14 @@ def analyse_modified_terminal(expr): if reference_value is None: reference_value = False - mt = ModifiedTerminal(expr, t, local_derivatives, averaged, restriction, reference_value) + # Consistency check + if isinstance(t, (SpatialCoordinate, Jacobian)): + pass + else: + if local_derivatives and not reference_value: + raise ValueError("Local derivatives of non-local value?") - if local_derivatives and not reference_value: - raise ValueError("Local derivatives of non-local value?") - - return mt + return ModifiedTerminal(expr, t, local_derivatives, averaged, restriction, reference_value) def construct_modified_terminal(mt, terminal): From ac8f1215ba74dabef437ebc451cc1f43d5ee90fd Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 17:05:53 +0100 Subject: [PATCH 04/11] extend kernel interface --- tsfc/kernel_interface/__init__.py | 5 +++++ tsfc/kernel_interface/common.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/tsfc/kernel_interface/__init__.py b/tsfc/kernel_interface/__init__.py index 4e8b7a2f..0eb52be7 100644 --- a/tsfc/kernel_interface/__init__.py +++ b/tsfc/kernel_interface/__init__.py @@ -10,6 +10,11 @@ class KernelInterface(with_metaclass(ABCMeta)): """Abstract interface for accessing the GEM expressions corresponding to kernel arguments.""" + @abstractmethod + def coordinate(self, ufl_domain): + """A function that maps :class:`ufl.Domain`s to coordinate + :class:`ufl.Coefficient`s.""" + @abstractmethod def coefficient(self, ufl_coefficient, restriction): """A function that maps :class:`ufl.Coefficient`s to GEM diff --git a/tsfc/kernel_interface/common.py b/tsfc/kernel_interface/common.py index ac01068b..b3fee316 100644 --- a/tsfc/kernel_interface/common.py +++ b/tsfc/kernel_interface/common.py @@ -23,9 +23,15 @@ def __init__(self, interior_facet=False): self.prepare = [] self.finalise = [] + # Coordinates + self.domain_coordinate = {} + # Coefficients self.coefficient_map = {} + def coordinate(self, domain): + return self.domain_coordinate[domain] + def coefficient(self, ufl_coefficient, restriction): """A function that maps :class:`ufl.Coefficient`s to GEM expressions.""" From 500c1cfce261c1d0a29f31bfee0906e2abc32204 Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 17:06:56 +0100 Subject: [PATCH 05/11] handle SpatialCoordinate in 1st stage --- tsfc/fem.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tsfc/fem.py b/tsfc/fem.py index 401ef622..bcb6da66 100644 --- a/tsfc/fem.py +++ b/tsfc/fem.py @@ -18,7 +18,8 @@ CellVolume, Coefficient, FacetArea, FacetCoordinate, GeometricQuantity, QuadratureWeight, ReferenceCellVolume, - ReferenceFacetVolume, ReferenceNormal) + ReferenceFacetVolume, ReferenceNormal, + SpatialCoordinate) from FIAT.reference_element import make_affine_mapping @@ -33,9 +34,11 @@ from tsfc import ufl2gem from tsfc.finatinterface import as_fiat_cell from tsfc.kernel_interface import ProxyKernelInterface -from tsfc.modified_terminals import analyse_modified_terminal +from tsfc.modified_terminals import (analyse_modified_terminal, + construct_modified_terminal) from tsfc.parameters import NUMPY_TYPE, PARAMETERS -from tsfc.ufl_utils import ModifiedTerminalMixin, PickRestriction, simplify_abs +from tsfc.ufl_utils import (ModifiedTerminalMixin, PickRestriction, + simplify_abs, preprocess_expression) class ContextBase(ProxyKernelInterface): @@ -293,6 +296,18 @@ def translate_facet_coordinate(terminal, mt, ctx): return ctx.point_expr +@translate.register(SpatialCoordinate) +def translate_spatialcoordinate(terminal, mt, ctx): + # Replace terminal with a Coefficient + terminal = ctx.coordinate(terminal.ufl_domain()) + # Get back to reference space + terminal = preprocess_expression(terminal) + # Rebuild modified terminal + expr = construct_modified_terminal(mt, terminal) + # Translate replaced UFL snippet + return ctx.translator(expr) + + @translate.register(CellVolume) def translate_cellvolume(terminal, mt, ctx): return ctx.cellvolume(mt.restriction) From 33e91cf933eaa3e68f31a23728a0822ddd98eb2f Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 17:07:43 +0100 Subject: [PATCH 06/11] switch to new kernel interface --- tsfc/driver.py | 32 +++++++++++++----------------- tsfc/kernel_interface/firedrake.py | 9 ++++++--- tsfc/kernel_interface/ufc.py | 12 +++++++---- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/tsfc/driver.py b/tsfc/driver.py index 0e892d9d..6b61fbb6 100644 --- a/tsfc/driver.py +++ b/tsfc/driver.py @@ -14,7 +14,7 @@ import ufl from ufl.algorithms import extract_arguments, extract_coefficients from ufl.algorithms.analysis import has_type -from ufl.classes import Form, CellVolume +from ufl.classes import Form, GeometricQuantity from ufl.log import GREEN from ufl.utils.sequences import max_degree @@ -109,8 +109,7 @@ def compile_integral(integral_data, form_data, prefix, parameters, for arg in arguments) return_variables = builder.set_arguments(arguments, argument_multiindices) - coordinates = ufl_utils.coordinate_coefficient(mesh) - builder.set_coordinates(coordinates) + builder.set_coordinates(mesh) builder.set_coefficients(integral_data, form_data) @@ -132,8 +131,8 @@ def compile_integral(integral_data, form_data, prefix, parameters, argument_multiindices=argument_multiindices, index_cache=index_cache) - kernel_cfg["facetarea"] = facetarea_generator(mesh, coordinates, kernel_cfg, integral_type) - kernel_cfg["cellvolume"] = cellvolume_generator(mesh, coordinates, kernel_cfg) + kernel_cfg["facetarea"] = facetarea_generator(mesh, kernel_cfg, integral_type) + kernel_cfg["cellvolume"] = cellvolume_generator(mesh, kernel_cfg) mode_irs = collections.OrderedDict() for integral in integral_data.integrals: @@ -145,8 +144,7 @@ def compile_integral(integral_data, form_data, prefix, parameters, mode = pick_mode(params["mode"]) mode_irs.setdefault(mode, collections.OrderedDict()) - integrand = ufl_utils.replace_coordinates(integral.integrand(), coordinates) - integrand = ufl.replace(integrand, form_data.function_replace_map) + integrand = ufl.replace(integral.integrand(), form_data.function_replace_map) integrand = ufl_utils.split_coefficients(integrand, builder.coefficient_split) # Check if the integral has a quad degree attached, otherwise use @@ -157,7 +155,7 @@ def compile_integral(integral_data, form_data, prefix, parameters, quadrature_degree = params["quadrature_degree"] except KeyError: quadrature_degree = params["estimated_polynomial_degree"] - functions = list(arguments) + [coordinates] + list(integral_data.integral_coefficients) + functions = list(arguments) + [builder.coordinate(mesh)] + list(integral_data.integral_coefficients) function_degrees = [f.ufl_function_space().ufl_element().degree() for f in functions] if all((asarray(quadrature_degree) > 10 * asarray(degree)).all() for degree in function_degrees): @@ -263,11 +261,10 @@ def coefficient(self, ufl_coefficient, r): return self._wrapee.coefficient(ufl_coefficient, self.restriction) -def cellvolume_generator(domain, coordinate_coefficient, kernel_config): +def cellvolume_generator(domain, kernel_config): def cellvolume(restriction): from ufl import dx integrand, degree = ufl_utils.one_times(dx(domain=domain)) - integrand = ufl_utils.replace_coordinates(integrand, coordinate_coefficient) interface = CellVolumeKernelInterface(kernel_config["interface"], restriction) config = {k: v for k, v in kernel_config.items() @@ -278,12 +275,11 @@ def cellvolume(restriction): return cellvolume -def facetarea_generator(domain, coordinate_coefficient, kernel_config, integral_type): +def facetarea_generator(domain, kernel_config, integral_type): def facetarea(): from ufl import Measure assert integral_type != 'cell' integrand, degree = ufl_utils.one_times(Measure(integral_type, domain=domain)) - integrand = ufl_utils.replace_coordinates(integrand, coordinate_coefficient) config = kernel_config.copy() config.update(quadrature_degree=degree) @@ -318,19 +314,19 @@ def compile_expression_at_points(expression, points, coordinates, parameters=Non # Apply UFL preprocessing expression = ufl_utils.preprocess_expression(expression) + # Initialise kernel builder + builder = firedrake_interface.ExpressionKernelBuilder() + # Replace coordinates (if any) domain = expression.ufl_domain() if domain: assert coordinates.ufl_domain() == domain - expression = ufl_utils.replace_coordinates(expression, coordinates) + builder.domain_coordinate[domain] = coordinates # Collect required coefficients coefficients = extract_coefficients(expression) - if coordinates not in coefficients and has_type(expression, CellVolume): + if has_type(expression, GeometricQuantity): coefficients = [coordinates] + coefficients - - # Initialise kernel builder - builder = firedrake_interface.ExpressionKernelBuilder() builder.set_coefficients(coefficients) # Split mixed coefficients @@ -342,7 +338,7 @@ def compile_expression_at_points(expression, points, coordinates, parameters=Non ufl_cell=coordinates.ufl_domain().ufl_cell(), precision=parameters["precision"], point_set=point_set) - config["cellvolume"] = cellvolume_generator(coordinates.ufl_domain(), coordinates, config) + config["cellvolume"] = cellvolume_generator(coordinates.ufl_domain(), config) ir, = fem.compile_ufl(expression, point_sum=False, **config) # Deal with non-scalar expressions diff --git a/tsfc/kernel_interface/firedrake.py b/tsfc/kernel_interface/firedrake.py index e9756d47..36fd2293 100644 --- a/tsfc/kernel_interface/firedrake.py +++ b/tsfc/kernel_interface/firedrake.py @@ -181,12 +181,15 @@ def set_arguments(self, arguments, multiindices): arguments, multiindices, interior_facet=self.interior_facet) return expressions - def set_coordinates(self, coefficient): + def set_coordinates(self, domain): """Prepare the coordinate field. - :arg coefficient: :class:`ufl.Coefficient` + :arg domain: :class:`ufl.Domain` """ - self.coordinates_arg = self._coefficient(coefficient, "coords") + # Create a fake coordinate coefficient for a domain. + f = Coefficient(FunctionSpace(domain, domain.ufl_coordinate_element())) + self.domain_coordinate[domain] = f + self.coordinates_arg = self._coefficient(f, "coords") def set_coefficients(self, integral_data, form_data): """Prepare the coefficients of the form. diff --git a/tsfc/kernel_interface/ufc.py b/tsfc/kernel_interface/ufc.py index 252399d5..cbcdd2c8 100644 --- a/tsfc/kernel_interface/ufc.py +++ b/tsfc/kernel_interface/ufc.py @@ -12,6 +12,8 @@ from finat import TensorFiniteElement +import ufl + from tsfc.kernel_interface.common import KernelBuilderBase from tsfc.finatinterface import create_element as _create_element from tsfc.coffee import SCALAR_TYPE @@ -62,14 +64,16 @@ def set_arguments(self, arguments, multiindices): self.apply_glue(prepare) return expressions - def set_coordinates(self, coefficient): + def set_coordinates(self, domain): """Prepare the coordinate field. - :arg coefficient: :class:`ufl.Coefficient` + :arg domain: :class:`ufl.Domain` """ + # Create a fake coordinate coefficient for a domain. + f = ufl.Coefficient(ufl.FunctionSpace(domain, domain.ufl_coordinate_element())) self.coordinates_args, expression = prepare_coordinates( - coefficient, "coordinate_dofs", interior_facet=self.interior_facet) - self.coefficient_map[coefficient] = expression + f, "coordinate_dofs", interior_facet=self.interior_facet) + self.coefficient_map[f] = expression def set_coefficients(self, integral_data, form_data): """Prepare the coefficients of the form. From 50a777906531f2d693dbed806ac4d0035392b453 Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 31 Aug 2017 17:26:06 +0100 Subject: [PATCH 07/11] CellVolume: driver.py -> fem.py --- tsfc/driver.py | 32 -------------------------------- tsfc/fem.py | 29 ++++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/tsfc/driver.py b/tsfc/driver.py index 6b61fbb6..eeeb41c3 100644 --- a/tsfc/driver.py +++ b/tsfc/driver.py @@ -32,7 +32,6 @@ from tsfc.logging import logger from tsfc.parameters import default_parameters -from tsfc.kernel_interface import ProxyKernelInterface import tsfc.kernel_interface.firedrake as firedrake_interface @@ -132,7 +131,6 @@ def compile_integral(integral_data, form_data, prefix, parameters, index_cache=index_cache) kernel_cfg["facetarea"] = facetarea_generator(mesh, kernel_cfg, integral_type) - kernel_cfg["cellvolume"] = cellvolume_generator(mesh, kernel_cfg) mode_irs = collections.OrderedDict() for integral in integral_data.integrals: @@ -246,35 +244,6 @@ def name_multiindex(multiindex, name): return builder.construct_kernel(kernel_name, body) -class CellVolumeKernelInterface(ProxyKernelInterface): - # Since CellVolume is evaluated as a cell integral, we must ensure - # that the right restriction is applied when it is used in an - # interior facet integral. This proxy diverts coefficient - # translation to use a specified restriction. - - def __init__(self, wrapee, restriction): - ProxyKernelInterface.__init__(self, wrapee) - self.restriction = restriction - - def coefficient(self, ufl_coefficient, r): - assert r is None - return self._wrapee.coefficient(ufl_coefficient, self.restriction) - - -def cellvolume_generator(domain, kernel_config): - def cellvolume(restriction): - from ufl import dx - integrand, degree = ufl_utils.one_times(dx(domain=domain)) - interface = CellVolumeKernelInterface(kernel_config["interface"], restriction) - - config = {k: v for k, v in kernel_config.items() - if k in ["ufl_cell", "precision", "index_cache"]} - config.update(interface=interface, quadrature_degree=degree) - expr, = fem.compile_ufl(integrand, point_sum=True, **config) - return expr - return cellvolume - - def facetarea_generator(domain, kernel_config, integral_type): def facetarea(): from ufl import Measure @@ -338,7 +307,6 @@ def compile_expression_at_points(expression, points, coordinates, parameters=Non ufl_cell=coordinates.ufl_domain().ufl_cell(), precision=parameters["precision"], point_set=point_set) - config["cellvolume"] = cellvolume_generator(coordinates.ufl_domain(), config) ir, = fem.compile_ufl(expression, point_sum=False, **config) # Deal with non-scalar expressions diff --git a/tsfc/fem.py b/tsfc/fem.py index bcb6da66..cfa81c63 100644 --- a/tsfc/fem.py +++ b/tsfc/fem.py @@ -11,6 +11,7 @@ import numpy from singledispatch import singledispatch +import ufl from ufl.corealg.map_dag import map_expr_dag, map_expr_dags from ufl.corealg.multifunction import MultiFunction from ufl.classes import (Argument, CellCoordinate, CellEdgeVectors, @@ -38,7 +39,8 @@ construct_modified_terminal) from tsfc.parameters import NUMPY_TYPE, PARAMETERS from tsfc.ufl_utils import (ModifiedTerminalMixin, PickRestriction, - simplify_abs, preprocess_expression) + one_times, simplify_abs, + preprocess_expression) class ContextBase(ProxyKernelInterface): @@ -50,7 +52,6 @@ class ContextBase(ProxyKernelInterface): 'entity_ids', 'precision', 'argument_multiindices', - 'cellvolume', 'facetarea', 'index_cache') @@ -308,9 +309,31 @@ def translate_spatialcoordinate(terminal, mt, ctx): return ctx.translator(expr) +class CellVolumeKernelInterface(ProxyKernelInterface): + # Since CellVolume is evaluated as a cell integral, we must ensure + # that the right restriction is applied when it is used in an + # interior facet integral. This proxy diverts coefficient + # translation to use a specified restriction. + + def __init__(self, wrapee, restriction): + ProxyKernelInterface.__init__(self, wrapee) + self.restriction = restriction + + def coefficient(self, ufl_coefficient, r): + assert r is None + return self._wrapee.coefficient(ufl_coefficient, self.restriction) + + @translate.register(CellVolume) def translate_cellvolume(terminal, mt, ctx): - return ctx.cellvolume(mt.restriction) + integrand, degree = one_times(ufl.dx(domain=terminal.ufl_domain())) + interface = CellVolumeKernelInterface(ctx, mt.restriction) + + config = {name: getattr(ctx, name) + for name in ["ufl_cell", "precision", "index_cache"]} + config.update(interface=interface, quadrature_degree=degree) + expr, = compile_ufl(integrand, point_sum=True, **config) + return expr @translate.register(FacetArea) From cdb19a9826c8142bf3e864fbdcf7629ad8202227 Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 31 Aug 2017 17:42:24 +0100 Subject: [PATCH 08/11] FacetArea: driver.py -> fem.py --- tsfc/driver.py | 16 +--------------- tsfc/fem.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/tsfc/driver.py b/tsfc/driver.py index eeeb41c3..ea6675c0 100644 --- a/tsfc/driver.py +++ b/tsfc/driver.py @@ -124,14 +124,13 @@ def compile_integral(integral_data, form_data, prefix, parameters, kernel_cfg = dict(interface=builder, ufl_cell=cell, + integral_type=integral_type, precision=parameters["precision"], integration_dim=integration_dim, entity_ids=entity_ids, argument_multiindices=argument_multiindices, index_cache=index_cache) - kernel_cfg["facetarea"] = facetarea_generator(mesh, kernel_cfg, integral_type) - mode_irs = collections.OrderedDict() for integral in integral_data.integrals: params = parameters.copy() @@ -244,19 +243,6 @@ def name_multiindex(multiindex, name): return builder.construct_kernel(kernel_name, body) -def facetarea_generator(domain, kernel_config, integral_type): - def facetarea(): - from ufl import Measure - assert integral_type != 'cell' - integrand, degree = ufl_utils.one_times(Measure(integral_type, domain=domain)) - - config = kernel_config.copy() - config.update(quadrature_degree=degree) - expr, = fem.compile_ufl(integrand, point_sum=True, **config) - return expr - return facetarea - - def compile_expression_at_points(expression, points, coordinates, parameters=None): """Compiles a UFL expression to be evaluated at compile-time known reference points. Useful for interpolating UFL expressions onto diff --git a/tsfc/fem.py b/tsfc/fem.py index cfa81c63..01ce687f 100644 --- a/tsfc/fem.py +++ b/tsfc/fem.py @@ -48,6 +48,7 @@ class ContextBase(ProxyKernelInterface): keywords = ('ufl_cell', 'fiat_cell', + 'integral_type', 'integration_dim', 'entity_ids', 'precision', @@ -338,7 +339,16 @@ def translate_cellvolume(terminal, mt, ctx): @translate.register(FacetArea) def translate_facetarea(terminal, mt, ctx): - return ctx.facetarea() + assert ctx.integral_type != 'cell' + domain = terminal.ufl_domain() + integrand, degree = one_times(ufl.Measure(ctx.integral_type, domain=domain)) + + config = {name: getattr(ctx, name) + for name in ["ufl_cell", "integration_dim", + "entity_ids", "precision", "index_cache"]} + config.update(interface=ctx, quadrature_degree=degree) + expr, = compile_ufl(integrand, point_sum=True, **config) + return expr def fiat_to_ufl(fiat_dict, order): From b44667f16683f42e719139666704799731dd604d Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 14:41:03 +0100 Subject: [PATCH 09/11] remove some no longer required UFL utils --- tsfc/ufl_utils.py | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/tsfc/ufl_utils.py b/tsfc/ufl_utils.py index 83875501..bc53419e 100644 --- a/tsfc/ufl_utils.py +++ b/tsfc/ufl_utils.py @@ -19,8 +19,8 @@ from ufl.classes import (Abs, Argument, CellOrientation, Coefficient, ComponentTensor, Expr, FloatValue, Division, MixedElement, MultiIndex, Product, - ReferenceValue, ScalarValue, Sqrt, Zero, - CellVolume, FacetArea) + ScalarValue, Sqrt, Zero, CellVolume, + FacetArea) from gem.node import MemoizerArg @@ -95,37 +95,6 @@ def preprocess_expression(expression): return expression -class SpatialCoordinateReplacer(MultiFunction): - """Replace SpatialCoordinate nodes with the ReferenceValue of a - Coefficient. Assumes that the coordinate element only needs - affine mapping. - - :arg coordinates: the coefficient to replace spatial coordinates with - """ - def __init__(self, coordinates): - self.coordinates = coordinates - MultiFunction.__init__(self) - - expr = MultiFunction.reuse_if_untouched - - def terminal(self, t): - return t - - def spatial_coordinate(self, o): - assert o.ufl_domain().ufl_coordinate_element().mapping() == "identity" - return ReferenceValue(self.coordinates) - - -def replace_coordinates(integrand, coordinate_coefficient): - """Replace SpatialCoordinate nodes with Coefficients.""" - return map_expr_dag(SpatialCoordinateReplacer(coordinate_coefficient), integrand) - - -def coordinate_coefficient(domain): - """Create a fake coordinate coefficient for a domain.""" - return ufl.Coefficient(ufl.FunctionSpace(domain, domain.ufl_coordinate_element())) - - class ModifiedTerminalMixin(object): """Mixin to use with MultiFunctions that operate on modified terminals.""" From 249c62c8b384efd4eba31afa1eff675410ae8c87 Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Thu, 7 Sep 2017 17:40:18 +0100 Subject: [PATCH 10/11] implement CellOrigin --- tsfc/fem.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tsfc/fem.py b/tsfc/fem.py index 01ce687f..5f569a4e 100644 --- a/tsfc/fem.py +++ b/tsfc/fem.py @@ -16,11 +16,11 @@ from ufl.corealg.multifunction import MultiFunction from ufl.classes import (Argument, CellCoordinate, CellEdgeVectors, CellFacetJacobian, CellOrientation, - CellVolume, Coefficient, FacetArea, - FacetCoordinate, GeometricQuantity, - QuadratureWeight, ReferenceCellVolume, - ReferenceFacetVolume, ReferenceNormal, - SpatialCoordinate) + CellOrigin, CellVolume, Coefficient, + FacetArea, FacetCoordinate, + GeometricQuantity, QuadratureWeight, + ReferenceCellVolume, ReferenceFacetVolume, + ReferenceNormal, SpatialCoordinate) from FIAT.reference_element import make_affine_mapping @@ -30,6 +30,7 @@ from gem.unconcatenate import unconcatenate from gem.utils import cached_property +from finat.point_set import PointSingleton from finat.quadrature import make_quadrature from tsfc import ufl2gem @@ -351,6 +352,20 @@ def translate_facetarea(terminal, mt, ctx): return expr +@translate.register(CellOrigin) +def translate_cellorigin(terminal, mt, ctx): + domain = terminal.ufl_domain() + coords = SpatialCoordinate(domain) + expression = construct_modified_terminal(mt, coords) + point_set = PointSingleton((0.0,) * domain.topological_dimension()) + + config = {name: getattr(ctx, name) + for name in ["ufl_cell", "precision", "index_cache"]} + config.update(interface=ctx, point_set=point_set) + context = PointSetContext(**config) + return context.translator(expression) + + def fiat_to_ufl(fiat_dict, order): # All derivative multiindices must be of the same dimension. dimension, = list(set(len(alpha) for alpha in iterkeys(fiat_dict))) From 835b0b829ad206e9780c9f743f3f682119461c99 Mon Sep 17 00:00:00 2001 From: Miklos Homolya Date: Fri, 8 Sep 2017 10:57:58 +0100 Subject: [PATCH 11/11] fix UFC interface --- tsfc/kernel_interface/ufc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tsfc/kernel_interface/ufc.py b/tsfc/kernel_interface/ufc.py index cbcdd2c8..9c9b1435 100644 --- a/tsfc/kernel_interface/ufc.py +++ b/tsfc/kernel_interface/ufc.py @@ -71,6 +71,7 @@ def set_coordinates(self, domain): """ # Create a fake coordinate coefficient for a domain. f = ufl.Coefficient(ufl.FunctionSpace(domain, domain.ufl_coordinate_element())) + self.domain_coordinate[domain] = f self.coordinates_args, expression = prepare_coordinates( f, "coordinate_dofs", interior_facet=self.interior_facet) self.coefficient_map[f] = expression