This file is indexed.

/usr/lib/python2.7/dist-packages/ufl/measure.py is in python-ufl 2017.2.0.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
# -*- coding: utf-8 -*-
"""The Measure class."""

# Copyright (C) 2008-2016 Martin Sandve Alnæs
#
# This file is part of UFL.
#
# UFL is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# UFL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with UFL. If not, see <http://www.gnu.org/licenses/>.
#
# Modified by Anders Logg 2008-2016
# Modified by Massimiliano Leoni, 2016.

from six import string_types
import numbers

from ufl.utils.py23 import as_native_strings
from ufl.utils.py23 import as_native_str
from ufl.log import error, deprecate
from ufl.core.expr import Expr
from ufl.checks import is_true_ufl_scalar
from ufl.constantvalue import as_ufl
from ufl.utils.dicts import EmptyDict
from ufl.domain import as_domain, AbstractDomain, extract_domains
from ufl.protocols import id_or_none, metadata_equal, metadata_hashdata


# Export list for ufl.classes
__all_classes__ = as_native_strings(["Measure", "MeasureSum", "MeasureProduct"])


# TODO: Design a class IntegralType(name, shortname, codim, num_cells, ...)?
# TODO: Improve descriptions below:

# Enumeration of valid domain types
_integral_types = [
    # === Integration over full topological dimension:
    ("cell", "dx"),                     # Over cells of a mesh
    # ("macro_cell", "dE"),              # Over a group of adjacent cells (TODO: Arbitrary cell group? Not currently used.)

    # === Integration over topological dimension - 1:
    ("exterior_facet", "ds"),           # Over one-sided exterior facets of a mesh
    ("interior_facet", "dS"),           # Over two-sided facets between pairs of adjacent cells of a mesh

    # === Integration over topological dimension 0
    ("vertex", "dP"),                    # Over vertices of a mesh
    # ("vertex", "dV"),                  # TODO: Use this over vertices?
    # ("point", "dP"),                   # TODO: Use this over arbitrary points inside cells?

    # === Integration over custom domains
    ("custom", "dc"),                 # Over custom user-defined domains (run-time quadrature points)
    ("cutcell", "dC"),                # Over a cell with some part cut away (run-time quadrature points)
    ("interface", "dI"),              # Over a facet fragment overlapping with two or more cells (run-time quadrature points)
    ("overlap", "dO"),                # Over a cell fragment overlapping with two or more cells (run-time quadrature points)

    # === Firedrake specific hacks on the way out:
    # TODO: Remove these, firedrake can use metadata instead
    # and create the measure objects in firedrake:
    ("exterior_facet_bottom", "ds_b"),  # Over bottom facets on extruded mesh
    ("exterior_facet_top", "ds_t"),     # Over top facets on extruded mesh
    ("exterior_facet_vert", "ds_v"),    # Over side facets of an extruded mesh
    ("interior_facet_horiz", "dS_h"),   # Over horizontal facets of an extruded mesh
    ("interior_facet_vert", "dS_v"),  # Over vertical facets of an extruded mesh
]

integral_type_to_measure_name = dict((l, s) for l, s in _integral_types)
measure_name_to_integral_type = dict((s, l) for l, s in _integral_types)

custom_integral_types = ("custom", "cutcell", "interface", "overlap")
point_integral_types = ("vertex",)  # "point")
facet_integral_types = ("exterior_facet", "interior_facet")


def register_integral_type(integral_type, measure_name):
    global integral_type_to_measure_name, measure_name_to_integral_type
    if measure_name != integral_type_to_measure_name.get(integral_type, measure_name):
        error("Integral type already added with different measure name!")
    if integral_type != measure_name_to_integral_type.get(measure_name, integral_type):
        error("Measure name already used for another domain type!")
    integral_type_to_measure_name[integral_type] = measure_name
    measure_name_to_integral_type[measure_name] = integral_type


def as_integral_type(integral_type):
    "Map short name to long name and require a valid one."
    integral_type = integral_type.replace(" ", "_")
    integral_type = measure_name_to_integral_type.get(integral_type,
                                                      integral_type)
    if integral_type not in integral_type_to_measure_name:
        error("Invalid integral_type.")
    return integral_type


def integral_types():
    "Return a tuple of all domain type strings."
    return tuple(sorted(integral_type_to_measure_name.keys()))


def measure_names():
    "Return a tuple of all measure name strings."
    return tuple(sorted(measure_name_to_integral_type.keys()))


class Measure(object):
    __slots__ = as_native_strings(("_integral_type",
                                   "_domain",
                                   "_subdomain_id",
                                   "_metadata",
                                   "_subdomain_data"))
    """Representation of an integration measure.

    The Measure object holds information about integration properties
    to be transferred to a Form on multiplication with a scalar
    expression.

    """

    def __init__(self,
                 integral_type,  # "dx" etc
                 domain=None,
                 subdomain_id="everywhere",
                 metadata=None,
                 subdomain_data=None):
        """
        integral_type:
            str, one of "cell", etc.,
            or short form "dx", etc.

        domain:
            an AbstractDomain object (most often a Mesh)

        subdomain_id:
            either string "everywhere",
            a single subdomain id int,
            or tuple of ints

        metadata:
            dict, with additional compiler-specific parameters
            affecting how code is generated, including parameters
            for optimization or debugging of generated code.

        subdomain_data:
            object representing data to interpret subdomain_id with.
        """
        # Map short name to long name and require a valid one
        self._integral_type = as_integral_type(integral_type)

        # Check that we either have a proper AbstractDomain or none
        self._domain = None if domain is None else as_domain(domain)
        if not (self._domain is None or isinstance(self._domain, AbstractDomain)):
            error("Invalid domain.")

        # Store subdomain data
        self._subdomain_data = subdomain_data
        # FIXME: Cannot require this (yet) because we currently have
        # no way to implement ufl_id for dolfin SubDomain
        # if not (self._subdomain_data is None or hasattr(self._subdomain_data, "ufl_id")):
        #     error("Invalid domain data, missing ufl_id() implementation.")

        # Accept "everywhere", single subdomain, or multiple
        # subdomains
        if isinstance(subdomain_id, tuple):
            for did in subdomain_id:
                if not isinstance(did, numbers.Integral):
                    error("Invalid subdomain_id %s." % (did,))
        else:
            if not (subdomain_id in ("everywhere",) or isinstance(subdomain_id, numbers.Integral)):
                error("Invalid subdomain_id %s." % (subdomain_id,))
        self._subdomain_id = subdomain_id

        # Validate compiler options are None or dict
        if metadata is not None and not isinstance(metadata, dict):
            error("Invalid metadata.")
        self._metadata = metadata or EmptyDict

    def integral_type(self):
        """Return the domain type.

        Valid domain types are "cell", "exterior_facet", "interior_facet", etc.
        """
        return self._integral_type

    def ufl_domain(self):
        """Return the domain associated with this measure.

        This may be None or a Domain object.
        """
        return self._domain

    def subdomain_id(self):
        "Return the domain id of this measure (integer)."
        return self._subdomain_id

    def metadata(self):
        """Return the integral metadata. This data is not interpreted by UFL.
        It is passed to the form compiler which can ignore it or use
        it to compile each integral of a form in a different way.

        """
        return self._metadata

    def reconstruct(self,
                    integral_type=None,
                    subdomain_id=None,
                    domain=None,
                    metadata=None,
                    subdomain_data=None):
        """Construct a new Measure object with some properties replaced with
        new values.

        Example:
            <dm = Measure instance>
            b = dm.reconstruct(subdomain_id=2)
            c = dm.reconstruct(metadata={ "quadrature_degree": 3 })

        Used by the call operator, so this is equivalent:
            b = dm(2)
            c = dm(0, { "quadrature_degree": 3 })

        """
        if subdomain_id is None:
            subdomain_id = self.subdomain_id()
        if domain is None:
            domain = self.ufl_domain()
        if metadata is None:
            metadata = self.metadata()
        if subdomain_data is None:
            subdomain_data = self.subdomain_data()
        return Measure(self.integral_type(),
                       domain=domain, subdomain_id=subdomain_id,
                       metadata=metadata, subdomain_data=subdomain_data)

    def subdomain_data(self):
        """Return the integral subdomain_data. This data is not interpreted by
        UFL.  Its intension is to give a context in which the domain
        id is interpreted.

        """
        return self._subdomain_data

    # Note: Must keep the order of the first two arguments here
    # (subdomain_id, metadata) for backwards compatibility, because
    # some tutorials write e.g. dx(0, {...}) to set metadata.
    def __call__(self, subdomain_id=None, metadata=None, domain=None,
                 subdomain_data=None, degree=None, scheme=None, rule=None):
        """Reconfigure measure with new domain specification or metadata."""

        # Deprecation of 'rule' in favour of 'scheme'
        if rule is not None:
            deprecate("Measure argument 'rule' has been renamed to 'scheme'.")
            assert scheme is None or scheme == rule
            scheme = rule

        # Let syntax dx() mean integral over everywhere
        all_args = (subdomain_id, metadata, domain, subdomain_data,
                    degree, scheme)
        if all(arg is None for arg in all_args):
            return self.reconstruct(subdomain_id="everywhere")

        # Let syntax dx(domain) or dx(domain, metadata) mean integral
        # over entire domain.  To do this we need to hijack the first
        # argument:
        if subdomain_id is not None and (isinstance(subdomain_id,
                                                    AbstractDomain) or
                                         hasattr(subdomain_id, 'ufl_domain')):
            if domain is not None:
                error("Ambiguous: setting domain both as keyword argument and first argument.")
            subdomain_id, domain = "everywhere", as_domain(subdomain_id)

        # If degree or scheme is set, inject into metadata. This is a
        # quick fix to enable the dx(..., degree=3) notation.
        # TODO: Make degree and scheme properties of integrals instead of adding to metadata.
        if (degree, scheme) != (None, None):
            metadata = {} if metadata is None else metadata.copy()
            if degree is not None:
                metadata["quadrature_degree"] = degree
            if scheme is not None:
                metadata["quadrature_rule"] = scheme

        # If we get any keywords, use them to reconstruct Measure.
        # Note that if only one argument is given, it is the
        # subdomain_id, e.g. dx(3) == dx(subdomain_id=3)
        return self.reconstruct(subdomain_id=subdomain_id, domain=domain,
                                metadata=metadata,
                                subdomain_data=subdomain_data)

    def __getitem__(self, data):
        """This operator supports legacy syntax in python dolfin programs.

        The old documentation reads: Return a new Measure for same
        integration type with an attached context for interpreting
        domain ids. By default this new Measure integrates over
        everywhere, but it can be restricted with a domain id as
        usual. Example: dx = dx[boundaries]; L = f*v*dx + g*v+dx(1).

        """
        deprecate("Notation dx[meshfunction] is deprecated. Please use dx(subdomain_data=meshfunction) instead.")
        return self(subdomain_data=data)

    def __unicode__(self):
        # Only in python 2
        return str(self).decode("utf-8")

    def __str__(self):
        global integral_type_to_measure_name
        name = integral_type_to_measure_name[self._integral_type]
        args = []

        if self._subdomain_id is not None:
            args.append("subdomain_id=%s" % (self._subdomain_id,))
        if self._domain is not None:
            args.append("domain=%s" % (self._domain,))
        if self._metadata:  # Stored as EmptyDict if None
            args.append("metadata=%s" % (self._metadata,))
        if self._subdomain_data is not None:
            args.append("subdomain_data=%s" % (self._subdomain_data,))

        return "%s(%s)" % (name, ', '.join(args))

    def __repr__(self):
        "Return a repr string for this Measure."
        global integral_type_to_measure_name

        args = []
        args.append(repr(self._integral_type))

        if self._subdomain_id is not None:
            args.append("subdomain_id=%s" % repr(self._subdomain_id))
        if self._domain is not None:
            args.append("domain=%s" % repr(self._domain))
        if self._metadata:  # Stored as EmptyDict if None
            args.append("metadata=%s" % repr(self._metadata))
        if self._subdomain_data is not None:
            args.append("subdomain_data=%s" % repr(self._subdomain_data))

        r = "%s(%s)" % (type(self).__name__, ', '.join(args))
        return as_native_str(r)

    def __hash__(self):
        "Return a hash value for this Measure."
        hashdata = (self._integral_type,
                    self._subdomain_id,
                    hash(self._domain),
                    metadata_hashdata(self._metadata),
                    id_or_none(self._subdomain_data))
        return hash(hashdata)

    def __eq__(self, other):
        "Checks if two Measures are equal."
        return (isinstance(other, Measure) and
                self._integral_type == other._integral_type and
                self._subdomain_id == other._subdomain_id and
                self._domain == other._domain and
                id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data) and
                metadata_equal(self._metadata, other._metadata))

    def __add__(self, other):
        """Add two measures (self+other).

        Creates an intermediate object used for the notation

          expr * (dx(1) + dx(2)) := expr * dx(1) + expr * dx(2)
        """
        if isinstance(other, Measure):
            # Let dx(1) + dx(2) equal dx((1,2))
            return MeasureSum(self, other)
        else:
            # Can only add Measures
            return NotImplemented

    def __mul__(self, other):
        """Multiply two measures (self*other).

        Creates an intermediate object used for the notation

          expr * (dm1 * dm2) := expr * dm1 * dm2

        This is work in progress and not functional.
        """
        if isinstance(other, Measure):
            # Tensor product measure support
            return MeasureProduct(self, other)
        else:
            # Can't multiply Measure from the right with non-Measure type
            return NotImplemented

    def __rmul__(self, integrand):
        """Multiply a scalar expression with measure to construct a form with
        a single integral.

        This is to implement the notation

            form = integrand * self

        Integration properties are taken from this Measure object.

        """
        # Avoid circular imports
        from ufl.integral import Integral
        from ufl.form import Form

        # Allow python literals: 1*dx and 1.0*dx
        if isinstance(integrand, (int, float)):
            integrand = as_ufl(integrand)

        # Let other types implement multiplication with Measure if
        # they want to (to support the dolfin-adjoint TimeMeasure)
        if not isinstance(integrand, Expr):
            return NotImplemented

        # Allow only scalar integrands
        if not is_true_ufl_scalar(integrand):
            error("Can only integrate scalar expressions. The integrand is a "
                  "tensor expression with value shape %s and free indices with labels %s." %
                  (integrand.ufl_shape, integrand.ufl_free_indices))

        # If we have a tuple of domain ids, delegate composition to
        # Integral.__add__:
        subdomain_id = self.subdomain_id()
        if isinstance(subdomain_id, tuple):
            return sum(integrand*self.reconstruct(subdomain_id=d) for d in subdomain_id)

        # Check that we have an integer subdomain or a string
        # ("everywhere" or "otherwise", any more?)
        if not isinstance(subdomain_id, string_types + (numbers.Integral,)):
            error("Expecting integer or string domain id.")

        # If we don't have an integration domain, try to find one in
        # integrand
        domain = self.ufl_domain()
        if domain is None:
            domains = extract_domains(integrand)
            if len(domains) == 1:
                domain, = domains
            elif len(domains) == 0:
                error("This integral is missing an integration domain.")
            else:
                error("Multiple domains found, making the choice of integration domain ambiguous.")

        # Otherwise create and return a one-integral form
        integral = Integral(integrand=integrand,
                            integral_type=self.integral_type(),
                            domain=domain,
                            subdomain_id=subdomain_id,
                            metadata=self.metadata(),
                            subdomain_data=self.subdomain_data())
        return Form([integral])


class MeasureSum(object):
    """Represents a sum of measures.

    This is a notational intermediate object to translate the notation

        f*(ds(1)+ds(3))

    into

        f*ds(1) + f*ds(3)
    """
    __slots__ = as_native_strings(("_measures",))

    def __init__(self, *measures):
        self._measures = measures

    def __rmul__(self, other):
        integrals = [other*m for m in self._measures]
        return sum(integrals)

    def __add__(self, other):
        if isinstance(other, Measure):
            return MeasureSum(*(self._measures + (other,)))
        elif isinstance(other, MeasureSum):
            return MeasureSum(*(self._measures + other._measures))
        return NotImplemented

    def __unicode__(self):
        # Only in python 2
        return str(self).decode("utf-8")

    def __str__(self):
        return "{\n    " + "\n  + ".join(map(str, self._measures)) + "\n}"


class MeasureProduct(object):
    """Represents a product of measures.

    This is a notational intermediate object to handle the notation

        f*(dm1*dm2)

    This is work in progress and not functional. It needs support
    in other parts of ufl and the rest of the code generation chain.

    """
    __slots__ = as_native_strings(("_measures",))

    def __init__(self, *measures):
        "Create MeasureProduct from given list of measures."
        self._measures = measures
        if len(self._measures) < 2:
            error("Expecting at least two measures.")

    def __mul__(self, other):
        """Flatten multiplication of product measures.

        This is to ensure that (dm1*dm2)*dm3 is stored as a simple
        list (dm1,dm2,dm3) in a single MeasureProduct.

        """
        if isinstance(other, Measure):
            measures = self.sub_measures() + [other]
            return MeasureProduct(*measures)
        else:
            return NotImplemented

    def __rmul__(self, integrand):
        error("TODO: Implement MeasureProduct.__rmul__ to construct integral and form somehow.")

    def sub_measures(self):
        "Return submeasures."
        return self._measures