File: _VectorElement.py

package info (click to toggle)
xmds2 2.2.3%2Bdfsg-15
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 53,904 kB
  • sloc: python: 54,093; cpp: 3,929; ansic: 1,463; makefile: 115; sh: 54
file content (203 lines) | stat: -rw-r--r-- 7,194 bytes parent folder | download | duplicates (3)
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
#!/usr/bin/env python
# encoding: utf-8
"""
_VectorElement.py

This contains all the pure-python code for VectorElement.tmpl

Created by Graham Dennis on 2007-10-17.

Copyright (c) 2007-2012, Graham Dennis

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""

from xpdeint.ScriptElement import ScriptElement
from xpdeint.Geometry.FieldElement import FieldElement
from xpdeint.Vectors.VectorInitialisation import VectorInitialisation

from xpdeint.Function import Function
from xpdeint.Utilities import lazy_property

class _VectorElement (ScriptElement):
  isComputed = False
  isNoise = False
  
  def __init__(self, *args, **KWs):
    localKWs = self.extractLocalKWs(['name', 'field', 'initialBasis', 'type'], KWs)
    field = localKWs['field']
    self.name = localKWs['name']
    self.field = field
    if not 'parent' in KWs: KWs['parent'] = field
    
    if KWs['parent'] is field:
      field.managedVectors.add(self)
    else:
      field.temporaryVectors.add(self)
    
    ScriptElement.__init__(self, *args, **KWs)
    
    # Set default variables
    self.components = []
    self._needsInitialisation = True
    self._integratingComponents = False
    self.type = localKWs['type']
    self.aliases = set()
    self.basesNeeded = set()
    self.initialBasis = None
    
    if localKWs.get('initialBasis') is not None:
      self.initialBasis = self.field.basisForBasis(localKWs['initialBasis'])
      self.basesNeeded.add(self.initialBasis)
    
    # Set default initialisation to be the zero initialisation template
    self.initialiser = VectorInitialisation(*args, **KWs)
    self.initialiser.vector = self
    
    intialiseFunctionName = ''.join(['_', self.id, '_initialise'])
    initialiseFunction = Function(name = intialiseFunctionName,
                                  args = [],
                                  implementation = self.initialiseFunctionContents,
                                  description = 'initialisation for ' + self.description(),
                                  predicate = lambda: self.needsInitialisation)
    self.functions['initialise'] = initialiseFunction
    
    basisTransformFunctionName = ''.join(['_', self.id, '_basis_transform'])
    basisTransformFunction = Function(name = basisTransformFunctionName,
                               args = [('ptrdiff_t', 'new_basis')],
                               implementation = self.basisTransformFunctionContents,
                               predicate = lambda: self.needsTransforms)
    self.functions['basisTransform'] = basisTransformFunction
  
  @property
  def dependencies(self):
    try:
      return self.initialiser.codeBlocks['initialisation'].dependencies
    except (AttributeError, KeyError), err:
      return []
  
  @property
  def needsTransforms(self):
    return len(self.basesNeeded) > 1
  
  def __hash__(self):
    """
    Returns a hash of the vector element. This is used to ensure the ordering of vectors in sets remains the same between invocations.
    """
    return hash(self.id)
  
  @lazy_property
  def id(self):
    return ''.join([self.field.name, '_', self.name])
  
  @property
  def children(self):
    children = super(_VectorElement, self).children
    if self.initialiser:
      children.append(self.initialiser)
    return children
  
  @lazy_property
  def nComponents(self):
    return len(self.components)
  
  def _getNeedsInitialisation(self):
    return self._needsInitialisation
  
  def _setNeedsInitialisation(self, value):
    self._needsInitialisation = value
    if not value and self.initialiser:
      self.initialiser.vector = None
      self.initialiser.remove()
      self.initialiser = None
  
  # Create a property for the class with the above getter and setter methods
  needsInitialisation = property(_getNeedsInitialisation, _setNeedsInitialisation)
  del _getNeedsInitialisation, _setNeedsInitialisation
  
  def _getIntegratingComponents(self):
    return self._integratingComponents
  
  def _setIntegratingComponents(self, value):
    self._integratingComponents = value
    # The computed vector only needs initialisation to zero if we are integrating.
    self.needsInitialisation = value
  
  integratingComponents = property(_getIntegratingComponents, _setIntegratingComponents)
  del _getIntegratingComponents, _setIntegratingComponents
  
  
  @lazy_property
  def allocSize(self):
    return '_' + self.id + '_alloc_size'
  
  def sizeInBasis(self, basis):
    return self.field.sizeInBasis(basis) + ' * _' + self.id + '_ncomponents'
  
  def sizeInBasisInReals(self, basis):
    if self.type == 'real':
      return self.sizeInBasis(basis)
    else:
      return '2 * ' + self.sizeInBasis(basis)
  
  def isTransformableTo(self, basis):
    return basis in self.transformMap['bases']
  
  def remove(self):
    self.field.managedVectors.discard(self)
    self.field.temporaryVectors.discard(self)
    
    super(_VectorElement, self).remove()
  
  @property
  def primaryCodeBlock(self):
    try:
      return self.initialiser.codeBlocks['initialisation']
    except (AttributeError, KeyError), err:
      return None
  
  def preflight(self):
    super(_VectorElement, self).preflight()
    
    codeBlock = self.primaryCodeBlock
    if codeBlock:
      loopingDimensionNames = set([dim.name for dim in self.field.dimensions])
      for dependency in codeBlock.dependencies:
        loopingDimensionNames.update([dim.name for dim in dependency.field.dimensions])
    
      codeBlock.field = FieldElement.sortedFieldWithDimensionNames(loopingDimensionNames)
    
      if codeBlock.dependenciesEntity and codeBlock.dependenciesEntity.xmlElement.hasAttribute('basis'):
        dependenciesXMLElement = codeBlock.dependenciesEntity.xmlElement
        codeBlock.basis = \
          codeBlock.field.basisFromString(
            dependenciesXMLElement.getAttribute('basis'),
            xmlElement = dependenciesXMLElement
          )
      
      # Because we have modified the codeBlock's field, we may also need to modify its basis.
      # We will take any missing elements from the new field's defaultCoordinateBasis
      codeBlock.basis = codeBlock.field.completedBasisForBasis(codeBlock.basis, codeBlock.field.defaultCoordinateBasis)
      
      self.initialBasis = self.field.basisForBasis(codeBlock.basis)
      self.basesNeeded.add(self.initialBasis)
    
      # Our components are constructed by an integral if the looping field doesn't have the same
      # dimensions as the field to which the computed vector belongs.
      if not codeBlock.field.isEquivalentToField(self.field):
        self.integratingComponents = True