/usr/lib/python2.7/dist-packages/ffc/uflacs/analysis/indexing.py is in python-ffc 2016.2.0-1.
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 | # -*- coding: utf-8 -*-
# Copyright (C) 2011-2016 Martin Sandve Alnæs
#
# This file is part of UFLACS.
#
# UFLACS 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.
#
# UFLACS 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 UFLACS. If not, see <http://www.gnu.org/licenses/>.
"""Algorithms for working with multiindices."""
from ufl import product
from ufl.permutation import compute_indices
from ufl.utils.indexflattening import shape_to_strides, flatten_multiindex
from ufl.classes import ComponentTensor, FixedIndex, Index, Indexed
def map_indexed_arg_components(indexed):
"""Build integer list mapping between flattended components
of indexed expression and its underlying tensor-valued subexpression."""
assert isinstance(indexed, Indexed)
# AKA indexed = tensor[multiindex]
tensor, multiindex = indexed.ufl_operands
# AKA e1 = e2[multiindex]
# (this renaming is historical, but kept for consistency with all the variables *1,*2 below)
e2 = tensor
e1 = indexed
# Get tensor and index shape
sh1 = e1.ufl_shape
sh2 = e2.ufl_shape
fi1 = e1.ufl_free_indices
fi2 = e2.ufl_free_indices
fid1 = e1.ufl_index_dimensions
fid2 = e2.ufl_index_dimensions
# Compute regular and total shape
tsh1 = sh1 + fid1
tsh2 = sh2 + fid2
# r1 = len(tsh1)
r2 = len(tsh2)
# str1 = shape_to_strides(tsh1)
str2 = shape_to_strides(tsh2)
assert not sh1
assert sh2 # Must have shape to be indexed in the first place
assert product(tsh1) <= product(tsh2)
# Build map from fi2/fid2 position (-offset nmui) to fi1/fid1 position
ind2_to_ind1_map = [None] * len(fi2)
for k, i in enumerate(fi2):
ind2_to_ind1_map[k] = fi1.index(i)
# Build map from fi1/fid1 position to mi position
nmui = len(multiindex)
multiindex_to_ind1_map = [None] * nmui
for k, i in enumerate(multiindex):
if isinstance(i, Index):
multiindex_to_ind1_map[k] = fi1.index(i.count())
# Build map from flattened e1 component to flattened e2 component
perm1 = compute_indices(tsh1)
ni1 = product(tsh1)
# Situation: e1 = e2[mi]
d1 = [None] * ni1
p2 = [None] * r2
assert len(sh2) == nmui
for k, i in enumerate(multiindex):
if isinstance(i, FixedIndex):
p2[k] = int(i)
for c1, p1 in enumerate(perm1):
for k, i in enumerate(multiindex):
if isinstance(i, Index):
p2[k] = p1[multiindex_to_ind1_map[k]]
for k, i in enumerate(ind2_to_ind1_map):
p2[nmui + k] = p1[i]
c2 = flatten_multiindex(p2, str2)
d1[c1] = c2
# Consistency checks
assert all(isinstance(x, int) for x in d1)
assert len(set(d1)) == len(d1)
return d1
def map_component_tensor_arg_components(tensor):
"""Build integer list mapping between flattended components
of tensor and its underlying indexed subexpression."""
assert isinstance(tensor, ComponentTensor)
# AKA tensor = as_tensor(indexed, multiindex)
indexed, multiindex = tensor.ufl_operands
e1 = indexed
e2 = tensor # e2 = as_tensor(e1, multiindex)
mi = [i for i in multiindex if isinstance(i, Index)]
# Get tensor and index shapes
sh1 = e1.ufl_shape # (sh)ape of e1
sh2 = e2.ufl_shape # (sh)ape of e2
fi1 = e1.ufl_free_indices # (f)ree (i)ndices of e1
fi2 = e2.ufl_free_indices # ...
fid1 = e1.ufl_index_dimensions # (f)ree (i)ndex (d)imensions of e1
fid2 = e2.ufl_index_dimensions # ...
# Compute total shape (tsh) of e1 and e2
tsh1 = sh1 + fid1
tsh2 = sh2 + fid2
r1 = len(tsh1) # 'total rank' or e1
r2 = len(tsh2) # ...
str1 = shape_to_strides(tsh1)
assert not sh1
assert sh2
assert len(mi) == len(multiindex)
assert product(tsh1) == product(tsh2)
assert fi1
assert all(i in fi1 for i in fi2)
nmui = len(multiindex)
assert nmui == len(sh2)
# Build map from fi2/fid2 position (-offset nmui) to fi1/fid1 position
p2_to_p1_map = [None] * r2
for k, i in enumerate(fi2):
p2_to_p1_map[k + nmui] = fi1.index(i)
# Build map from fi1/fid1 position to mi position
for k, i in enumerate(mi):
p2_to_p1_map[k] = fi1.index(mi[k].count())
# Build map from flattened e1 component to flattened e2 component
perm2 = compute_indices(tsh2)
ni2 = product(tsh2)
# Situation: e2 = as_tensor(e1, mi)
d2 = [None] * ni2
p1 = [None] * r1
for c2, p2 in enumerate(perm2):
for k2, k1 in enumerate(p2_to_p1_map):
p1[k1] = p2[k2]
c1 = flatten_multiindex(p1, str1)
d2[c2] = c1
# Consistency checks
assert all(isinstance(x, int) for x in d2)
assert len(set(d2)) == len(d2)
return d2
|