This file is indexed.

/usr/lib/python-escript-mpi/esys/escriptcore/splitworld.py is in python-escript-mpi 5.1-5.

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
##############################################################################
#
# Copyright (c) 2014-2017 by The University of Queensland
# http://www.uq.edu.au
#
# Primary Business: Queensland, Australia
# Licensed under the Apache License, version 2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Development until 2012 by Earth Systems Science Computational Center (ESSCC)
# Development 2012-2013 by School of Earth Sciences
# Development from 2014 by Centre for Geoscience Computing (GeoComp)
#
##############################################################################

from __future__ import print_function, division

__copyright__="""Copyright (c) 2014-2017 by The University of Queensland
http://www.uq.edu.au
Primary Business: Queensland, Australia"""
__license__="""Licensed under the Apache License, version 2.0
http://www.apache.org/licenses/LICENSE-2.0"""
__url__="https://launchpad.net/escript-finley"

__author__="Joel Fenwick"

"""
This module contains the Python side of the SplitWorld functionality.
"""

import warnings
warnings.simplefilter('default', category=DeprecationWarning)

from . import escriptcpp as escore


class SplitWorld(object):
  """
  Wrapper for the C++ class exposed as __SplitWorld.
  This is a namespace consideration, it allows us to make 
  boost::python::raw_functions into members of a class.
  """
  
  def __init__(self, count):
    """
    :var count: How many equally sized subworlds should our compute resources be partitioned into?
    :var type: `int`
    """
    self.cpp_obj=escore.Internal_SplitWorld(count)
    
  def buildDomains(self, fn, *vec, **kwargs):
    """
    Instruct subworlds how to build the domain.
    :var fn: The function/class to call to create a domain.
    :type fn: `callable`
    The remaining parameters are for the arguments of the function.
    """
    escore.internal_buildDomains(self.cpp_obj, fn, *vec, **kwargs)

    
  def addJob(self, jobctr, *vec, **kwargs):
    """
    Submit a job to be run later on an available subworld.
    :var jobctr: class or function to be called to create a job
    :type jobctr: `callable`
    The remaining parameters are for the arguments of the function.
    """
    escore.internal_addJob(self.cpp_obj, jobctr, *vec, **kwargs)
    
  def addJobPerWorld(self, jobctr, *vec, **kwargs):
    """
    Submit one job per subworld to run later.
    :var jobctr: class or function to be called to create a job
    :type jobctr: `callable`
    The remaining parameters are for the arguments of the function.    
    """
    escore.internal_addJobPerWorld(self.cpp_obj, jobctr,  *vec, **kwargs)
    
    
  def addVariable(self, vname, vartype, *vec, **kwargs):
    """
    Create a variable on all subworlds.
    :var vartype: the type of variable to be created
    :type vartype: `str`
    The remaining parameters are for optional arguments depending on the variable type.
    """
    if vartype=="local":
        escore.internal_addVariable(self.cpp_obj, vname, escore.internal_makeLocalOnly);
    elif vartype=="Data":
        escore.internal_addVariable(self.cpp_obj, vname, escore.internal_makeDataReducer, *vec)
    elif vartype=="float":
        escore.internal_addVariable(self.cpp_obj, vname, escore.internal_makeScalarReducer, *vec)
    else:
        raise ValueError("Unknown variable type (%s)"%str(vartype))

  def runJobs(self):
    """
    Executes pending jobs.
    """
    self.cpp_obj.runJobs()

  def removeVariable(self, name):
    """
    Removes the named variable from all subworlds.
    :var name: 
    :type name: `str`
    """
    self.cpp_obj.removeVariable(name)
    
    
  def clearVariable(self, name):
    """
    Clears the value of the named variable.  The variable itself still exists.
    :var name: variable to clear
    :type name: `str`
    """
    self.cpp_obj.clearVariable(name)
    
  def getVarList(self):
    """
    Returns the names of all declared variables and a boolean for each indicating whether they have values.
    """
    return self.cpp_obj.getVarList()
  
  
  def getVarInfo(self):
    """
    Returns the names of all declared variables and a description of type.
    The details of the output are not fixed and may change without notice
    """
    return self.cpp_obj.getVarInfo()
    
    
  def getFloatVariable(self, vname):
    """
    Return the value of a floating point variable
    """
    return self.cpp_obj.getDoubleVariable(vname)
  
  
  def getLocalObjectVariable(self, vname):
    """
    Return the value of a local object variable - that is, an object (eg tuple) which does not need to
    be reduced/shared between worlds
    """
    return self.cpp_obj.getLocalObjectVariable(vname)
    
  def getSubWorldCount(self):
    """
    Return the number of subworlds in this splitworld
    """
    return self.cpp_obj.getSubWorldCount()

  def getSubWorldID(self):
    """
    Return the id of the subworld which _this_ MPI process belongs to.
    """
    return self.cpp_obj.getSubWorldID()
    
    
  def copyVariable(self, src, dest):
    """
    copy the contents of one splitworld variable into another
    :var src: name of variable to copy from
    :type src: `str`
    :var dest: name of variable to copy to 
    :type dest: `str`
    """
    self.cpp_obj.copyVariable(src, dest)
    
class Job(object):
  """
  Describes a sequence of work to be carried out in a subworld.
  The instances of this class used in the subworlds will
  be constructed by the system.
  The majority of the work done by the Job will be in the 
  *overloaded* work() method.
  To do specific work, this class should be subclassed and the work() 
  (and possibly __init__ methods overloaded).
  The majority of the work done by the job will be in the *overloaded* work() method.
  The work() method should retrieve values from the outside using importValue() and pass values to
  the rest of the system using exportValue().
  The rest of the methods should be considered off limits.
  """

  def __init__(self, *args, **kwargs):
    """
    It ignores all of its parameters, except, it requires the following as keyword arguments
    :var domain: Domain to be used as the basis for all ``Data`` and PDEs in this Job.
    :var jobid: sequence number of this job. The first job has id=1
    :type jobid: Positive ``int``
    """
    self.domain=kwargs["domain"]
    self.jobid=kwargs["jobid"]
    self.wantedvalues=[]                # names of shared values this job wishes to import    
    self.importedvalues={}      # name:values of which this jobs wants to use
    self.exportedvalues={}      # name:values exported by this job
    self.swcount=kwargs["swcount"]      # How many subworlds are there?
    self.swid=kwargs["swid"]    # which subworld are we running in?
    
    
    
  def setImportValue(self, name, v):
    """
    Use to make a value available to the job (ie called from outside the job)
    :var name: label used to identify this import
    :type name: ``str``
    :var v: value to be imported
    :type v: python object
    """
    self.importedvalues[name]=v
        
  def exportValue(self, name, v):
    """
    Make value v available to other Jobs under the label name.
    name must have already been registered with the SplitWorld instance.
    For use inside the work() method.
    :var name: registered label for exported value
    :type name: ``str``
    :var v: value to be imported
    :type v: python object
    """
    if type(name)==type([]):
        for x in name:
          if type(x)!=type(""):
            raise RuntimeError("Variable name must be a string or list of strings- instead got [%s]"%(str(type(x))))
    elif type(name)!=type(""):
      raise RuntimeError("Variable name must be a string or list of strings- instead got %s"%(str(type(name))))
    self.exportedvalues[name]=v
    
  def importValue(self, name):
    """
    For use inside the work() method.
    :var name: label for imported value.
    :type name: ``str``
    """
    if name in self.importedvalues:
        return self.importedvalues[name]
    else:
        raise KeyError("Attempt to import variable \'"+name+"\' which is not available to this job.")
        return None

  def clearExports(self):
    """
    Remove exported values from the map
    """
    self.exportedvalues.clear()
    
  def clearImports(self):
    """
    Remove imported values from their map
    """
    self.importedvalues.clear()
    
  def declareImport(self, name):
    """
    Adds name to the list of imports
    """
    if (not isinstance(name, str)) or len(name)==0:
      raise ValueError("Imports must be identified with non-empty strings")
    if not name in self.wantedvalues:
      self.wantedvalues+=name

  def work(self):
    """
    Need to be overloaded for the job to actually do anthing.
    A return value of True indicates this job thinks it is done.
    A return value of False indicates work still to be done
    """
    raise RuntimeError("work() function not overridden as required")

class FunctionJob(Job):
  """
  Takes a python function (with only self and keyword params) to be called as the work method
  """
  def __init__(self, fn, *args, **kwargs):
    super(FunctionJob, self).__init__(*args, **kwargs)
    self.__fn__ = fn
    if fn is None:
      raise ValueError("Attempt to create a Function Job with no function to run (fn argument missing).")
    self.__calldict__ = kwargs
    if "imports" in kwargs:
      if isinstance(kwargs["imports"], str):
        self.declareImport(kwargs["imports"])
      else:
        for n in kwargs["imports"]:
          self.declareImport(n)

  def work(self):
    self.__fn__(self, **self.__calldict__)
    return True