/[escript]/trunk/escript/py_src/util.py
ViewVC logotype

Diff of /trunk/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3974 by jfenwick, Thu Jun 14 01:01:03 2012 UTC revision 3975 by caltinay, Thu Sep 20 01:54:06 2012 UTC
# Line 45  from esys.escript import getVersion, get Line 45  from esys.escript import getVersion, get
45  from esys.escript import printParallelThreadCounts  from esys.escript import printParallelThreadCounts
46  from esys.escript import listEscriptParams  from esys.escript import listEscriptParams
47  from esys.escript.escriptcpp import Data, _saveDataCSV, _condEval  from esys.escript.escriptcpp import Data, _saveDataCSV, _condEval
48    from esys.escript.symbolic import *
49    
50  #=========================================================  #=========================================================
51  #   some helpers:  #   some helpers:
# Line 129  def interpolateTable(tab, dat, start, st Line 130  def interpolateTable(tab, dat, start, st
130      if dim==2:      if dim==2:
131          d1=dat[1]          d1=dat[1]
132          return firstdim.interpolateTable(tab, start[0], step[0], d1, start[1], step[1], undef, check_boundaries)          return firstdim.interpolateTable(tab, start[0], step[0], d1, start[1], step[1], undef, check_boundaries)
133  #   return d1.interpolateTable(tab, start[1], step[1], firstdim, start[0], step[0], undef, check_boundaries)  #   return d1.interpolateTable(tab, start[1], step[1], firstdim, start[0], step[0], undef, check_boundaries)
134      else:      else:
135          return firstdim.interpolateTable(tab, start[0], step[0], undef, check_boundaries)          return firstdim.interpolateTable(tab, start[0], step[0], undef, check_boundaries)
136    
# Line 178  def saveDataCSV(filename, append=False, Line 179  def saveDataCSV(filename, append=False,
179      new_data={}      new_data={}
180      for n,d in list(data.items()):      for n,d in list(data.items()):
181          if isinstance(d, Data):          if isinstance(d, Data):
182              new_data[n]=d              new_data[n]=d
183          else:          else:
184              try:              try:
185                 new_data[n]=Data(d,fs)                 new_data[n]=Data(d,fs)
# Line 456  def unitVector(i=0,d=3): Line 457  def unitVector(i=0,d=3):
457     return kronecker(d)[i]     return kronecker(d)[i]
458    
459  #=========================================================================  #=========================================================================
460  #   global reduction operations (these functions have no symbolic version)  #   global reduction operations
461  #=========================================================================  #=========================================================================
462  def Lsup(arg):  def Lsup(arg):
463      """      """
# Line 479  def Lsup(arg): Line 480  def Lsup(arg):
480      elif isinstance(arg,int):      elif isinstance(arg,int):
481          return abs(float(arg))          return abs(float(arg))
482      else:      else:
483        raise TypeError("Lsup: Unknown argument type.")          raise TypeError("Lsup: Unknown argument type.")
484    
485  def sup(arg):  def sup(arg):
486      """      """
# Line 500  def sup(arg): Line 501  def sup(arg):
501      elif isinstance(arg,int):      elif isinstance(arg,int):
502          return float(arg)          return float(arg)
503      else:      else:
504        raise TypeError("sup: Unknown argument type.")          raise TypeError("sup: Unknown argument type.")
505    
506  def inf(arg):  def inf(arg):
507      """      """
# Line 591  def pokeDim(arg): Line 592  def pokeDim(arg):
592    
593      if isinstance(arg,escript.Data):      if isinstance(arg,escript.Data):
594          return arg.getFunctionSpace().getDim()          return arg.getFunctionSpace().getDim()
     elif isinstance(arg,Symbol):  
         return arg.getDim()  
595      else:      else:
596          return None          return None
597    
# Line 663  def testForZero(arg): Line 662  def testForZero(arg):
662         return not Lsup(arg)>0.         return not Lsup(arg)>0.
663      elif isinstance(arg,int):      elif isinstance(arg,int):
664         return not Lsup(arg)>0.         return not Lsup(arg)>0.
     elif isinstance(arg,Symbol):  
        return False  
665      else:      else:
666         return False         return False
667    
668  def matchType(arg0=0.,arg1=0.):  def matchType(arg0=0.,arg1=0.):
669      """      """
670      Converts ``arg0`` and ``arg1`` both to the same type ``numpy.ndarray`` or      Converts ``arg0`` and ``arg1`` both to the same type ``numpy.ndarray`` or
671      `escript.Data` or, if one of ``arg0`` or ``arg1`` is of type `Symbol`, the      `escript.Data`
     other one to be of type ``numpy.ndarray`` or `escript.Data`.  
672    
673      :param arg0: first argument      :param arg0: first argument
674      :type arg0: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``      :type arg0: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``
675      :param arg1: second argument      :param arg1: second argument
676      :type arg1: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``      :type arg1: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``
677      :return: a tuple representing ``arg0`` and ``arg1`` with the same type or      :return: a tuple representing ``arg0`` and ``arg1`` with the same type or
678               with one of them being a `Symbol`               with at least one of them being a `Symbol`
679      :rtype: ``tuple`` of two ``numpy.ndarray``, two `escript.Data`,      :rtype: ``tuple`` of two ``numpy.ndarray`` or two `escript.Data`
             a ``Symbol`` and one of the types ``numpy.ndarray`` or  
             `escript.Data`  
680      :raise TypeError: if type of ``arg0`` or ``arg1`` cannot be processed      :raise TypeError: if type of ``arg0`` or ``arg1`` cannot be processed
681      """      """
682      if isinstance(arg0,numpy.ndarray):      if isinstance(arg0,numpy.ndarray):
# Line 717  def matchType(arg0=0.,arg1=0.): Line 711  def matchType(arg0=0.,arg1=0.):
711         elif isinstance(arg1,escript.Data):         elif isinstance(arg1,escript.Data):
712            pass            pass
713         elif isinstance(arg1,float):         elif isinstance(arg1,float):
714            arg1=numpy.array(arg1,dtype=numpy.float64)            pass
715         elif isinstance(arg1,int):         elif isinstance(arg1,int):
716            arg1=numpy.array(float(arg1),dtype=numpy.float64)            pass
717         elif isinstance(arg1,Symbol):         elif isinstance(arg1,Symbol):
718            pass            pass
719         else:         else:
# Line 736  def matchType(arg0=0.,arg1=0.): Line 730  def matchType(arg0=0.,arg1=0.):
730            arg0=numpy.array(arg0,dtype=numpy.float64)            arg0=numpy.array(arg0,dtype=numpy.float64)
731            arg1=numpy.array(float(arg1),dtype=numpy.float64)            arg1=numpy.array(float(arg1),dtype=numpy.float64)
732         elif isinstance(arg1,Symbol):         elif isinstance(arg1,Symbol):
733            arg0=numpy.array(arg0,dtype=numpy.float64)            pass
734         else:         else:
735            raise TypeError("function: Unknown type of second argument.")            raise TypeError("function: Unknown type of second argument.")
736      elif isinstance(arg0,int):      elif isinstance(arg0,int):
# Line 751  def matchType(arg0=0.,arg1=0.): Line 745  def matchType(arg0=0.,arg1=0.):
745            arg0=numpy.array(float(arg0),dtype=numpy.float64)            arg0=numpy.array(float(arg0),dtype=numpy.float64)
746            arg1=numpy.array(float(arg1),dtype=numpy.float64)            arg1=numpy.array(float(arg1),dtype=numpy.float64)
747         elif isinstance(arg1,Symbol):         elif isinstance(arg1,Symbol):
748            arg0=numpy.array(float(arg0),dtype=numpy.float64)            pass
749         else:         else:
750            raise TypeError("function: Unknown type of second argument.")            raise TypeError("function: Unknown type of second argument.")
751      else:      else:
# Line 781  def matchShape(arg0,arg1): Line 775  def matchShape(arg0,arg1):
775      else:      else:
776         return arg0,arg1         return arg0,arg1
777    
 #=========================================================  
 #   symbolic tool box starts here:  
 #=========================================================  
 class Symbol(object):  
    """  
    Symbol class objects provide the same functionality as ``numpy.ndarray``  
    and `escript.Data` objects but they do not have a value and therefore  
    cannot be plotted or visualized. The main purpose is the possibility to  
    calculate derivatives with respect to other Symbols used to define a Symbol.  
   
    """  
    def __init__(self,shape=(),args=[],dim=None):  
        """  
        Creates an instance of a symbol of a given shape. The symbol may depend  
        on a list of arguments ``args`` which may be symbols or any other object.  
   
        :param args: the arguments of the symbol  
        :type args: ``list``  
        :param shape: the shape of the symbol  
        :type shape: ``tuple`` of ``int``  
        :param dim: spatial dimension of the symbol. If dim=``None`` the spatial  
                    dimension is undefined.  
        :type dim: ``None`` or ``int``  
   
        """  
        if len(shape)>4:  
            raise ValueError("Symbol only supports tensors up to order 4")  
        self.__args=args  
        self.__shape=shape  
        self.__dim=dim  
   
    def getArgument(self,i=None):  
        """  
        Returns the i-th argument of the symbol.  
   
        :param i: index of the argument requested  
        :type i: ``int`` or ``None``  
        :raise IndexError: if the requested index does not exist  
        :return: the value of the i-th argument or if i is not specified the  
                 list of all arguments  
        :rtype: a single object or a list of objects  
        """  
        if i==None:  
           return self.__args  
        else:  
           if i<0 or i>=len(self.__args):  
              raise IndexError("there are only %s arguments"%len(self.__args))  
           return self.__args[i]  
   
    def getRank(self):  
        """  
        Returns the rank of the symbol.  
   
        :return: the rank of the symbol. This is length of the shape.  
        :rtype: ``int``  
        """  
        return len(self.getShape())  
   
    def getShape(self):  
        """  
        Returns the shape of the symbol.  
   
        :return: the shape of the symbol  
        :rtype: ``tuple`` of ``int``  
        """  
        return self.__shape  
   
    def getDim(self):  
        """  
        Returns the spatial dimension.  
   
        :return: the symbol's spatial dimension  
        :rtype: ``int`` if the dimension is defined, ``None`` otherwise  
        """  
        return self.__dim  
   
    def __str__(self):  
        """  
        Returns a string representation of the symbol.  
   
        :return: a string representation of the object  
        :rtype: ``str``  
        """  
        args=[]  
        for arg in self.getArgument():  
           args.append(str(arg))  
        try:  
            out=self.getMyCode(args,format="str")  
        except NotImplementedError:  
            out="<Symbol %s>"%id(self)  
        return out  
   
    def getSubstitutedArguments(self,argvals):  
        """  
        Substitutes symbols in the arguments of this object and returns the  
        result as a list.  
   
        :param argvals: `Symbol` and their substitutes. The `Symbol` u in the  
                        expression defining this object is replaced by  
                        argvals[u].  
        :type argvals: ``dict`` with keywords of type `Symbol`  
        :rtype: ``list`` of objects  
        :return: list of the object assigned to the arguments through  
                 substitution or for the arguments which are not `Symbol` s the  
                 value assigned to the argument at instantiation.  
        """  
        out=[]  
        for a in self.getArgument():  
           if isinstance(a,Symbol):  
              out.append(a.substitute(argvals))  
           else:  
              out.append(a)  
        return out  
   
    def getDifferentiatedArguments(self,arg):  
        """  
        Applies differentials to the arguments of this object and returns the  
        result as a list.  
   
        :param arg: the derivative is calculated with respect to ``arg``  
        :type arg: typically `escript.Symbol` but can also be ``float``,  
                   `escript.Data`, ``numpy.ndarray`` depending on the  
                   involved functions and data  
        :rtype: ``list`` of objects  
        :return: list of object obtained by calculating the derivatives of the  
                 arguments with respect to ``arg``  
        """  
        out=[]  
        for a in self.getArgument():  
           if isinstance(a,Symbol):  
              out.append(a.substitute(argvals))  
           else:  
               s=getShape(s)+arg.getShape()  
               if len(s)>0:  
                  out.append(numpy.zeros(s),numpy.float64)  
               else:  
                  out.append(a)  
        return out  
   
    def isAppropriateValue(self,arg):  
       """  
       Checks if the given argument ``arg`` can be used as a substitution for  
       this object. The method checks the shape of ``arg`` and, if the spatial  
       dimension is defined, the spatial dimension of ``arg``.  
   
       :param arg: object to be checked  
       :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,  
                  ``Symbol``  
       :return: True if ``arg`` is a suitable object to be used for substitution,  
                False otherwise  
       :rtype: ``bool``  
       """  
       if isinstance(arg,numpy.ndarray):  
           return arg.shape==self.getShape()  
       elif isinstance(arg,escript.Data):  
           if self.getDim()==None:  
               return arg.getShape()==self.getShape()  
           elif self.getDim()==arg.getFunctionSpace().getDim():  
               return arg.getShape()==self.getShape()  
           else:  
               return False  
       elif isinstance(arg,Symbol):  
           if self.getDim()==None:  
               return arg.getShape()==self.getShape()  
           elif self.getDim()==arg.getDim():  
               return arg.getShape()==self.getShape()  
           else:  
               return False  
       elif isinstance(arg,float):  
           return ()==self.getShape()  
       elif isinstance(arg,int):  
           return ()==self.getShape()  
       else:  
          return False  
   
    def getMyCode(self,argstrs,format="escript"):  
        """  
        Returns program code that can be used to evaluate the symbol.  
   
        :param argstrs: a string for each argument representing the argument  
                        for the evaluation  
        :type argstrs: ``list`` of ``str``  
        :param format: specifies the format to be used. At the moment only  
                       "escript", "str" and "text" are supported.  
        :type format: ``str``  
        :return: a piece of program code which can be used to evaluate the  
                 expression assuming the values for the arguments are available  
        :rtype: ``str``  
        :raise NotImplementedError: if no implementation for the given format  
                                    is available  
        :note: This method has to be overwritten by subclasses.  
        """  
        raise NotImplementedError("no code for %s representation available"%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
   
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :note: this method has to be overwritten by a particular `Symbol`  
       :raise NotImplementedError: if no implementation for the given format is  
                                   available  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("Symbol: new value is not appropriate.")  
       else:  
          raise NotImplementedError("no substitution in %s avialable"%str(self))  
   
    def diff(self,arg):  
        """  
        Returns the derivative of the symbol with respect to `Symbol` ``arg``.  
   
        :param arg: the derivative is calculated with respect to ``arg``  
        :type arg: typically `escript.Symbol` but can also be ``float``,  
                   `escript.Data`, ``numpy.ndarray`` depending on the  
                   involved functions and data  
        :return: derivative with respect to ``arg``  
        :rtype: typically `escript.Symbol` but other types such as ``float``,  
                `escript.Data`, ``numpy.ndarray`` are possible  
        :note: this method is overwritten by a particular `Symbol`.  
        """  
        if arg==self:  
           return identity(self.getShape())  
        else:  
           s=self.getShape()+arg.getShape()  
           if len(s)>0:  
              return numpy.zeros(s,numpy.float64)  
           else:  
              return 0.  
   
    def __neg__(self):  
        """  
        Returns -self.  
   
        :return: a `Symbol` representing the negative of the object  
        :rtype: `DependendSymbol`  
        """  
        return self*(-1.)  
   
    def __pos__(self):  
        """  
        Returns +self.  
   
        :return: a `Symbol` representing the positive of the object  
        :rtype: `DependendSymbol`  
        """  
        return self*(1.)  
   
    def __abs__(self):  
        """  
        Returns a `Symbol` representing the absolute value of the object.  
        """  
        return Abs_Symbol(self)  
   
    def __add__(self,other):  
        """  
        Adds another object to this object.  
   
        :param other: object to be added to this object  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``.  
        :return: a `Symbol` representing the sum of this object and ``other``  
        :rtype: `DependendSymbol`  
        """  
        return add(self,other)  
   
    def __radd__(self,other):  
        """  
        Adds this object to another object.  
   
        :param other: object to add this object to  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the sum of ``other`` and this object  
        :rtype: `DependendSymbol`  
        """  
        return add(other,self)  
   
    def __sub__(self,other):  
        """  
        Subtracts another object from this object.  
   
        :param other: object to be subtracted from this object  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the difference of ``other`` and this  
                 object  
        :rtype: `DependendSymbol`  
        """  
        return add(self,-other)  
   
    def __rsub__(self,other):  
        """  
        Subtracts this object from another object.  
   
        :param other: object this object is to be subtracted from  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the difference of this object and  
                 ``other``.  
        :rtype: `DependendSymbol`  
        """  
        return add(-self,other)  
   
    def __mul__(self,other):  
        """  
        Multiplies this object with another object.  
   
        :param other: object to be mutiplied by this object  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the product of the object and ``other``  
        :rtype: `DependendSymbol` or 0 if other is identical to zero.  
        """  
        return mult(self,other)  
   
    def __rmul__(self,other):  
        """  
        Multiplies another object by this object.  
   
        :param other: object this object is multiplied with  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the product of ``other`` and the object  
        :rtype: `DependendSymbol` or 0 if other is identical to zero  
        """  
        return mult(other,self)  
   
    def __div__(self,other):  
        """  
        Divides this object by another object.  
   
        :param other: object dividing this object  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the quotient of this object and  
                 ``other``  
        :rtype: `DependendSymbol`  
        """  
        return quotient(self,other)  
   
    def __truediv__(self,other):  
        return self.__div__(other)  
   
    def __rdiv__(self,other):  
        """  
        Divides another object by this object.  
   
        :param other: object to be divided by this object  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the quotient of ``other`` and this  
                 object  
        :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero  
        """  
        return quotient(other,self)  
   
    def __rtruediv__(self,other):  
        return self.__rdiv__(other)  
   
    def __pow__(self,other):  
        """  
        Raises this object to the power of ``other``.  
   
        :param other: exponent  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the power of this object to ``other``  
        :rtype: `DependendSymbol` or 1 if ``other`` is identical to zero  
        """  
        return power(self,other)  
   
    def __rpow__(self,other):  
        """  
        Raises an object to the power of this object.  
   
        :param other: basis  
        :type other: `escript.Symbol`, ``float``, `escript.Data`,  
                     ``numpy.ndarray``  
        :return: a `Symbol` representing the power of ``other`` to this object  
        :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero  
        """  
        return power(other,self)  
   
    def __getitem__(self,index):  
        """  
        Returns the slice defined by ``index``.  
   
        :param index: the slice index  
        :type index: ``slice`` or ``int`` or a ``tuple`` of them  
        :return: a `Symbol` representing the slice defined by index  
        :rtype: `DependendSymbol`  
        """  
        return GetSlice_Symbol(self,index)  
   
 class DependendSymbol(Symbol):  
    """  
    DependendSymbol extents `Symbol` by modifying the == operator to allow two  
    instances to be equal. Two ``DependendSymbol`` s are equal if they have the  
    same shape, the same arguments and one of them has an unspecified spatial  
    dimension or the spatial dimension is identical.  
   
    Example::  
   
      u1=Symbol(shape=(3,4),dim=2,args=[4.])  
      u2=Symbol(shape=(3,4),dim=2,args=[4.])  
      print u1==u2  
      False  
   
    but::  
   
      u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])  
      u2=DependendSymbol(shape=(3,4),dim=2,args=[4.])  
      u3=DependendSymbol(shape=(2,),dim=2,args=[4.])  
      print u1==u2, u1==u3  
      True False  
   
    :note: DependendSymbol should be used as return value of functions with  
           `Symbol` arguments. This will allow the optimizer to remove  
           redundant function calls.  
    """  
   
    def __hash__(self):  
        return hash(self.getShape()) ^ hash(self.getDim()) ^ len(self.getArgument())  
   
    def __eq__(self,other):  
       """  
       Checks if ``other`` equals self.  
   
       :param other: any object  
       :return: True if other has the same class as self and the shape, the  
                spatial dimension and the arguments are equal, False otherwise  
       :rtype: ``bool``  
       """  
       if isinstance(other,DependendSymbol):  
          if self.__class__==other.__class__:  
             if self.getShape()==other.getShape():  
                if self.getArgument()==other.getArgument():  
                   if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():  
                      return True  
       return False  
   
    def __ne__(self,other):  
       """  
       Checks if ``other`` is not equal to self.  
   
       :param other: any object  
       :return: False if other has the same class as self and the shape, the  
                spatial dimension and the arguments are equal, True otherwise  
       :rtype: ``bool``  
       """  
       return not self==other  
 #=========================================================  
 #  Unary operations preserving the shape  
 #========================================================  
 class GetSlice_Symbol(DependendSymbol):  
    """  
    `Symbol` representing getting a slice for a `Symbol`.  
    """  
    def __init__(self,arg,index):  
       """  
       Initialization of the `Symbol` with argument ``arg``.  
   
       :param arg: argument  
       :type arg: `Symbol`  
       :param index: defines index  
       :type index: ``slice`` or ``int`` or a ``tuple`` of them  
       :raise IndexError: if length of index is larger than rank of arg or  
                           index start or stop is out of range  
       :raise ValueError: if a step is given  
       """  
       if not isinstance(index,tuple): index=(index,)  
       if len(index)>arg.getRank():  
            raise IndexError("GetSlice_Symbol: index out of range.")  
       sh=()  
       index2=()  
       for i in range(len(index)):  
          ix=index[i]  
          if isinstance(ix,int):  
             if ix<0 or ix>=arg.getShape()[i]:  
                raise IndexError("GetSlice_Symbol: index out of range.")  
             index2=index2+(ix,)  
          else:  
            if not ix.step==None:  
              raise ValueError("GetSlice_Symbol: stepping is not supported.")  
            if ix.start==None:  
               s=0  
            else:  
               s=ix.start  
            if ix.stop==None:  
               e=arg.getShape()[i]  
            else:  
               e=ix.stop  
               if e>arg.getShape()[i]:  
                  raise IndexError("GetSlice_Symbol: index out of range.")  
            index2=index2+(slice(s,e),)  
            if e>s:  
                sh=sh+(e-s,)  
            elif s>e:  
                raise IndexError("GetSlice_Symbol: slice start must be less or equal slice end")  
       for i in range(len(index),arg.getRank()):  
           index2=index2+(slice(0,arg.getShape()[i]),)  
           sh=sh+(arg.getShape()[i],)  
       super(GetSlice_Symbol, self).__init__(args=[arg,index2],shape=sh,dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "%s.__getitem__(%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("GetItem_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          arg=args[0]  
          index=args[1]  
          return arg.__getitem__(index)  
   
778  def log10(arg):  def log10(arg):
779     """     """
780     Returns base-10 logarithm of argument ``arg``.     Returns base-10 logarithm of argument ``arg``.
# Line 1365  def log10(arg): Line 794  def log10(arg):
794     elif isinstance(arg,int):     elif isinstance(arg,int):
795        return math.log10(float(arg))        return math.log10(float(arg))
796     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
797        return log(arg)/log(10.)        return arg.applyfunc(symfn.log10)
798     else:     else:
799        raise TypeError("log10: Unknown argument type.")        raise TypeError("log10: Unknown argument type.")
800    
# Line 1396  def wherePositive(arg): Line 825  def wherePositive(arg):
825        else:        else:
826          return 0.          return 0.
827     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
828        return WherePositive_Symbol(arg)        return arg.applyfunc(symfn.wherePositive)
829     else:     else:
830        raise TypeError("wherePositive: Unknown argument type.")        raise TypeError("wherePositive: Unknown argument type.")
831    
 class WherePositive_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the mask of positive values function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of wherePositive `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "wherePositive(%s)"%argstrs  
       else:  
          raise NotImplementedError("WherePositive_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return wherePositive(arg)  
   
832  def whereNegative(arg):  def whereNegative(arg):
833     """     """
834     Returns mask of negative values of argument ``arg``.     Returns mask of negative values of argument ``arg``.
# Line 1487  def whereNegative(arg): Line 856  def whereNegative(arg):
856        else:        else:
857          return 0.          return 0.
858     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
859        return WhereNegative_Symbol(arg)        return arg.applyfunc(symfn.whereNegative)
860     else:     else:
861        raise TypeError("whereNegative: Unknown argument type.")        raise TypeError("whereNegative: Unknown argument type.")
862    
 class WhereNegative_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the mask of negative values function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of whereNegative `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "whereNegative(%s)"%argstrs  
       else:  
          raise NotImplementedError("WhereNegative_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return whereNegative(arg)  
   
863  def whereNonNegative(arg):  def whereNonNegative(arg):
864     """     """
865     Returns mask of non-negative values of argument ``arg``.     Returns mask of non-negative values of argument ``arg``.
# Line 1578  def whereNonNegative(arg): Line 887  def whereNonNegative(arg):
887        else:        else:
888          return 1.          return 1.
889     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
890        return 1.-whereNegative(arg)        return arg.applyfunc(symfn.whereNonNegative)
891     else:     else:
892        raise TypeError("whereNonNegative: Unknown argument type.")        raise TypeError("whereNonNegative: Unknown argument type.")
893    
# Line 1609  def whereNonPositive(arg): Line 918  def whereNonPositive(arg):
918        else:        else:
919          return 1.          return 1.
920     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
921        return 1.-wherePositive(arg)        return arg.applyfunc(symfn.whereNonPositive)
922     else:     else:
923        raise TypeError("whereNonPositive: Unknown argument type.")        raise TypeError("whereNonPositive: Unknown argument type.")
924    
# Line 1618  def whereZero(arg,tol=None,rtol=math.sqr Line 927  def whereZero(arg,tol=None,rtol=math.sqr
927     Returns mask of zero entries of argument ``arg``.     Returns mask of zero entries of argument ``arg``.
928    
929     :param arg: argument     :param arg: argument
930     :type arg: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray``     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
931     :param tol: absolute tolerance. Values with absolute value less than tol are accepted     :param tol: absolute tolerance. Values with absolute value less than tol are accepted
932                 as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.                 as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
933     :type tol: ``float``     :type tol: ``float``
934     :param rtol: relative tolerance used to define the absolute tolerance if ``tol`` is not present.     :param rtol: relative tolerance used to define the absolute tolerance if ``tol`` is not present.
935     :type rtol: non-negative ``float``     :type rtol: non-negative ``float``
936     :rtype: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray`` depending     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
937             on the type of ``arg``             on the type of ``arg``
938     :raise ValueError: if ``rtol`` is non-negative.     :raise ValueError: if ``rtol`` is non-negative.
939     :raise TypeError: if the type of the argument is not expected     :raise TypeError: if the type of the argument is not expected
940     """     """
941     if tol == None:     if tol is None and not isinstance(arg, Symbol):
942        if not isinstance(arg,Symbol):        if rtol<0: raise ValueError("rtol must be non-negative.")
943           if rtol<0: raise ValueError("rtol must be non-negative.")        tol = Lsup(arg)*rtol
          tol = Lsup(arg)*rtol  
       else:  
          tol=0.  
944     if isinstance(arg,numpy.ndarray):     if isinstance(arg,numpy.ndarray):
945        out=numpy.less_equal(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.        out=numpy.less_equal(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
946        if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)        if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
# Line 1652  def whereZero(arg,tol=None,rtol=math.sqr Line 958  def whereZero(arg,tol=None,rtol=math.sqr
958        else:        else:
959          return 0.          return 0.
960     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
961        return WhereZero_Symbol(arg,tol)        return arg.applyfunc(symfn.whereZero)
962     else:     else:
963        raise TypeError("whereZero: Unknown argument type.")        raise TypeError("whereZero: Unknown argument type.")
964    
 class WhereZero_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the mask of zero entries function.  
    """  
    def __init__(self,arg,tol=0.):  
       """  
       Initialization of whereZero `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("WhereZero_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return whereZero(arg[0],arg[1])  
   
965  def whereNonZero(arg,tol=0.):  def whereNonZero(arg,tol=0.):
966     """     """
967     Returns mask of values different from zero of argument ``arg``.     Returns mask of values different from zero of argument ``arg``.
# Line 1729  def whereNonZero(arg,tol=0.): Line 977  def whereNonZero(arg,tol=0.):
977     :raise TypeError: if the type of the argument is not expected     :raise TypeError: if the type of the argument is not expected
978     """     """
979     if tol == None:     if tol == None:
980        if not isinstance(arg,Symbol):        if rtol<=0: raise ValueError("rtol must be non-negative.")
981           if rtol<=0: raise ValueError("rtol must be non-negative.")        tol = Lsup(arg)*rtol
          tol = Lsup(arg)*rtol  
       else:  
          tol=0.  
982     if isinstance(arg,numpy.ndarray):     if isinstance(arg,numpy.ndarray):
983        out=numpy.greater(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.        out=numpy.greater(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
984        if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)        if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
# Line 1751  def whereNonZero(arg,tol=0.): Line 996  def whereNonZero(arg,tol=0.):
996        else:        else:
997          return 0.          return 0.
998     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
999        return 1.-whereZero(arg,tol)        return arg.applyfunc(symfn.whereNonZero)
1000     else:     else:
1001        raise TypeError("whereNonZero: Unknown argument type.")        raise TypeError("whereNonZero: Unknown argument type.")
1002    
1003    def Abs(arg):
1004       """
1005       Returns the absolute value of argument ``arg``.
1006    
1007       :param arg: argument
1008       :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1009       :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1010               on the type of ``arg``
1011       :raise TypeError: if the type of the argument is not expected
1012       """
1013       if isinstance(arg,Symbol):
1014          return arg.applyfunc(symfn.abs)
1015       else:
1016          return abs(arg)
1017    
1018  def erf(arg):  def erf(arg):
1019     """     """
1020     Returns the error function *erf* of argument ``arg``.     Returns the error function *erf* of argument ``arg``.
# Line 1767  def erf(arg): Line 1027  def erf(arg):
1027     """     """
1028     if isinstance(arg,escript.Data):     if isinstance(arg,escript.Data):
1029        return arg._erf()        return arg._erf()
1030       elif isinstance(arg,Symbol):
1031          return arg.applyfunc(symfn.erf)
1032     else:     else:
1033        raise TypeError("erf: Unknown argument type.")        raise TypeError("erf: Unknown argument type.")
1034    
# Line 1789  def sin(arg): Line 1051  def sin(arg):
1051     elif isinstance(arg,int):     elif isinstance(arg,int):
1052        return math.sin(arg)        return math.sin(arg)
1053     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1054        return Sin_Symbol(arg)        return arg.applyfunc(symfn.sin)
1055     else:     else:
1056        raise TypeError("sin: Unknown argument type.")        raise TypeError("sin: Unknown argument type.")
1057    
 class Sin_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the sine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of sin `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "sin(%s)"%argstrs  
       else:  
          raise NotImplementedError("Sin_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return sin(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1058  def cos(arg):  def cos(arg):
1059     """     """
1060     Returns cosine of argument ``arg``.     Returns cosine of argument ``arg``.
# Line 1889  def cos(arg): Line 1074  def cos(arg):
1074     elif isinstance(arg,int):     elif isinstance(arg,int):
1075        return math.cos(arg)        return math.cos(arg)
1076     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1077        return Cos_Symbol(arg)        return arg.applyfunc(symfn.cos)
1078     else:     else:
1079        raise TypeError("cos: Unknown argument type.")        raise TypeError("cos: Unknown argument type.")
1080    
 class Cos_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the cosine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of cos `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "cos(%s)"%argstrs  
       else:  
          raise NotImplementedError("Cos_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return cos(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1081  def tan(arg):  def tan(arg):
1082     """     """
1083     Returns tangent of argument ``arg``.     Returns tangent of argument ``arg``.
# Line 1989  def tan(arg): Line 1097  def tan(arg):
1097     elif isinstance(arg,int):     elif isinstance(arg,int):
1098        return math.tan(arg)        return math.tan(arg)
1099     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1100        return Tan_Symbol(arg)        return arg.applyfunc(symfn.tan)
1101     else:     else:
1102        raise TypeError("tan: Unknown argument type.")        raise TypeError("tan: Unknown argument type.")
1103    
 class Tan_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the tangent function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of tan `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "tan(%s)"%argstrs  
       else:  
          raise NotImplementedError("Tan_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return tan(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1104  def asin(arg):  def asin(arg):
1105     """     """
1106     Returns the inverse sine of argument ``arg``.     Returns the inverse sine of argument ``arg``.
# Line 2089  def asin(arg): Line 1120  def asin(arg):
1120     elif isinstance(arg,int):     elif isinstance(arg,int):
1121        return math.asin(arg)        return math.asin(arg)
1122     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1123        return Asin_Symbol(arg)        return arg.applyfunc(symfn.asin)
1124     else:     else:
1125        raise TypeError("asin: Unknown argument type.")        raise TypeError("asin: Unknown argument type.")
1126    
 class Asin_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse sine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of asin `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "asin(%s)"%argstrs  
       else:  
          raise NotImplementedError("Asin_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return asin(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1127  def acos(arg):  def acos(arg):
1128     """     """
1129     Returns the inverse cosine of argument ``arg``.     Returns the inverse cosine of argument ``arg``.
# Line 2189  def acos(arg): Line 1143  def acos(arg):
1143     elif isinstance(arg,int):     elif isinstance(arg,int):
1144        return math.acos(arg)        return math.acos(arg)
1145     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1146        return Acos_Symbol(arg)        return arg.applyfunc(symfn.acos)
1147     else:     else:
1148        raise TypeError("acos: Unknown argument type.")        raise TypeError("acos: Unknown argument type.")
1149    
 class Acos_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse cosine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of acos `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "acos(%s)"%argstrs  
       else:  
          raise NotImplementedError("Acos_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return acos(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1150  def atan(arg):  def atan(arg):
1151     """     """
1152     Returns inverse tangent of argument ``arg``.     Returns inverse tangent of argument ``arg``.
# Line 2289  def atan(arg): Line 1166  def atan(arg):
1166     elif isinstance(arg,int):     elif isinstance(arg,int):
1167        return math.atan(arg)        return math.atan(arg)
1168     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1169        return Atan_Symbol(arg)        return arg.applyfunc(symfn.atan)
1170     else:     else:
1171        raise TypeError("atan: Unknown argument type.")        raise TypeError("atan: Unknown argument type.")
1172    
 class Atan_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse tangent function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of atan `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "atan(%s)"%argstrs  
       else:  
          raise NotImplementedError("Atan_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return atan(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1173  def sinh(arg):  def sinh(arg):
1174     """     """
1175     Returns the hyperbolic sine of argument ``arg``.     Returns the hyperbolic sine of argument ``arg``.
# Line 2389  def sinh(arg): Line 1189  def sinh(arg):
1189     elif isinstance(arg,int):     elif isinstance(arg,int):
1190        return math.sinh(arg)        return math.sinh(arg)
1191     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1192        return Sinh_Symbol(arg)        return arg.applyfunc(symfn.sinh)
1193     else:     else:
1194        raise TypeError("sinh: Unknown argument type.")        raise TypeError("sinh: Unknown argument type.")
1195    
 class Sinh_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the hyperbolic sine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of sinh `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "sinh(%s)"%argstrs  
       else:  
          raise NotImplementedError("Sinh_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return sinh(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1196  def cosh(arg):  def cosh(arg):
1197     """     """
1198     Returns the hyperbolic cosine of argument ``arg``.     Returns the hyperbolic cosine of argument ``arg``.
# Line 2489  def cosh(arg): Line 1212  def cosh(arg):
1212     elif isinstance(arg,int):     elif isinstance(arg,int):
1213        return math.cosh(arg)        return math.cosh(arg)
1214     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1215        return Cosh_Symbol(arg)        return arg.applyfunc(symfn.cosh)
1216     else:     else:
1217        raise TypeError("cosh: Unknown argument type.")        raise TypeError("cosh: Unknown argument type.")
1218    
 class Cosh_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the hyperbolic cosine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of cosh `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "cosh(%s)"%argstrs  
       else:  
          raise NotImplementedError("Cosh_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return cosh(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1219  def tanh(arg):  def tanh(arg):
1220     """     """
1221     Returns the hyperbolic tangent of argument ``arg``.     Returns the hyperbolic tangent of argument ``arg``.
# Line 2589  def tanh(arg): Line 1235  def tanh(arg):
1235     elif isinstance(arg,int):     elif isinstance(arg,int):
1236        return math.tanh(arg)        return math.tanh(arg)
1237     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1238        return Tanh_Symbol(arg)        return arg.applyfunc(symfn.tanh)
1239     else:     else:
1240        raise TypeError("tanh: Unknown argument type.")        raise TypeError("tanh: Unknown argument type.")
1241    
 class Tanh_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the hyperbolic tangent function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of tanh `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "tanh(%s)"%argstrs  
       else:  
          raise NotImplementedError("Tanh_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return tanh(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1242  def asinh(arg):  def asinh(arg):
1243     """     """
1244     Returns the inverse hyperbolic sine of argument ``arg``.     Returns the inverse hyperbolic sine of argument ``arg``.
# Line 2689  def asinh(arg): Line 1258  def asinh(arg):
1258     elif isinstance(arg,int):     elif isinstance(arg,int):
1259        return numpy.arcsinh(float(arg))        return numpy.arcsinh(float(arg))
1260     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1261        return Asinh_Symbol(arg)        return arg.applyfunc(symfn.asinh)
1262     else:     else:
1263        raise TypeError("asinh: Unknown argument type.")        raise TypeError("asinh: Unknown argument type.")
1264    
 class Asinh_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse hyperbolic sine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of asinh `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "asinh(%s)"%argstrs  
       else:  
          raise NotImplementedError("Asinh_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return asinh(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1265  def acosh(arg):  def acosh(arg):
1266     """     """
1267     Returns the inverse hyperbolic cosine of argument ``arg``.     Returns the inverse hyperbolic cosine of argument ``arg``.
# Line 2789  def acosh(arg): Line 1281  def acosh(arg):
1281     elif isinstance(arg,int):     elif isinstance(arg,int):
1282        return numpy.arccosh(float(arg))        return numpy.arccosh(float(arg))
1283     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1284        return Acosh_Symbol(arg)        return arg.applyfunc(symfn.acosh)
1285     else:     else:
1286        raise TypeError("acosh: Unknown argument type.")        raise TypeError("acosh: Unknown argument type.")
1287    
 class Acosh_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse hyperbolic cosine function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of acosh `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "acosh(%s)"%argstrs  
       else:  
          raise NotImplementedError("Acosh_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return acosh(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1288  def atanh(arg):  def atanh(arg):
1289     """     """
1290     Returns the inverse hyperbolic tangent of argument ``arg``.     Returns the inverse hyperbolic tangent of argument ``arg``.
# Line 2889  def atanh(arg): Line 1304  def atanh(arg):
1304     elif isinstance(arg,int):     elif isinstance(arg,int):
1305        return numpy.arctanh(float(arg))        return numpy.arctanh(float(arg))
1306     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1307        return Atanh_Symbol(arg)        return arg.applyfunc(symfn.atanh)
1308     else:     else:
1309        raise TypeError("atanh: Unknown argument type.")        raise TypeError("atanh: Unknown argument type.")
1310    
 class Atanh_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse hyperbolic tangent function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of atanh `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "atanh(%s)"%argstrs  
       else:  
          raise NotImplementedError("Atanh_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return atanh(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1311  def exp(arg):  def exp(arg):
1312     """     """
1313     Returns *e* to the power of argument ``arg``.     Returns *e* to the power of argument ``arg``.
# Line 2989  def exp(arg): Line 1327  def exp(arg):
1327     elif isinstance(arg,int):     elif isinstance(arg,int):
1328        return math.exp(arg)        return math.exp(arg)
1329     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1330        return Exp_Symbol(arg)        return arg.applyfunc(symfn.exp)
1331     else:     else:
1332        raise TypeError("exp: Unknown argument type.")        raise TypeError("exp: Unknown argument type.")
1333    
 class Exp_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the exponential function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of exp `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "exp(%s)"%argstrs  
       else:  
          raise NotImplementedError("Exp_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return exp(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(self,self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1334  def sqrt(arg):  def sqrt(arg):
1335     """     """
1336     Returns the square root of argument ``arg``.     Returns the square root of argument ``arg``.
# Line 3089  def sqrt(arg): Line 1350  def sqrt(arg):
1350     elif isinstance(arg,int):     elif isinstance(arg,int):
1351        return math.sqrt(arg)        return math.sqrt(arg)
1352     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1353        return Sqrt_Symbol(arg)        return arg.applyfunc(symfn.sqrt)
1354     else:     else:
1355        raise TypeError("sqrt: Unknown argument type.")        raise TypeError("sqrt: Unknown argument type.")
1356    
 class Sqrt_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the square root function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of sqrt `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "sqrt(%s)"%argstrs  
       else:  
          raise NotImplementedError("Sqrt_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return sqrt(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1357  def log(arg):  def log(arg):
1358     """     """
1359     Returns the natural logarithm of argument ``arg``.     Returns the natural logarithm of argument ``arg``.
# Line 3189  def log(arg): Line 1373  def log(arg):
1373     elif isinstance(arg,int):     elif isinstance(arg,int):
1374        return math.log(arg)        return math.log(arg)
1375     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1376        return Log_Symbol(arg)        return arg.applyfunc(symfn.log)
1377     else:     else:
1378        raise TypeError("log: Unknown argument type.")        raise TypeError("log: Unknown argument type.")
1379    
 class Log_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the natural logarithm function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of log `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "log(%s)"%argstrs  
       else:  
          raise NotImplementedError("Log_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return log(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(1./arg,self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1380  def sign(arg):  def sign(arg):
1381     """     """
1382     Returns the sign of argument ``arg``.     Returns the sign of argument ``arg``.
# Line 3299  def sign(arg): Line 1406  def sign(arg):
1406        else:        else:
1407          return 0.          return 0.
1408     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1409        return wherePositive(arg)-whereNegative(arg)        return arg.applyfunc(symfn.sign)
1410     else:     else:
1411        raise TypeError("sign: Unknown argument type.")        raise TypeError("sign: Unknown argument type.")
1412    
 class Abs_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the absolute value function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of abs `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "abs(%s)"%argstrs  
       else:  
          raise NotImplementedError("Abs_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return abs(arg)  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myarg=self.getArgument()[0]  
          val=matchShape(sign(myarg),self.getDifferentiatedArguments(arg)[0])  
          return val[0]*val[1]  
   
1413  def minval(arg):  def minval(arg):
1414     """     """
1415     Returns the minimum value over all components of ``arg`` at each data point.     Returns the minimum value over all components of ``arg`` at each data point.
# Line 3401  def minval(arg): Line 1431  def minval(arg):
1431     elif isinstance(arg,int):     elif isinstance(arg,int):
1432        return float(arg)        return float(arg)
1433     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1434        return Minval_Symbol(arg)        return symfn.minval(arg)
1435     else:     else:
1436        raise TypeError("minval: Unknown argument type.")        raise TypeError("minval: Unknown argument type.")
1437    
 class Minval_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the minimum value function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of minimum value `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "minval(%s)"%argstrs  
       else:  
          raise NotImplementedError("Minval_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return minval(arg)  
   
1438  def maxval(arg):  def maxval(arg):
1439     """     """
1440     Returns the maximum value over all components of ``arg`` at each data point.     Returns the maximum value over all components of ``arg`` at each data point.
# Line 3486  def maxval(arg): Line 1456  def maxval(arg):
1456     elif isinstance(arg,int):     elif isinstance(arg,int):
1457        return float(arg)        return float(arg)
1458     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1459        return Maxval_Symbol(arg)        return symfn.maxval(arg)
1460     else:     else:
1461        raise TypeError("maxval: Unknown argument type.")        raise TypeError("maxval: Unknown argument type.")
1462    
 class Maxval_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the maximum value function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of maximum value `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: typically `Symbol`  
       """  
       DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if isinstance(argstrs,list):  
           argstrs=argstrs[0]  
       if format=="escript" or format=="str"  or format=="text":  
          return "maxval(%s)"%argstrs  
       else:  
          raise NotImplementedError("Maxval_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)[0]  
          return maxval(arg)  
   
1463  def length(arg):  def length(arg):
1464     """     """
1465     Returns the length (Euclidean norm) of argument ``arg`` at each data point.     Returns the length (Euclidean norm) of argument ``arg`` at each data point.
# Line 3573  def trace(arg,axis_offset=0): Line 1483  def trace(arg,axis_offset=0):
1483     :type axis_offset: ``int``     :type axis_offset: ``int``
1484     :return: trace of arg. The rank of the returned object is rank of ``arg``     :return: trace of arg. The rank of the returned object is rank of ``arg``
1485              minus 2.              minus 2.
1486     :rtype: `escript.Data`, `Symbol`, ``numpy.ndarray`` depending on the     :rtype: `escript.Data`, `Symbol` or ``numpy.ndarray`` depending on the type
1487             type of ``arg``             of ``arg``
1488     """     """
1489     if isinstance(arg,numpy.ndarray):     if isinstance(arg,numpy.ndarray):
1490        sh=arg.shape        sh=arg.shape
# Line 3604  def trace(arg,axis_offset=0): Line 1514  def trace(arg,axis_offset=0):
1514        if not s[axis_offset] == s[axis_offset+1]:        if not s[axis_offset] == s[axis_offset+1]:
1515          raise ValueError("dimensions of component %d and %d must match."%(axis_offset,axis_offset+1))          raise ValueError("dimensions of component %d and %d must match."%(axis_offset,axis_offset+1))
1516        return arg._trace(axis_offset)        return arg._trace(axis_offset)
    elif isinstance(arg,float):  
       raise TypeError("illegal argument type float.")  
    elif isinstance(arg,int):  
       raise TypeError("illegal argument type int.")  
1517     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
       return Trace_Symbol(arg,axis_offset)  
    else:  
       raise TypeError("Unknown argument type.")  
   
 class Trace_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the trace function.  
    """  
    def __init__(self,arg,axis_offset=0):  
       """  
       Initialization of trace `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: `Symbol`  
       :param axis_offset: ``axis_offset`` to components to sum over.  
                           ``axis_offset`` must be non-negative and less than the  
                           rank of ``arg`` +1. The dimensions on component  
                           ``axis_offset`` and axis_offset+1 must be equal.  
       :type axis_offset: ``int``  
       """  
1518        if arg.getRank()<2:        if arg.getRank()<2:
1519          raise ValueError("rank of argument must be greater than 1")          raise ValueError("rank of argument must be greater than 1")
1520        if axis_offset<0 or axis_offset>arg.getRank()-2:        if axis_offset<0 or axis_offset>arg.getRank()-2:
# Line 3636  class Trace_Symbol(DependendSymbol): Line 1522  class Trace_Symbol(DependendSymbol):
1522        s=list(arg.getShape())        s=list(arg.getShape())
1523        if not s[axis_offset] == s[axis_offset+1]:        if not s[axis_offset] == s[axis_offset+1]:
1524          raise ValueError("dimensions of component %d and %d must match."%(axis_offset,axis_offset+1))          raise ValueError("dimensions of component %d and %d must match."%(axis_offset,axis_offset+1))
1525        super(Trace_Symbol,self).__init__(args=[arg,axis_offset],shape=tuple(s[0:axis_offset]+s[axis_offset+2:]),dim=arg.getDim())        return arg.trace(axis_offset)
1526       elif isinstance(arg,float):
1527     def getMyCode(self,argstrs,format="escript"):        raise TypeError("illegal argument type float.")
1528        """     elif isinstance(arg,int):
1529        Returns program code that can be used to evaluate the symbol.        raise TypeError("illegal argument type int.")
1530       else:
1531        :param argstrs: a string for each argument representing the argument        raise TypeError("Unknown argument type.")
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "trace(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("Trace_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return trace(arg[0],axis_offset=arg[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return trace(self.getDifferentiatedArguments(arg)[0],axis_offset=self.getArgument()[1])  
1532    
1533  def transpose(arg,axis_offset=None):  def transpose(arg,axis_offset=None):
1534     """     """
1535     Returns the transpose of ``arg`` by swapping the first ``axis_offset`` and the     Returns the transpose of ``arg`` by swapping the first ``axis_offset`` and
1536     last ``rank-axis_offset`` components.     the last ``rank-axis_offset`` components.
1537    
1538     :param arg: argument     :param arg: argument
1539     :type arg: `escript.Data`, `Symbol`, ``numpy.ndarray``, ``float``, ``int``     :type arg: `escript.Data`, `Symbol`, ``numpy.ndarray``, ``float``, ``int``
# Line 3733  def transpose(arg,axis_offset=None): Line 1565  def transpose(arg,axis_offset=None):
1565          raise ValueError("axis_offset must be 0 for int argument")          raise ValueError("axis_offset must be 0 for int argument")
1566        return float(arg)        return float(arg)
1567     elif isinstance(arg,Symbol):     elif isinstance(arg,Symbol):
1568        if axis_offset==None: axis_offset=int(arg.getRank()/2)        r=arg.getRank()
1569        return Transpose_Symbol(arg,axis_offset)        if axis_offset==None: axis_offset=int(r/2)
1570          if axis_offset<0 or axis_offset>r:
1571            raise ValueError,"axis_offset must be between 0 and %s"%r
1572          return arg.transpose(axis_offset)
1573     else:     else:
1574        raise TypeError("Unknown argument type.")        raise TypeError("Unknown argument type.")
1575    
 class Transpose_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the transpose function.  
    """  
    def __init__(self,arg,axis_offset=None):  
       """  
       Initialization of transpose `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: `Symbol`  
       :param axis_offset: the first ``axis_offset`` components are swapped with  
                           the rest. ``axis_offset`` must be non-negative and  
                           less than or equal to the rank of ``arg``. If  
                           ``axis_offset`` is not present ``int(r/2)`` where r is  
                           the rank of ``arg`` is used.  
       :type axis_offset: ``int``  
       """  
       if axis_offset==None: axis_offset=int(arg.getRank()/2)  
       if axis_offset<0 or axis_offset>arg.getRank():  
         raise ValueError("axis_offset must be between 0 and %s"%arg.getRank())  
       s=arg.getShape()  
       super(Transpose_Symbol,self).__init__(args=[arg,axis_offset],shape=s[axis_offset:]+s[:axis_offset],dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "transpose(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("Transpose_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return transpose(arg[0],axis_offset=arg[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return transpose(self.getDifferentiatedArguments(arg)[0],axis_offset=self.getArgument()[1])  
   
1576  def swap_axes(arg,axis0=0,axis1=1):  def swap_axes(arg,axis0=0,axis1=1):
1577     """     """
1578     Returns the swap of ``arg`` by swapping the components ``axis0`` and ``axis1``.     Returns the swap of ``arg`` by swapping the components ``axis0`` and ``axis1``.
# Line 3834  def swap_axes(arg,axis0=0,axis1=1): Line 1586  def swap_axes(arg,axis0=0,axis1=1):
1586                   rank of ``arg``.                   rank of ``arg``.
1587     :type axis1: ``int``     :type axis1: ``int``
1588     :return: ``arg`` with swapped components     :return: ``arg`` with swapped components
1589     :rtype: `escript.Data`, `Symbol`, ``numpy.ndarray`` depending on the     :rtype: `escript.Data`, `Symbol` or ``numpy.ndarray`` depending on the type
1590             type of ``arg``             of ``arg``
1591     """     """
1592     if axis0 > axis1:     if axis0 > axis1:
1593        axis0,axis1=axis1,axis0        axis0,axis1=axis1,axis0
# Line 3843  def swap_axes(arg,axis0=0,axis1=1): Line 1595  def swap_axes(arg,axis0=0,axis1=1):
1595        return numpy.swapaxes(arg,axis0,axis1)        return numpy.swapaxes(arg,axis0,axis1)
1596     elif isinstance(arg,escript.Data):     elif isinstance(arg,escript.Data):
1597        return arg._swap_axes(axis0,axis1)        return arg._swap_axes(axis0,axis1)
1598       elif isinstance(arg,Symbol):
1599          return arg.swap_axes(axis0,axis1)
1600     elif isinstance(arg,float):     elif isinstance(arg,float):
1601        raise TypeError("float argument is not supported.")        raise TypeError("float argument is not supported.")
1602     elif isinstance(arg,int):     elif isinstance(arg,int):
1603        raise TypeError("int argument is not supported.")        raise TypeError("int argument is not supported.")
    elif isinstance(arg,Symbol):  
       return SwapAxes_Symbol(arg,axis0,axis1)  
1604     else:     else:
1605        raise TypeError("Unknown argument type.")        raise TypeError("Unknown argument type.")
1606    
 class SwapAxes_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the swap function.  
    """  
    def __init__(self,arg,axis0=0,axis1=1):  
       """  
       Initialization of swap `Symbol` with argument ``arg``.  
   
       :param arg: argument  
       :type arg: `Symbol`  
       :param axis0: first axis. ``axis0`` must be non-negative and less than the  
                     rank of ``arg``.  
       :type axis0: ``int``  
       :param axis1: second axis. ``axis1`` must be non-negative and less than  
                     the rank of ``arg``.  
       :type axis1: ``int``  
       """  
       if arg.getRank()<2:  
          raise ValueError("argument must have at least rank 2.")  
       if axis0<0 or axis0>arg.getRank()-1:  
          raise ValueError("axis0 must be between 0 and %s"%arg.getRank()-1)  
       if axis1<0 or axis1>arg.getRank()-1:  
          raise ValueError("axis1 must be between 0 and %s"%arg.getRank()-1)  
       if axis0 == axis1:  
          raise ValueError("axis indices must be different.")  
       if axis0 > axis1:  
          axis0,axis1=axis1,axis0  
       s=arg.getShape()  
       s_out=[]  
       for i in range(len(s)):  
          if i == axis0:  
             s_out.append(s[axis1])  
          elif i == axis1:  
             s_out.append(s[axis0])  
          else:  
             s_out.append(s[i])  
       super(SwapAxes_Symbol,self).__init__(args=[arg,axis0,axis1],shape=tuple(s_out),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "swap(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("SwapAxes_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return swap_axes(arg[0],axis0=arg[1],axis1=arg[2])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return swap_axes(self.getDifferentiatedArguments(arg)[0],axis0=self.getArgument()[1],axis1=self.getArgument()[2])  
   
1607  def symmetric(arg):  def symmetric(arg):
1608      """      """
1609      Returns the symmetric part of the square matrix ``arg``. That is,      Returns the symmetric part of the square matrix ``arg``. That is,
# Line 3958  def symmetric(arg): Line 1612  def symmetric(arg):
1612      :param arg: input matrix. Must have rank 2 or 4 and be square.      :param arg: input matrix. Must have rank 2 or 4 and be square.
1613      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`
1614      :return: symmetric part of ``arg``      :return: symmetric part of ``arg``
1615      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
1616      """      """
1617      if isinstance(arg,numpy.ndarray):      if isinstance(arg,numpy.ndarray):
1618        if arg.ndim==2:        if arg.ndim==2:
# Line 3982  def symmetric(arg): Line 1635  def symmetric(arg):
1635          return arg._symmetric()          return arg._symmetric()
1636        else:        else:
1637          raise ValueError("rank 2 or 4 is required.")          raise ValueError("rank 2 or 4 is required.")
1638        elif isinstance(arg, Symbol):
1639            if arg.getRank()==2:
1640                if arg.getShape()[0]!=arg.getShape()[1]:
1641                    raise ValueError("symmetric: argument must be square.")
1642            elif arg.getRank()==4:
1643                if arg.getShape()[0]!=arg.getShape()[2] or arg.getShape()[1]!=arg.getShape()[3]:
1644                    raise ValueError("symmetric: argument must be square.")
1645            else:
1646                raise ValueError("symmetric: rank 2 or 4 is required.")
1647            return (arg+transpose(arg))/2
1648      elif isinstance(arg,float):      elif isinstance(arg,float):
1649        return arg        return arg
1650      elif isinstance(arg,int):      elif isinstance(arg,int):
1651        return float(arg)        return float(arg)
     elif isinstance(arg,Symbol):  
       if arg.getRank()==2:  
         if not (arg.getShape()[0]==arg.getShape()[1]):  
            raise ValueError("argument must be square.")  
       elif arg.getRank()==4:  
         if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]):  
            raise ValueError("argument must be square.")  
       else:  
         raise ValueError("rank 2 or 4 is required.")  
       return (arg+transpose(arg))/2  
1652      else:      else:
1653        raise TypeError("symmetric: Unknown argument type.")        raise TypeError("symmetric: Unknown argument type.")
1654    
# Line 4007  def nonsymmetric(arg): Line 1660  def nonsymmetric(arg):
1660      :param arg: input matrix. Must have rank 2 or 4 and be square.      :param arg: input matrix. Must have rank 2 or 4 and be square.
1661      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`
1662      :return: non-symmetric part of ``arg``      :return: non-symmetric part of ``arg``
1663      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
1664      """      """
1665      if isinstance(arg,numpy.ndarray):      if isinstance(arg,numpy.ndarray):
1666        if arg.ndim==2:        if arg.ndim==2:
# Line 4031  def nonsymmetric(arg): Line 1683  def nonsymmetric(arg):
1683          return arg._nonsymmetric()          return arg._nonsymmetric()
1684        else:        else:
1685          raise ValueError("rank 2 or 4 is required.")          raise ValueError("rank 2 or 4 is required.")
1686        elif isinstance(arg, Symbol):
1687            if arg.getRank()==2:
1688                if arg.getShape()[0]!=arg.getShape()[1]:
1689                    raise ValueError("nonsymmetric: argument must be square.")
1690            elif arg.getRank()==4:
1691                if arg.getShape()[0]!=arg.getShape()[2] or arg.getShape()[1]!=arg.getShape()[3]:
1692                    raise ValueError("nonsymmetric: argument must be square.")
1693            else:
1694                raise ValueError("nonsymmetric: rank 2 or 4 is required.")
1695            return (arg-transpose(arg))/2
1696      elif isinstance(arg,float):      elif isinstance(arg,float):
1697        return arg          return arg
1698      elif isinstance(arg,int):      elif isinstance(arg,int):
1699        return float(arg)          return float(arg)
     elif isinstance(arg,Symbol):  
       if arg.getRank()==2:  
         if not (arg.getShape()[0]==arg.getShape()[1]):  
            raise ValueError("nonsymmetric: argument must be square.")  
       elif arg.getRank()==4:  
         if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]):  
            raise ValueError("nonsymmetric: argument must be square.")  
       else:  
         raise ValueError("nonsymmetric: rank 2 or 4 is required.")  
       return (arg-transpose(arg))/2  
1700      else:      else:
1701        raise TypeError("nonsymmetric: Unknown argument type.")          raise TypeError("nonsymmetric: Unknown argument type.")
1702    
1703  def inverse(arg):  def inverse(arg):
1704      """      """
# Line 4057  def inverse(arg): Line 1709  def inverse(arg):
1709      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`
1710      :return: inverse of the argument. ``matrix_mult(inverse(arg),arg)`` will be      :return: inverse of the argument. ``matrix_mult(inverse(arg),arg)`` will be
1711               almost equal to ``kronecker(arg.getShape()[0])``               almost equal to ``kronecker(arg.getShape()[0])``
1712      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
1713      :note: for `escript.Data` objects the dimension is restricted to 3.      :note: for `escript.Data` objects the dimension is restricted to 3.
1714      """      """
1715      import numpy.linalg      import numpy.linalg
# Line 4071  def inverse(arg): Line 1722  def inverse(arg):
1722      elif isinstance(arg,int):      elif isinstance(arg,int):
1723        return 1./float(arg)        return 1./float(arg)
1724      elif isinstance(arg,Symbol):      elif isinstance(arg,Symbol):
1725        return Inverse_Symbol(arg)        return arg.inverse()
1726      else:      else:
1727        raise TypeError("inverse: Unknown argument type.")        raise TypeError("inverse: Unknown argument type.")
1728    
1729  def escript_inverse(arg): # this should be escript._inverse and use LAPACK  def escript_inverse(arg): # this should be escript._inverse and use LAPACK
1730        "arg is a Data object!!!"        "arg is a Data object!"
1731        return arg._inverse()        return arg._inverse()
1732    
1733        #if not arg.getRank()==2:        #if not arg.getRank()==2:
# Line 4129  def escript_inverse(arg): # this should Line 1780  def escript_inverse(arg): # this should
1780           #raise TypeError,"escript_inverse: only matrix dimensions 1,2,3 are supported right now."           #raise TypeError,"escript_inverse: only matrix dimensions 1,2,3 are supported right now."
1781        #return out        #return out
1782    
 class Inverse_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the inverse function.  
    """  
    def __init__(self,arg):  
       """  
       Initialization of inverse `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: `Symbol`  
       """  
       if not arg.getRank()==2:  
         raise ValueError("Inverse_Symbol:: argument must have rank 2")  
       s=arg.getShape()  
       if not s[0] == s[1]:  
         raise ValueError("Inverse_Symbol:: argument must be a square matrix.")  
       super(Inverse_Symbol,self).__init__(args=[arg],shape=s,dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 1 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "inverse(%s)"%argstrs[0]  
       else:  
          raise NotImplementedError("Inverse_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return inverse(arg[0])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return -matrix_mult(matrix_mult(self,self.getDifferentiatedArguments(arg)[0]),self)  
   
1783  def eigenvalues(arg):  def eigenvalues(arg):
1784      """      """
1785      Returns the eigenvalues of the square matrix ``arg``.      Returns the eigenvalues of the square matrix ``arg``.
# Line 4216  def eigenvalues(arg): Line 1789  def eigenvalues(arg):
1789                  ``transpose(arg)==arg`` (this is not checked).                  ``transpose(arg)==arg`` (this is not checked).
1790      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg: ``numpy.ndarray``, `escript.Data`, `Symbol`
1791      :return: the eigenvalues in increasing order      :return: the eigenvalues in increasing order
1792      :rtype: ``numpy.ndarray``,`escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
1793      :note: for `escript.Data` and `Symbol` objects the dimension is      :note: for `escript.Data` and `Symbol` objects the dimension is
1794             restricted to 3.             restricted to 3.
1795      """      """
# Line 4227  def eigenvalues(arg): Line 1799  def eigenvalues(arg):
1799        return out        return out
1800      elif isinstance(arg,escript.Data):      elif isinstance(arg,escript.Data):
1801        return arg._eigenvalues()        return arg._eigenvalues()
     elif isinstance(arg,Symbol):  
       if not arg.getRank()==2:  
         raise ValueError("eigenvalues: argument must have rank 2")  
       s=arg.getShape()  
       if not s[0] == s[1]:  
         raise ValueError("eigenvalues: argument must be a square matrix.")  
       if s[0]==1:  
           return arg[0]  
       elif s[0]==2:  
           arg1=symmetric(arg)  
           A11=arg1[0,0]  
           A12=arg1[0,1]  
           A22=arg1[1,1]  
           trA=(A11+A22)/2.  
           A11-=trA  
           A22-=trA  
           s=sqrt(A12**2-A11*A22)  
           return trA+s*numpy.array([-1.,1.],dtype=numpy.float64)  
       elif s[0]==3:  
           arg1=symmetric(arg)  
           A11=arg1[0,0]  
           A12=arg1[0,1]  
           A22=arg1[1,1]  
           A13=arg1[0,2]  
           A23=arg1[1,2]  
           A33=arg1[2,2]  
           trA=(A11+A22+A33)/3.  
           A11-=trA  
           A22-=trA  
           A33-=trA  
           A13_2=A13**2  
           A23_2=A23**2  
           A12_2=A12**2  
           p=A13_2+A23_2+A12_2+(A11**2+A22**2+A33**2)/2.  
           q=A13_2*A22+A23_2*A11+A12_2*A33-A11*A22*A33-2*A12*A23*A13  
           sq_p=sqrt(p/3.)  
           alpha_3=acos(clip(-q*(sq_p+whereZero(p,0.)*1.e-15)**(-3.)/2.,-1.,1.))/3.  # whereZero is protection against divison by zero  
           sq_p*=2.  
           f=cos(alpha_3)               *numpy.array([0.,0.,1.],dtype=numpy.float64) \  
            -cos(alpha_3+numpy.pi/3.)*numpy.array([0.,1.,0.],dtype=numpy.float64) \  
            -cos(alpha_3-numpy.pi/3.)*numpy.array([1.,0.,0.],dtype=numpy.float64)  
           return trA+sq_p*f  
       else:  
          raise TypeError("eigenvalues: only matrix dimensions 1,2,3 are supported right now.")  
1802      elif isinstance(arg,float):      elif isinstance(arg,float):
1803        return arg        return arg
1804      elif isinstance(arg,int):      elif isinstance(arg,int):
1805        return float(arg)        return float(arg)
1806        elif isinstance(arg,Symbol):
1807          return symfn.eigenvalues(arg)
1808      else:      else:
1809        raise TypeError("eigenvalues: Unknown argument type.")        raise TypeError("eigenvalues: Unknown argument type.")
1810    
# Line 4297  def eigenvalues_and_eigenvectors(arg): Line 1827  def eigenvalues_and_eigenvectors(arg):
1827        raise TypeError("eigenvalues_and_eigenvectors does not support numpy.ndarray arguments")        raise TypeError("eigenvalues_and_eigenvectors does not support numpy.ndarray arguments")
1828      elif isinstance(arg,escript.Data):      elif isinstance(arg,escript.Data):
1829        return arg._eigenvalues_and_eigenvectors()        return arg._eigenvalues_and_eigenvectors()
     elif isinstance(arg,Symbol):  
       raise TypeError("eigenvalues_and_eigenvectors does not support Symbol arguments")  
1830      elif isinstance(arg,float):      elif isinstance(arg,float):
1831        return (numpy.array([[arg]],numpy.float_),numpy.ones((1,1),numpy.float_))        return (numpy.array([[arg]],numpy.float_),numpy.ones((1,1),numpy.float_))
1832      elif isinstance(arg,int):      elif isinstance(arg,int):
1833        return (numpy.array([[arg]],numpy.float_),numpy.ones((1,1),numpy.float_))        return (numpy.array([[arg]],numpy.float_),numpy.ones((1,1),numpy.float_))
1834        elif isinstance(arg,Symbol):
1835          return symfn.eigenvalues_and_eigenvectors(arg)
1836      else:      else:
1837        raise TypeError("eigenvalues: Unknown argument type.")        raise TypeError("eigenvalues: Unknown argument type.")
1838    
 #=======================================================  
 #  Binary operations:  
 #=======================================================  
 def add(arg0,arg1):  
        """  
        Adds ``arg0`` and ``arg1`` together.  
   
        :param arg0: first term  
        :type arg0: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: second term  
        :type arg1: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                    ``numpy.ndarray``  
        :return: the sum of ``arg0`` and ``arg1``  
        :rtype: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                ``numpy.ndarray``  
        :note: The shape of both arguments is matched according to the rules  
               used in `matchShape`.  
        """  
        args=matchShape(arg0,arg1)  
        if testForZero(args[0]):  
           return args[1]  
        elif testForZero(args[1]):  
           return args[0]  
        else:  
           if isinstance(args[0],Symbol) or isinstance(args[1],Symbol) :  
               return Add_Symbol(args[0],args[1])  
           elif isinstance(args[0],numpy.ndarray):  
               return args[1]+args[0]  
           else:  
               return args[0]+args[1]  
   
 class Add_Symbol(DependendSymbol):  
    """  
    Symbol representing the sum of two arguments.  
    """  
    def __init__(self,arg0,arg1):  
        """  
        Initialization of the `Symbol` representing the sum of two arguments.  
   
        :param arg0: first term in the sum  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: second term in the sum  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: if both arguments do not have the same shape  
        :note: if both arguments have a spatial dimension, they must be equal.  
        """  
        sh0=getShape(arg0)  
        sh1=getShape(arg1)  
        if not sh0==sh1:  
           raise ValueError("Add_Symbol: shape of arguments must match")  
        DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0,args=[arg0,arg1])  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="str" or format=="text":  
          return "(%s)+(%s)"%(argstrs[0],argstrs[1])  
       elif format=="escript":  
          return "add(%s,%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          out=add(args[0],args[1])  
          return out  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          dargs=self.getDifferentiatedArguments(arg)  
          return add(dargs[0],dargs[1])  
   
1839  def mult(arg0,arg1):  def mult(arg0,arg1):
1840         """         """
1841         Product of ``arg0`` and ``arg1``.         Product of ``arg0`` and ``arg1``.
1842    
1843         :param arg0: first term         :param arg0: first term
1844         :type arg0: `escript.Symbol`, ``float``, ``int``, `escript.Data`,         :type arg0: `Symbol`, ``float``, ``int``, `escript.Data` or
1845                     ``numpy.ndarray``                     ``numpy.ndarray``
1846         :param arg1: second term         :param arg1: second term
1847         :type arg1: `escript.Symbol`, ``float``, ``int``, `escript.Data`,         :type arg1: `Symbol`, ``float``, ``int``, `escript.Data` or
1848                     ``numpy.ndarray``                     ``numpy.ndarray``
1849         :return: the product of ``arg0`` and ``arg1``         :return: the product of ``arg0`` and ``arg1``
1850         :rtype: `escript.Symbol`, ``float``, ``int``, `escript.Data`,         :rtype: `Symbol`, ``float``, ``int``, `escript.Data` or
1851                 ``numpy.ndarray``                 ``numpy.ndarray``
1852         :note: The shape of both arguments is matched according to the rules         :note: The shape of both arguments is matched according to the rules
1853                used in `matchShape`.                used in `matchShape`.
# Line 4445  def mult(arg0,arg1): Line 1856  def mult(arg0,arg1):
1856         if testForZero(args[0]) or testForZero(args[1]):         if testForZero(args[0]) or testForZero(args[1]):
1857            return numpy.zeros(getShape(args[0]),numpy.float64)            return numpy.zeros(getShape(args[0]),numpy.float64)
1858         else:         else:
1859            if isinstance(args[0],Symbol) or isinstance(args[1],Symbol) :            if isinstance(args[0],numpy.ndarray):
               return Mult_Symbol(args[0],args[1])  
           elif isinstance(args[0],numpy.ndarray):  
1860                return args[1]*args[0]                return args[1]*args[0]
1861            else:            else:
1862                return args[0]*args[1]                return args[0]*args[1]
1863    
 class Mult_Symbol(DependendSymbol):  
    """  
    Symbol representing the product of two arguments.  
    """  
    def __init__(self,arg0,arg1):  
        """  
        Initialization of the `Symbol` representing the product of two  
        arguments.  
   
        :param arg0: first factor  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: second factor  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: if both arguments do not have the same shape  
        :note: if both arguments have a spatial dimension, they must be equal.  
        """  
        sh0=getShape(arg0)  
        sh1=getShape(arg1)  
        if not sh0==sh1:  
           raise ValueError("Mult_Symbol: shape of arguments must match")  
        DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0,args=[arg0,arg1])  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="str" or format=="text":  
          return "(%s)*(%s)"%(argstrs[0],argstrs[1])  
       elif format=="escript":  
          return "mult(%s,%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`.  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          return mult(args[0],args[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myargs=self.getArgument()  
          dargs=self.getDifferentiatedArguments(arg)  
          return add(mult(myargs[0],dargs[1]),mult(myargs[1],dargs[0]))  
   
 def quotient(arg0,arg1):  
        """  
        Quotient of ``arg0`` and ``arg1``.  
   
        :param arg0: numerator  
        :type arg0: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: denominator  
        :type arg1: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                    ``numpy.ndarray``  
        :return: the quotient of ``arg0`` and ``arg1``  
        :rtype: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                ``numpy.ndarray``  
        :note: The shape of both arguments is matched according to the rules  
               used in `matchShape`.  
        """  
        args=matchShape(arg0,arg1)  
        if testForZero(args[0]):  
           return numpy.zeros(getShape(args[0]),numpy.float64)  
        elif isinstance(args[0],Symbol):  
           if isinstance(args[1],Symbol):  
              return Quotient_Symbol(args[0],args[1])  
           else:  
              return mult(args[0],1./args[1])  
        else:  
           if isinstance(args[1],Symbol):  
              return Quotient_Symbol(args[0],args[1])  
           elif isinstance(args[0],numpy.ndarray) and not isinstance(args[1],numpy.ndarray):  
              return 1./args[1]*args[0]  
           else:  
              return args[0]/args[1]  
   
 class Quotient_Symbol(DependendSymbol):  
    """  
    Symbol representing the quotient of two arguments.  
    """  
    def __init__(self,arg0,arg1):  
        """  
        Initialization of `Symbol` representing the quotient of two arguments.  
   
        :param arg0: numerator  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: denominator  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: if both arguments do not have the same shape  
        :note: if both arguments have a spatial dimension, they must be equal.  
        """  
        sh0=getShape(arg0)  
        sh1=getShape(arg1)  
        if not sh0==sh1:  
           raise ValueError("Quotient_Symbol: shape of arguments must match")  
        DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0,args=[arg0,arg1])  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="str" or format=="text":  
          return "(%s)/(%s)"%(argstrs[0],argstrs[1])  
       if format=="escript":  
          return "quotient(%s,%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          return quotient(args[0],args[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myargs=self.getArgument()  
          dargs=self.getDifferentiatedArguments(arg)  
          return quotient(add(mult(myargs[1],dargs[0]),mult(-myargs[0],dargs[1])),myargs[1]*myargs[1])  
   
   
 def power(arg0,arg1):  
        """  
        Raises ``arg0`` to the power of ``arg1``.  
   
        :param arg0: basis  
        :type arg0: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: exponent  
        :type arg1: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                    ``numpy.ndarray``  
        :return: ``arg0`` to the power of ``arg1``  
        :rtype: `escript.Symbol`, ``float``, ``int``, `escript.Data`,  
                ``numpy.ndarray``  
        :note: The shape of both arguments is matched according to the rules  
               used in `matchShape`  
        """  
        args=matchShape(arg0,arg1)  
        if testForZero(args[0]):  
           return numpy.zeros(getShape(args[0]),numpy.float64)  
        elif testForZero(args[1]):  
           return numpy.ones(getShape(args[1]),numpy.float64)  
        elif isinstance(args[0],Symbol) or isinstance(args[1],Symbol):  
           return Power_Symbol(args[0],args[1])  
        elif isinstance(args[0],numpy.ndarray) and not isinstance(args[1],numpy.ndarray):  
           return exp(args[1]*log(args[0]))  
        else:  
            return args[0]**args[1]  
   
 class Power_Symbol(DependendSymbol):  
    """  
    Symbol representing the first argument to the power of the second argument.  
    """  
    def __init__(self,arg0,arg1):  
        """  
        Initialization of the `Symbol` representing raising the first argument  
        to the power of the second.  
   
        :param arg0: basis  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: exponent  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: if both arguments do not have the same shape  
        :note: if both arguments have a spatial dimension, they must be equal  
        """  
        sh0=getShape(arg0)  
        sh1=getShape(arg1)  
        if not sh0==sh1:  
           raise ValueError("Power_Symbol: shape of arguments must match")  
        d0=pokeDim(arg0)  
        d1=pokeDim(arg1)  
        DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0,args=[arg0,arg1])  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str" or format=="text":  
          return "(%s)**(%s)"%(argstrs[0],argstrs[1])  
       elif format=="escript":  
          return "power(%s,%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          return power(args[0],args[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          myargs=self.getArgument()  
          dargs=self.getDifferentiatedArguments(arg)  
          return mult(self,add(mult(log(myargs[0]),dargs[1]),mult(quotient(myargs[1],myargs[0]),dargs[0])))  
   
1864  def maximum(*args):  def maximum(*args):
1865      """      """
1866      The maximum over arguments ``args``.      The maximum over arguments ``args``.
# Line 4790  def maximum(*args): Line 1873  def maximum(*args):
1873      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``int`` or      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``int`` or
1874              ``float`` depending on the input              ``float`` depending on the input
1875      """      """
1876        if max([isinstance(v,Symbol) for v in args]):
1877            return symfn.maximum(*args)
1878      out=None      out=None
1879      for a in args:      for a in args:
1880         if out==None:         if out==None:
# Line 4797  def maximum(*args): Line 1882  def maximum(*args):
1882         else:         else:
1883            if isinstance(out,escript.Data) and isinstance(a,escript.Data):            if isinstance(out,escript.Data) and isinstance(a,escript.Data):
1884               if out.getRank()==0 and a.getRank()>0:               if out.getRank()==0 and a.getRank()>0:
1885          #We need to consider the case where we have scalars and higher                  # We need to consider the case where we have scalars and
1886          #ranked objects mixed. If the scalar was first it will get                  # higher ranked objects mixed. If the scalar was first it will
1887          #picked as the initial out and we have a problem,                  # get picked as the initial out and we have a problem, so we
1888          #so we swap the objects                  # swap the objects
1889                  res=a.copy()    #Deep copy of a                  res=a.copy() #Deep copy of a
1890                  res.copyWithMask(out,wherePositive(out-a))                  res.copyWithMask(out,wherePositive(out-a))
1891                  out=res                  out=res
1892               else:               else:
1893                  out.copyWithMask(a,wherePositive(a-out))                  out.copyWithMask(a,wherePositive(a-out))
1894            else:            else:
1895               diff=add(a,-out)               if isinstance(a, numpy.ndarray):
1896               temp=add(mult(out, whereNonPositive(diff)), mult(a, wherePositive(diff)))                  diff=-out+a
1897                 else:
1898                    diff=a-out
1899                 temp=mult(whereNonPositive(diff),out)+mult(wherePositive(diff),a)
1900               if isinstance(out,numpy.ndarray) and isinstance(a,numpy.ndarray):               if isinstance(out,numpy.ndarray) and isinstance(a,numpy.ndarray):
1901             # we need to convert the result to an array                  # we need to convert the result to an array
1902                 temp=numpy.array(temp)                              temp=numpy.array(temp)            
1903               out=temp               out=temp
1904      return out      return out
1905    
# Line 4827  def minimum(*args): Line 1915  def minimum(*args):
1915      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``int`` or      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``int`` or
1916              ``float`` depending on the input              ``float`` depending on the input
1917      """      """
1918        if max([isinstance(v,Symbol) for v in args]):
1919            return symfn.minimum(*args)
1920      out=None      out=None
1921      for a in args:      for a in args:
1922         if out==None:         if out==None:
1923            #out=a*1            if isinstance(a, numpy.ndarray):
           if isinstance(a, numpy.ndarray):  #Coz rank0 array * a scalar = scalar not array  
1924                out=a.copy()                out=a.copy()
1925            else:            else:
1926                out=a*1                out=a*1.
1927         else:         else:
1928            if isinstance(out,escript.Data) and isinstance(a,escript.Data):            if isinstance(out,escript.Data) and isinstance(a,escript.Data):
1929               if out.getRank()==0 and a.getRank()>0:               if out.getRank()==0 and a.getRank()>0:
1930              #We need to consider the case where we have scalars and higher                  # We need to consider the case where we have scalars and
1931          #ranked objects mixed. If the scalar was first it will get                  # higher ranked objects mixed. If the scalar was first it will
1932          #picked as the initial out and we have a problem,                  # get picked as the initial out and we have a problem, so we
1933          #so we swap the objects                  # swap the objects
1934                  res=a.copy()    #Deep copy of a                  res=a.copy() # Deep copy of a
1935                  res.copyWithMask(out,whereNegative(out-a))                  res.copyWithMask(out,whereNegative(out-a))
1936                  out=res                  out=res
1937               else:               else:
1938                  out.copyWithMask(a,whereNegative(a-out))                  out.copyWithMask(a,whereNegative(a-out))
1939            else:            else:
1940               diff=add(a,-out)               if isinstance(a, numpy.ndarray):
1941                    diff=-out+a
1942                 else:
1943                    diff=a-out
1944               #out=add(out,mult(whereNegative(diff),diff))               #out=add(out,mult(whereNegative(diff),diff))
1945               temp=add(mult(out, whereNonNegative(diff)), mult(a, whereNegative(diff)))               temp=mult(whereNonNegative(diff),out)+mult(whereNegative(diff),a)
1946               if isinstance(out,numpy.ndarray) and isinstance(a,numpy.ndarray):               if isinstance(out,numpy.ndarray) and isinstance(a,numpy.ndarray):
1947             # we need to convert the result to an array                  # we need to convert the result to an array
1948                 temp=numpy.array(temp)                  temp=numpy.array(temp)
1949               out=temp               out=temp
1950      return out      return out
1951    
# Line 4874  def clip(arg,minval=None,maxval=None): Line 1966  def clip(arg,minval=None,maxval=None):
1966              ``float`` depending on the input              ``float`` depending on the input
1967      :raise ValueError: if ``minval>maxval``      :raise ValueError: if ``minval>maxval``
1968      """      """
1969        if isinstance(arg, Symbol):
1970            clip_item=lambda item: symfn.clip(item, minval, maxval)
1971            return arg.applyfunc(clip_item)
1972      if not minval==None and not maxval==None:      if not minval==None and not maxval==None:
1973         if minval>maxval:         if minval>maxval:
1974            raise ValueError("minval = %s must be less than maxval %s"%(minval,maxval))            raise ValueError("minval = %s must be less than maxval %s"%(minval,maxval))
# Line 4886  def clip(arg,minval=None,maxval=None): Line 1981  def clip(arg,minval=None,maxval=None):
1981      else:      else:
1982          return minimum(tmp,maxval)          return minimum(tmp,maxval)
1983    
   
1984  def inner(arg0,arg1):  def inner(arg0,arg1):
1985      """      """
1986      Inner product of the two arguments. The inner product is defined as:      Inner product of the two arguments. The inner product is defined as:
# Line 4898  def inner(arg0,arg1): Line 1992  def inner(arg0,arg1):
1992      ``arg0`` and ``arg1`` must have the same shape.      ``arg0`` and ``arg1`` must have the same shape.
1993    
1994      :param arg0: first argument      :param arg0: first argument
1995      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
1996      :param arg1: second argument      :param arg1: second argument
1997      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
1998      :return: the inner product of ``arg0`` and ``arg1`` at each data point      :return: the inner product of ``arg0`` and ``arg1`` at each data point
1999      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``
2000              depending on the input              depending on the input
# Line 4925  def outer(arg0,arg1): Line 2017  def outer(arg0,arg1):
2017          - t runs through ``arg1.Shape``          - t runs through ``arg1.Shape``
2018    
2019      :param arg0: first argument      :param arg0: first argument
2020      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2021      :param arg1: second argument      :param arg1: second argument
2022      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2023      :return: the outer product of ``arg0`` and ``arg1`` at each data point      :return: the outer product of ``arg0`` and ``arg1`` at each data point
2024      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2025      """      """
2026      return generalTensorProduct(arg0,arg1,axis_offset=0)      return generalTensorProduct(arg0,arg1,axis_offset=0)
2027    
# Line 4961  def matrix_mult(arg0,arg1): Line 2050  def matrix_mult(arg0,arg1):
2050      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`
2051      :return: the matrix-matrix or matrix-vector product of ``arg0`` and ``arg1``      :return: the matrix-matrix or matrix-vector product of ``arg0`` and ``arg1``
2052               at each data point               at each data point
2053      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2054      :raise ValueError: if the shapes of the arguments are not appropriate      :raise ValueError: if the shapes of the arguments are not appropriate
2055      """      """
2056      sh0=getShape(arg0)      sh0=getShape(arg0)
# Line 5013  def tensor_mult(arg0,arg1): Line 2101  def tensor_mult(arg0,arg1):
2101                   rank of ``arg0``                   rank of ``arg0``
2102      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`
2103      :return: the tensor product of ``arg0`` and ``arg1`` at each data point      :return: the tensor product of ``arg0`` and ``arg1`` at each data point
2104      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2105      """      """
2106      sh0=getShape(arg0)      sh0=getShape(arg0)
2107      sh1=getShape(arg1)      sh1=getShape(arg1)
2108      if len(sh0)==2 and ( len(sh1)==2 or len(sh1)==1 ):      if len(sh0)==2 and ( len(sh1)==2 or len(sh1)==1 ):
2109         return generalTensorProduct(arg0,arg1,axis_offset=1)          return generalTensorProduct(arg0,arg1,axis_offset=1)
2110      elif len(sh0)==4 and (len(sh1)==2 or len(sh1)==3 or len(sh1)==4):      elif len(sh0)==4 and (len(sh1)==2 or len(sh1)==3 or len(sh1)==4):
2111         return generalTensorProduct(arg0,arg1,axis_offset=2)          return generalTensorProduct(arg0,arg1,axis_offset=2)
2112      else:      else:
2113          raise ValueError("tensor_mult: first argument must have rank 2 or 4")          raise ValueError("tensor_mult: first argument must have rank 2 or 4")
2114    
# Line 5037  def generalTensorProduct(arg0,arg1,axis_ Line 2124  def generalTensorProduct(arg0,arg1,axis_
2124          - t runs through ``arg1.Shape[axis_offset:]``          - t runs through ``arg1.Shape[axis_offset:]``
2125    
2126      :param arg0: first argument      :param arg0: first argument
2127      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2128      :param arg1: second argument      :param arg1: second argument
2129      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2130      :return: the general tensor product of ``arg0`` and ``arg1`` at each data      :return: the general tensor product of ``arg0`` and ``arg1`` at each data
2131               point               point
2132      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2133      """      """
2134      if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0      if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0
2135      arg0,arg1=matchType(arg0,arg1)      arg0,arg1=matchType(arg0,arg1)
2136      # at this stage arg0 and arg1 are both numpy.ndarray or escript.Data or      # at this stage arg0 and arg1 are both numpy.ndarray or escript.Data,
2137      # Symbols      # or one is a Symbol and the other either of the allowed types
2138      if isinstance(arg0,numpy.ndarray):      if isinstance(arg0,Symbol):
2139         if isinstance(arg1,Symbol):         sh0=arg0.getShape()
2140             return GeneralTensorProduct_Symbol(arg0,arg1,axis_offset)         sh1=getShape(arg1)
2141         else:         if not sh0[arg0.getRank()-axis_offset:]==sh1[:axis_offset]:
2142             if not arg0.shape[arg0.ndim-axis_offset:]==arg1.shape[:axis_offset]:            raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))
2143                 raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))         if isinstance(arg1,float):
2144             arg0_c=arg0.copy()            return arg0*arg1
2145             arg1_c=arg1.copy()         elif isinstance(arg1,numpy.ndarray) or isinstance(arg1, Symbol):
2146             sh0,sh1=arg0.shape,arg1.shape            return arg0.tensorProduct(arg1, axis_offset)
2147             d0,d1,d01=1,1,1         elif isinstance(arg1, escript.Data):
2148             for i in sh0[:arg0.ndim-axis_offset]: d0*=i            raise TypeError("tensor product of Symbol and Data not supported yet")
2149             for i in sh1[axis_offset:]: d1*=i      elif isinstance(arg0,numpy.ndarray):
2150             for i in sh1[:axis_offset]: d01*=i         if not arg0.shape[arg0.ndim-axis_offset:]==arg1.shape[:axis_offset]:
2151             arg0_c.resize((d0,d01))            raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))
2152             arg1_c.resize((d01,d1))         arg0_c=arg0.copy()
2153             out=numpy.zeros((d0,d1),numpy.float64)         arg1_c=arg1.copy()
2154             for i0 in range(d0):         sh0,sh1=arg0.shape,arg1.shape
2155                      for i1 in range(d1):         d0,d1,d01=1,1,1
2156                           out[i0,i1]=numpy.sum(arg0_c[i0,:]*arg1_c[:,i1])         for i in sh0[:arg0.ndim-axis_offset]: d0*=i
2157             out.resize(sh0[:arg0.ndim-axis_offset]+sh1[axis_offset:])         for i in sh1[axis_offset:]: d1*=i
2158             return out         for i in sh1[:axis_offset]: d01*=i
2159           arg0_c.resize((d0,d01))
2160           arg1_c.resize((d01,d1))
2161           out=numpy.zeros((d0,d1),numpy.float64)
2162           for i0 in range(d0):
2163              for i1 in range(d1):
2164                 out[i0,i1]=numpy.sum(arg0_c[i0,:]*arg1_c[:,i1])
2165           out.resize(sh0[:arg0.ndim-axis_offset]+sh1[axis_offset:])
2166           return out
2167      elif isinstance(arg0,escript.Data):      elif isinstance(arg0,escript.Data):
2168         if isinstance(arg1,Symbol):         if isinstance(arg1, Symbol):
2169             return GeneralTensorProduct_Symbol(arg0,arg1,axis_offset)            raise TypeError("tensor product of Data and Symbol not supported yet")
2170         else:         return escript_generalTensorProduct(arg0,arg1,axis_offset) # this call has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset)
2171             return escript_generalTensorProduct(arg0,arg1,axis_offset) # this calls has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset)      raise TypeError("generalTensorProduct: Unsupported argument type")
     else:  
        return GeneralTensorProduct_Symbol(arg0,arg1,axis_offset)  
   
 class GeneralTensorProduct_Symbol(DependendSymbol):  
    """  
    Symbol representing the general tensor product of two arguments.  
    """  
    def __init__(self,arg0,arg1,axis_offset=0):  
        """  
        Initialization of `Symbol` representing the general tensor product of  
        two arguments.  
   
        :param arg0: first argument  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: second argument  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: illegal dimension  
        :note: if both arguments have a spatial dimension, they must be equal.  
        """  
        sh_arg0=getShape(arg0)  
        sh_arg1=getShape(arg1)  
        sh0=sh_arg0[:len(sh_arg0)-axis_offset]  
        sh01=sh_arg0[len(sh_arg0)-axis_offset:]  
        sh10=sh_arg1[:axis_offset]  
        sh1=sh_arg1[axis_offset:]  
        if not sh01==sh10:  
            raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))  
        DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0+sh1,args=[arg0,arg1,axis_offset])  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str" or format=="text":  
          return "generalTensorProduct(%s,%s,axis_offset=%s)"%(argstrs[0],argstrs[1],argstrs[2])  
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          return generalTensorProduct(args[0],args[1],args[2])  
2172    
2173  def escript_generalTensorProduct(arg0,arg1,axis_offset,transpose=0):  def escript_generalTensorProduct(arg0,arg1,axis_offset,transpose=0):
2174      "arg0 and arg1 are both Data objects but not necessarily on the same function space. They could be identical!!!"      "arg0 and arg1 are both Data objects but not necessarily on the same function space. They could be identical!!!"
# Line 5179  def transposed_matrix_mult(arg0,arg1): Line 2196  def transposed_matrix_mult(arg0,arg1):
2196      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`
2197      :return: the product of the transpose of ``arg0`` and ``arg1`` at each data      :return: the product of the transpose of ``arg0`` and ``arg1`` at each data
2198               point               point
2199      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2200      :raise ValueError: if the shapes of the arguments are not appropriate      :raise ValueError: if the shapes of the arguments are not appropriate
2201      """      """
2202      sh0=getShape(arg0)      sh0=getShape(arg0)
# Line 5228  def transposed_tensor_mult(arg0,arg1): Line 2244  def transposed_tensor_mult(arg0,arg1):
2244                   rank of ``arg0``                   rank of ``arg0``
2245      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`
2246      :return: the tensor product of transpose of arg0 and arg1 at each data point      :return: the tensor product of transpose of arg0 and arg1 at each data point
2247      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2248      """      """
2249      sh0=getShape(arg0)      sh0=getShape(arg0)
2250      sh1=getShape(arg1)      sh1=getShape(arg1)
# Line 5256  def generalTransposedTensorProduct(arg0, Line 2271  def generalTransposedTensorProduct(arg0,
2271      ``generalTensorProduct(transpose(arg0,arg0.ndim-axis_offset),arg1,axis_offset)``.      ``generalTensorProduct(transpose(arg0,arg0.ndim-axis_offset),arg1,axis_offset)``.
2272    
2273      :param arg0: first argument      :param arg0: first argument
2274      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2275      :param arg1: second argument      :param arg1: second argument
2276      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2277      :return: the general tensor product of ``transpose(arg0)`` and ``arg1`` at      :return: the general tensor product of ``transpose(arg0)`` and ``arg1`` at
2278               each data point               each data point
2279      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2280      """      """
2281      if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0      if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0
2282      arg0,arg1=matchType(arg0,arg1)      arg0,arg1=matchType(arg0,arg1)
2283      # at this stage arg0 and arg1 are both numpy.ndarray or escript.Data or      # at this stage arg0 and arg1 are both numpy.ndarray or escript.Data,
2284      # Symbols      # or one is a Symbol and the other either of the allowed types
2285      if isinstance(arg0,numpy.ndarray):      if isinstance(arg0,Symbol):
2286         if isinstance(arg1,Symbol):         sh0=arg0.getShape()
2287             return GeneralTransposedTensorProduct_Symbol(arg0,arg1,axis_offset)         sh1=getShape(arg1)
2288         else:         if not sh0[:axis_offset]==sh1[:axis_offset]:
2289             if not arg0.shape[:axis_offset]==arg1.shape[:axis_offset]:            raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))
2290                 raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))         if isinstance(arg1,float):
2291             arg0_c=arg0.copy()            return arg0*arg1
2292             arg1_c=arg1.copy()         elif isinstance(arg1,numpy.ndarray) or isinstance(arg1, Symbol):
2293             sh0,sh1=arg0.shape,arg1.shape            return arg0.transposedTensorProduct(arg1, axis_offset)
2294             d0,d1,d01=1,1,1         elif isinstance(arg1, escript.Data):
2295             for i in sh0[axis_offset:]: d0*=i            raise TypeError("tensor product of Symbol and Data not supported yet")
2296             for i in sh1[axis_offset:]: d1*=i      elif isinstance(arg0,numpy.ndarray):
2297             for i in sh0[:axis_offset]: d01*=i         if not arg0.shape[:axis_offset]==arg1.shape[:axis_offset]:
            arg0_c.resize((d01,d0))  
            arg1_c.resize((d01,d1))  
            out=numpy.zeros((d0,d1),numpy.float64)  
            for i0 in range(d0):  
                     for i1 in range(d1):  
                          out[i0,i1]=numpy.sum(arg0_c[:,i0]*arg1_c[:,i1])  
            out.resize(sh0[axis_offset:]+sh1[axis_offset:])  
            return out  
     elif isinstance(arg0,escript.Data):  
        if isinstance(arg1,Symbol):  
            return GeneralTransposedTensorProduct_Symbol(arg0,arg1,axis_offset)  
        else:  
            # this call has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset)  
            return escript_generalTransposedTensorProduct(arg0,arg1,axis_offset)  
     else:  
        return GeneralTransposedTensorProduct_Symbol(arg0,arg1,axis_offset)  
   
 class GeneralTransposedTensorProduct_Symbol(DependendSymbol):  
    """  
    Symbol representing the general tensor product of the transpose of ``arg0``  
    and ``arg1``  
    """  
    def __init__(self,arg0,arg1,axis_offset=0):  
        """  
        Initialization of `Symbol` representing tensor product of the  
        transpose of ``arg0`` and ``arg1``.  
   
        :param arg0: first argument  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: second argument  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: inconsistent dimensions of arguments  
        :note: if both arguments have a spatial dimension, they must be equal.  
        """  
        sh_arg0=getShape(arg0)  
        sh_arg1=getShape(arg1)  
        sh01=sh_arg0[:axis_offset]  
        sh10=sh_arg1[:axis_offset]  
        sh0=sh_arg0[axis_offset:]  
        sh1=sh_arg1[axis_offset:]  
        if not sh01==sh10:  
2298             raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))             raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))
2299         DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0+sh1,args=[arg0,arg1,axis_offset])         arg0_c=arg0.copy()
2300           arg1_c=arg1.copy()
2301     def getMyCode(self,argstrs,format="escript"):         sh0,sh1=arg0.shape,arg1.shape
2302        """         d0,d1,d01=1,1,1
2303        Returns program code that can be used to evaluate the symbol.         for i in sh0[axis_offset:]: d0*=i
2304           for i in sh1[axis_offset:]: d1*=i
2305        :param argstrs: a string for each argument representing the argument         for i in sh0[:axis_offset]: d01*=i
2306                        for the evaluation         arg0_c.resize((d01,d0))
2307        :type argstrs: ``str`` or a ``list`` of length 2 of ``str``         arg1_c.resize((d01,d1))
2308        :param format: specifies the format to be used. At the moment only         out=numpy.zeros((d0,d1),numpy.float64)
2309                       "escript", "str" and "text" are supported.         for i0 in range(d0):
2310        :type format: ``str``                  for i1 in range(d1):
2311        :return: a piece of program code which can be used to evaluate the                       out[i0,i1]=numpy.sum(arg0_c[:,i0]*arg1_c[:,i1])
2312                 expression assuming the values for the arguments are available         out.resize(sh0[axis_offset:]+sh1[axis_offset:])
2313        :rtype: ``str``         return out
2314        :raise NotImplementedError: if no implementation for the given format      elif isinstance(arg0,escript.Data):
2315                                    is available         if isinstance(arg1, Symbol):
2316        """            raise TypeError("tensor product of Data and Symbol not supported yet")
2317        if format=="escript" or format=="str" or format=="text":         # this call has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset)
2318           return "generalTransposedTensorProduct(%s,%s,axis_offset=%s)"%(argstrs[0],argstrs[1],argstrs[2])         return escript_generalTransposedTensorProduct(arg0,arg1,axis_offset)
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          return generalTransposedTensorProduct(args[0],args[1],args[2])  
2319    
2320  # this should be escript._generalTransposedTensorProduct  # this should be escript._generalTransposedTensorProduct
2321  def escript_generalTransposedTensorProduct(arg0,arg1,axis_offset):  def escript_generalTransposedTensorProduct(arg0,arg1,axis_offset):
# Line 5396  def matrix_transposed_mult(arg0,arg1): Line 2339  def matrix_transposed_mult(arg0,arg1):
2339      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`
2340      :return: the product of ``arg0`` and the transposed of ``arg1`` at each data      :return: the product of ``arg0`` and the transposed of ``arg1`` at each data
2341               point               point
2342      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2343      :raise ValueError: if the shapes of the arguments are not appropriate      :raise ValueError: if the shapes of the arguments are not appropriate
2344      """      """
2345      sh0=getShape(arg0)      sh0=getShape(arg0)
# Line 5438  def tensor_transposed_mult(arg0,arg1): Line 2380  def tensor_transposed_mult(arg0,arg1):
2380      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`
2381      :return: the tensor product of the transposed of ``arg0`` and ``arg1`` at      :return: the tensor product of the transposed of ``arg0`` and ``arg1`` at
2382               each data point               each data point
2383      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2384      """      """
2385      sh0=getShape(arg0)      sh0=getShape(arg0)
2386      sh1=getShape(arg1)      sh1=getShape(arg1)
# Line 5466  def generalTensorTransposedProduct(arg0, Line 2407  def generalTensorTransposedProduct(arg0,
2407      ``generalTensorProduct(arg0,transpose(arg1,arg1.ndim-axis_offset),axis_offset)``.      ``generalTensorProduct(arg0,transpose(arg1,arg1.ndim-axis_offset),axis_offset)``.
2408    
2409      :param arg0: first argument      :param arg0: first argument
2410      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg0: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2411      :param arg1: second argument      :param arg1: second argument
2412      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``,      :type arg1: ``numpy.ndarray``, `escript.Data`, `Symbol`, ``float``, ``int``
                 ``int``  
2413      :return: the general tensor product of ``arg0`` and ``transpose(arg1)`` at      :return: the general tensor product of ``arg0`` and ``transpose(arg1)`` at
2414               each data point               each data point
2415      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the      :rtype: ``numpy.ndarray``, `escript.Data`, `Symbol` depending on the input
             input  
2416      """      """
2417      if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0      if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0
2418      arg0,arg1=matchType(arg0,arg1)      arg0,arg1=matchType(arg0,arg1)
2419      # at this stage arg0 and arg1 are both numpy.ndarray or escript.Data or      # at this stage arg0 and arg1 are both numpy.ndarray or escript.Data,
2420      # Symbols      # or one is a Symbol and the other either of the allowed types
2421      if isinstance(arg0,numpy.ndarray):      if isinstance(arg0,Symbol):
2422         if isinstance(arg1,Symbol):         sh0=arg0.getShape()
2423             return GeneralTensorTransposedProduct_Symbol(arg0,arg1,axis_offset)         sh1=getShape(arg1)
2424         else:         r1=getRank(arg1)
2425             if not arg0.shape[arg0.ndim-axis_offset:]==arg1.shape[arg1.ndim-axis_offset:]:         if not sh0[arg0.getRank()-axis_offset:]==sh1[r1-axis_offset:]:
2426                 raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))            raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))
2427             arg0_c=arg0.copy()         if isinstance(arg1,float):
2428             arg1_c=arg1.copy()            return arg0*arg1
2429             sh0,sh1=arg0.shape,arg1.shape         elif isinstance(arg1,numpy.ndarray) or isinstance(arg1, Symbol):
2430             d0,d1,d01=1,1,1            return arg0.tensorTransposedProduct(arg1, axis_offset)
2431             for i in sh0[:arg0.ndim-axis_offset]: d0*=i         elif isinstance(arg1, escript.Data):
2432             for i in sh1[:arg1.ndim-axis_offset]: d1*=i            raise TypeError("tensor product of Symbol and Data not supported yet")
2433             for i in sh1[arg1.ndim-axis_offset:]: d01*=i      elif isinstance(arg0,numpy.ndarray):
2434             arg0_c.resize((d0,d01))         if not arg0.shape[arg0.ndim-axis_offset:]==arg1.shape[arg1.ndim-axis_offset:]:
2435             arg1_c.resize((d1,d01))            raise ValueError("dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset))
2436             out=numpy.zeros((d0,d1),numpy.float64)         arg0_c=arg0.copy()
2437             for i0 in range(d0):         arg1_c=arg1.copy()
2438                      for i1 in range(d1):         sh0,sh1=arg0.shape,arg1.shape
2439                           out[i0,i1]=numpy.sum(arg0_c[i0,:]*arg1_c[i1,:])         d0,d1,d01=1,1,1
2440             out.resize(sh0[:arg0.ndim-axis_offset]+sh1[:arg1.ndim-axis_offset])         for i in sh0[:arg0.ndim-axis_offset]: d0*=i
2441             return out         for i in sh1[:arg1.ndim-axis_offset]: d1*=i
2442           for i in sh1[arg1.ndim-axis_offset:]: d01*=i
2443           arg0_c.resize((d0,d01))
2444           arg1_c.resize((d1,d01))
2445           out=numpy.zeros((d0,d1),numpy.float64)
2446           for i0 in range(d0):
2447              for i1 in range(d1):
2448                 out[i0,i1]=numpy.sum(arg0_c[i0,:]*arg1_c[i1,:])
2449           out.resize(sh0[:arg0.ndim-axis_offset]+sh1[:arg1.ndim-axis_offset])
2450           return out
2451      elif isinstance(arg0,escript.Data):      elif isinstance(arg0,escript.Data):
2452         if isinstance(arg1,Symbol):         if isinstance(arg1, Symbol):
2453             return GeneralTensorTransposedProduct_Symbol(arg0,arg1,axis_offset)            raise TypeError("tensor product of Data and Symbol not supported yet")
2454         else:         # this call has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset)
2455             # this call has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset)         return escript_generalTensorTransposedProduct(arg0,arg1,axis_offset)
            return escript_generalTensorTransposedProduct(arg0,arg1,axis_offset)  
     else:  
        return GeneralTensorTransposedProduct_Symbol(arg0,arg1,axis_offset)  
   
 class GeneralTensorTransposedProduct_Symbol(DependendSymbol):  
    """  
    Symbol representing the general tensor product of ``arg0`` and the transpose  
    of ``arg1``.  
    """  
    def __init__(self,arg0,arg1,axis_offset=0):  
        """  
        Initialization of `Symbol` representing the general tensor product of  
        ``arg0`` and the transpose of ``arg1``.  
   
        :param arg0: first argument  
        :type arg0: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :param arg1: second argument  
        :type arg1: `escript.Symbol`, ``float``, `escript.Data`,  
                    ``numpy.ndarray``  
        :raise ValueError: inconsistent dimensions of arguments  
        :note: if both arguments have a spatial dimension, they must be equal.  
        """  
        sh_arg0=getShape(arg0)  
        sh_arg1=getShape(arg1)  
        sh0=sh_arg0[:len(sh_arg0)-axis_offset]  
        sh01=sh_arg0[len(sh_arg0)-axis_offset:]  
        sh10=sh_arg1[len(sh_arg1)-axis_offset:]  
        sh1=sh_arg1[:len(sh_arg1)-axis_offset]  
        if not sh01==sh10:  
            raise ValueError("dimensions of last %s components in left argument don't match the last %s components in the right argument."%(axis_offset,axis_offset))  
        DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0+sh1,args=[arg0,arg1,axis_offset])  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str" or format=="text":  
          return "generalTensorTransposedProduct(%s,%s,axis_offset=%s)"%(argstrs[0],argstrs[1],argstrs[2])  
       else:  
          raise NotImplementedError("%s does not provide program code for format %s."%(str(self),format))  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          args=self.getSubstitutedArguments(argvals)  
          return generalTensorTransposedProduct(args[0],args[1],args[2])  
2456    
2457  # this should be escript._generalTensorTransposedProduct  # this should be escript._generalTensorTransposedProduct
2458  def escript_generalTensorTransposedProduct(arg0,arg1,axis_offset):  def escript_generalTensorTransposedProduct(arg0,arg1,axis_offset):
# Line 5617  def grad(arg,where=None): Line 2487  def grad(arg,where=None):
2487      :rtype: `escript.Data` or `Symbol`      :rtype: `escript.Data` or `Symbol`
2488      """      """
2489      if isinstance(arg,Symbol):      if isinstance(arg,Symbol):
2490         return Grad_Symbol(arg,where)         if where is None:
2491               return arg.grad()
2492           else:
2493               return arg.grad(where)
2494      elif isinstance(arg,escript.Data):      elif isinstance(arg,escript.Data):
2495         if where==None:         if where==None:
2496            return arg._grad()            return arg._grad()
# Line 5626  def grad(arg,where=None): Line 2499  def grad(arg,where=None):
2499      else:      else:
2500         raise TypeError("grad: Unknown argument type.")         raise TypeError("grad: Unknown argument type.")
2501    
2502  class Grad_Symbol(DependendSymbol):  def grad_n(arg, n, where=None):
2503     """      return grad(arg, where)[n]
    `Symbol` representing the result of the gradient operator.  
    """  
    def __init__(self,arg,where=None):  
       """  
       Initialization of gradient `Symbol` with argument ``arg``.  
   
       :param arg: argument of function  
       :type arg: `Symbol`  
       :param where: FunctionSpace in which the gradient will be calculated.  
                     If not present or ``None`` an appropriate default is used.  
       :type where: ``None`` or `escript.FunctionSpace`  
       """  
       d=arg.getDim()  
       if d==None:  
          raise ValueError("argument must have a spatial dimension")  
       super(Grad_Symbol,self).__init__(args=[arg,where],shape=arg.getShape()+(d,),dim=d)  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "grad(%s,where=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("Grad_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return grad(arg[0],where=arg[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to arg  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return grad(self.getDifferentiatedArguments(arg)[0],where=self.getArgument()[1])  
2504    
2505  def integrate(arg,where=None):  def integrate(arg,where=None):
2506      """      """
# Line 5718  def integrate(arg,where=None): Line 2515  def integrate(arg,where=None):
2515      :return: integral of ``arg``      :return: integral of ``arg``
2516      :rtype: ``float``, ``numpy.ndarray`` or `Symbol`      :rtype: ``float``, ``numpy.ndarray`` or `Symbol`
2517      """      """
2518      if isinstance(arg,Symbol):      if isinstance(arg,escript.Data):
        return Integrate_Symbol(arg,where)  
     elif isinstance(arg,escript.Data):  
2519         if not where==None: arg=escript.Data(arg,where)         if not where==None: arg=escript.Data(arg,where)
2520         if arg.getRank()==0:         if arg.getRank()==0:
2521            return arg._integrateToTuple()[0]            return arg._integrateToTuple()[0]
2522         else:         else:
2523            return numpy.array(arg._integrateToTuple())            return numpy.array(arg._integrateToTuple())
2524        elif isinstance(arg,Symbol):
2525           return symfn.integrate(arg, where)
2526      else:      else:
2527         arg2=escript.Data(arg,where)         arg2=escript.Data(arg,where)
2528         if arg2.getRank()==0:         if arg2.getRank()==0:
# Line 5733  def integrate(arg,where=None): Line 2530  def integrate(arg,where=None):
2530         else:         else:
2531            return numpy.array(arg2._integrateToTuple())            return numpy.array(arg2._integrateToTuple())
2532    
 class Integrate_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the spatial integration operator.  
    """  
    def __init__(self,arg,where=None):  
       """  
       Initialization of integration `Symbol` with argument ``arg``.  
   
       :param arg: argument of the integration  
       :type arg: `Symbol`  
       :param where: FunctionSpace in which the integration will be performed.  
                     If not present or ``None`` an appropriate default is used.  
       :type where: ``None`` or `escript.FunctionSpace`  
       """  
       super(Integrate_Symbol,self).__init__(args=[arg,where],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "integrate(%s,where=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("Integrate_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return integrate(arg[0],where=arg[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: typically `Symbol` but other types such as ``float``,  
               `escript.Data`, ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return integrate(self.getDifferentiatedArguments(arg)[0],where=self.getArgument()[1])  
   
   
2533  def interpolate(arg,where):  def interpolate(arg,where):
2534      """      """
2535      Interpolates the function into the `FunctionSpace` ``where``. If the      Interpolates the function into the `FunctionSpace` ``where``. If the
# Line 5823  def interpolate(arg,where): Line 2543  def interpolate(arg,where):
2543      :return: interpolated argument      :return: interpolated argument
2544      :rtype: ``escript.Data`` or `Symbol`      :rtype: ``escript.Data`` or `Symbol`
2545      """      """
2546      if isinstance(arg,Symbol):      if isinstance(arg,escript.Data):
        return Interpolate_Symbol(arg,where)  
     elif isinstance(arg,escript.Data):  
2547         if arg.isEmpty():         if arg.isEmpty():
2548            return arg            return arg
2549         elif where == arg.getFunctionSpace():         elif where == arg.getFunctionSpace():
2550            return arg            return arg
2551         else:         else:
2552            return escript.Data(arg,where)            return escript.Data(arg,where)
2553        elif isinstance(arg,Symbol):
2554           return symfn.interpolate(arg, where)
2555      else:      else:
2556         return escript.Data(arg,where)         return escript.Data(arg,where)
2557    
 class Interpolate_Symbol(DependendSymbol):  
    """  
    `Symbol` representing the result of the interpolation operator.  
    """  
    def __init__(self,arg,where):  
       """  
       Initialization of interpolation `Symbol` with argument ``arg``.  
   
       :param arg: argument of the interpolation  
       :type arg: `Symbol`  
       :param where: `FunctionSpace` into which the argument is interpolated  
       :type where: `escript.FunctionSpace`  
       """  
       super(Interpolate_Symbol,self).__init__(args=[arg,where],shape=arg.getShape(),dim=arg.getDim())  
   
    def getMyCode(self,argstrs,format="escript"):  
       """  
       Returns program code that can be used to evaluate the symbol.  
   
       :param argstrs: a string for each argument representing the argument  
                       for the evaluation  
       :type argstrs: ``str`` or a ``list`` of length 2 of ``str``  
       :param format: specifies the format to be used. At the moment only  
                      "escript", "str" and "text" are supported.  
       :type format: ``str``  
       :return: a piece of program code which can be used to evaluate the  
                expression assuming the values for the arguments are available  
       :rtype: ``str``  
       :raise NotImplementedError: if no implementation for the given format  
                                   is available  
       """  
       if format=="escript" or format=="str"  or format=="text":  
          return "interpolate(%s,where=%s)"%(argstrs[0],argstrs[1])  
       else:  
          raise NotImplementedError("Interpolate_Symbol does not provide program code for format %s."%format)  
   
    def substitute(self,argvals):  
       """  
       Assigns new values to symbols in the definition of the symbol.  
       The method replaces the `Symbol` u by argvals[u] in the expression  
       defining this object.  
   
       :param argvals: new values assigned to symbols  
       :type argvals: ``dict`` with keywords of type `Symbol`  
       :return: result of the substitution process. Operations are executed as  
                much as possible.  
       :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``  
               depending on the degree of substitution  
       :raise TypeError: if a value for a `Symbol` cannot be substituted  
       """  
       if self in argvals:  
          arg=argvals[self]  
          if self.isAppropriateValue(arg):  
             return arg  
          else:  
             raise TypeError("%s: new value is not appropriate."%str(self))  
       else:  
          arg=self.getSubstitutedArguments(argvals)  
          return interpolate(arg[0],where=arg[1])  
   
    def diff(self,arg):  
       """  
       Differential of this object.  
   
       :param arg: the derivative is calculated with respect to ``arg``  
       :type arg: `escript.Symbol`  
       :return: derivative with respect to ``arg``  
       :rtype: `Symbol` but other types such as `escript.Data`,  
               ``numpy.ndarray`` are possible  
       """  
       if arg==self:  
          return identity(self.getShape())  
       else:  
          return interpolate(self.getDifferentiatedArguments(arg)[0],where=self.getArgument()[1])  
   
   
2558  def div(arg,where=None):  def div(arg,where=None):
2559      """      """
2560      Returns the divergence of ``arg`` at ``where``.      Returns the divergence of ``arg`` at ``where``.
# Line 5924  def div(arg,where=None): Line 2568  def div(arg,where=None):
2568      :return: divergence of ``arg``      :return: divergence of ``arg``
2569      :rtype: `escript.Data` or `Symbol`      :rtype: `escript.Data` or `Symbol`
2570      """      """
2571      if isinstance(arg,Symbol):      if isinstance(arg,escript.Data):
         dim=arg.getDim()  
     elif isinstance(arg,escript.Data):  
2572          dim=arg.getDomain().getDim()          dim=arg.getDomain().getDim()
2573      else:          if not arg.getShape()==(dim,):
2574                raise ValueError("div: expected shape is (%s,)"%dim)
2575        elif not isinstance(arg, Symbol):
2576          raise TypeError("div: argument type not supported")          raise TypeError("div: argument type not supported")
     if not arg.getShape()==(dim,):  
       raise ValueError("div: expected shape is (%s,)"%dim)  
2577      return trace(grad(arg,where))      return trace(grad(arg,where))
2578    
2579  def jump(arg,domain=None):  def jump(arg,domain=None):
# Line 5942  def jump(arg,domain=None): Line 2584  def jump(arg,domain=None):
2584      :type arg: `escript.Data` or `Symbol`      :type arg: `escript.Data` or `Symbol`
2585      :param domain: the domain where the discontinuity is located. If domain is      :param domain: the domain where the discontinuity is located. If domain is
2586                     not present or equal to ``None`` the domain of ``arg`` is used.                     not present or equal to ``None`` the domain of ``arg`` is used.
                    If ``arg`` is a `Symbol` the domain must be present.  
2587      :type domain: ``None`` or `escript.Domain`      :type domain: ``None`` or `escript.Domain`
2588      :return: jump of ``arg``      :return: jump of ``arg``
2589      :rtype: `escript.Data` or `Symbol`      :rtype: `escript.Data` or `Symbol`
# Line 5960  def L2(arg): Line 2601  def L2(arg):
2601      :rtype: `float` or `Symbol`      :rtype: `float` or `Symbol`
2602      :note: L2(arg) is equivalent to ``sqrt(integrate(inner(arg,arg)))``      :note: L2(arg) is equivalent to ``sqrt(integrate(inner(arg,arg)))``
2603      """      """
2604        if isinstance(arg,Symbol):
2605            return symfn.L2(arg)
2606      return sqrt(integrate(inner(arg,arg)))      return sqrt(integrate(inner(arg,arg)))
2607    
2608  def getClosestValue(arg,origin=0):  def getClosestValue(arg,origin=0):
# Line 5967  def getClosestValue(arg,origin=0): Line 2610  def getClosestValue(arg,origin=0):
2610      Returns the value in ``arg`` which is closest to origin.      Returns the value in ``arg`` which is closest to origin.
2611    
2612      :param arg: function      :param arg: function
2613      :type arg: `escript.Data` or `Symbol`      :type arg: `escript.Data`
2614      :param origin: reference value      :param origin: reference value
2615      :type origin: ``float`` or `escript.Data`      :type origin: ``float`` or `escript.Data`
2616      :return: value in ``arg`` closest to origin      :return: value in ``arg`` closest to origin
2617      :rtype: ``numpy.ndarray`` or `Symbol`      :rtype: ``numpy.ndarray``
2618      """      """
2619      return arg.getValueOfGlobalDataPoint(*(length(arg-origin).minGlobalDataPoint()))      return arg.getValueOfGlobalDataPoint(*(length(arg-origin).minGlobalDataPoint()))
2620    
# Line 6230  class FileWriter(object): Line 2873  class FileWriter(object):
2873             errno=1             errno=1
2874          self.__handelerror(errno,e,"writing strings")          self.__handelerror(errno,e,"writing strings")
2875    
   
2876  def reorderComponents(arg,index):  def reorderComponents(arg,index):
2877      """      """
2878      Resorts the components of ``arg`` according to index.      Resorts the components of ``arg`` according to index.

Legend:
Removed from v.3974  
changed lines
  Added in v.3975

  ViewVC Help
Powered by ViewVC 1.1.26