/[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 123 by jgs, Fri Jul 8 04:08:13 2005 UTC revision 148 by jgs, Tue Aug 23 01:24:31 2005 UTC
# Line 13  TODO for Data: Line 13  TODO for Data:
13        
14    * implementation of outer outer(a,b)[:,*]=a[:]*b[*]    * implementation of outer outer(a,b)[:,*]=a[:]*b[*]
15    * trace: trace(arg,axis0=a0,axis1=a1)(:,&,*)=sum_i trace(:,i,&,i,*) (i are at index a0 and a1)    * trace: trace(arg,axis0=a0,axis1=a1)(:,&,*)=sum_i trace(:,i,&,i,*) (i are at index a0 and a1)
   
16  """  """
17    
18  import numarray  import numarray
19  import escript  import escript
20  #  
 #   escript constants (have to be consistent witj utilC.h  
 #  
 UNKNOWN=-1  
 EPSILON=1.e-15  
 Pi=numarray.pi  
 # some solver options:  
 NO_REORDERING=0  
 MINIMUM_FILL_IN=1  
 NESTED_DISSECTION=2  
 # solver methods  
 DEFAULT_METHOD=0  
 DIRECT=1  
 CHOLEVSKY=2  
 PCG=3  
 CR=4  
 CGS=5  
 BICGSTAB=6  
 SSOR=7  
 ILU0=8  
 ILUT=9  
 JACOBI=10  
 GMRES=11  
 PRES20=12  
   
 METHOD_KEY="method"  
 SYMMETRY_KEY="symmetric"  
 TOLERANCE_KEY="tolerance"  
   
 # supported file formats:  
 VRML=1  
 PNG=2  
 JPEG=3  
 JPG=3  
 PS=4  
 OOGL=5  
 BMP=6  
 TIFF=7  
 OPENINVENTOR=8  
 RENDERMAN=9  
 PNM=10  
21  #===========================================================  #===========================================================
22  #  a simple tool box to deal with _differentials of functions  # a simple tool box to deal with _differentials of functions
23  #===========================================================  #===========================================================
24    
25  class Symbol:  class Symbol:
# Line 165  class Symbol: Line 124  class Symbol:
124         else:         else:
125           return self           return self
126    
   
127     def __str__(self):     def __str__(self):
128         """returns a string representation of the symbol"""         """returns a string representation of the symbol"""
129         return self.__name         return self.__name
# Line 178  class Symbol: Line 136  class Symbol:
136            a=_matchShape([self,other])            a=_matchShape([self,other])
137            return Add_Symbol(a[0],a[1])            return Add_Symbol(a[0],a[1])
138    
   
139     def __radd__(self,other):     def __radd__(self,other):
140         """adds other to symbol self. if _testForZero(other) self is returned."""         """adds other to symbol self. if _testForZero(other) self is returned."""
141         return self+other         return self+other
# Line 301  class Tensor4Symbol(Symbol): Line 258  class Tensor4Symbol(Symbol):
258             d=dim             d=dim
259        Symbol.__init__(self,shape=(d,d,d,d),dim=d,name=name)        Symbol.__init__(self,shape=(d,d,d,d),dim=d,name=name)
260    
   
261  class Add_Symbol(Symbol):  class Add_Symbol(Symbol):
262     """symbol representing the sum of two arguments"""     """symbol representing the sum of two arguments"""
263     def __init__(self,arg0,arg1):     def __init__(self,arg0,arg1):
# Line 446  def _matchShape(args,shape=None): Line 402  def _matchShape(args,shape=None):
402              else:                else:  
403                  raise ValueError,"cannot adopt shape of %s to %s"%(str(args[i]),str(shape))                  raise ValueError,"cannot adopt shape of %s to %s"%(str(args[i]),str(shape))
404      return out        return out  
405    
406  #=========================================================  #=========================================================
407  #   wrapper for various mathematical functions:  #   wrappers for various mathematical functions:
408  #=========================================================  #=========================================================
409  def diff(arg,dep):  def diff(arg,dep):
410      """returns the derivative of arg with respect to dep. If arg is not Symbol object      """returns the derivative of arg with respect to dep. If arg is not Symbol object
# Line 531  class Log_Symbol(Symbol): Line 488  class Log_Symbol(Symbol):
488     def _diff(self,arg):     def _diff(self,arg):
489         return self.getDifferentiatedArguments(arg)[0]/self.getArgument(0)         return self.getDifferentiatedArguments(arg)[0]/self.getArgument(0)
490    
491    def ln(arg):
492        """
493        @brief applies the natural logarithmic function to arg
494        @param arg (input): argument
495        """
496        if isinstance(arg,Symbol):
497           return Ln_Symbol(arg)
498        elif hasattr(arg,"ln"):
499           return arg.log()
500        else:
501           return numarray.log(arg)
502    
503    class Ln_Symbol(Symbol):
504       """symbol representing natural logarithm of the argument"""
505       def __init__(self,arg):
506           Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])
507       def __str__(self):
508          return "ln(%s)"%str(self.getArgument(0))
509       def eval(self,argval):
510           return ln(self.getEvaluatedArguments(argval)[0])
511       def _diff(self,arg):
512           return self.getDifferentiatedArguments(arg)[0]/self.getArgument(0)
513    
514  def sin(arg):  def sin(arg):
515      """      """
516      @brief applies the sinus function to arg      @brief applies the sin function to arg
517      @param arg (input): argument      @param arg (input): argument
518      """      """
519      if isinstance(arg,Symbol):      if isinstance(arg,Symbol):
# Line 544  def sin(arg): Line 524  def sin(arg):
524         return numarray.sin(arg)         return numarray.sin(arg)
525    
526  class Sin_Symbol(Symbol):  class Sin_Symbol(Symbol):
527     """symbol representing logarithm of the argument"""     """symbol representing sin of the argument"""
528     def __init__(self,arg):     def __init__(self,arg):
529         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])
530     def __str__(self):     def __str__(self):
# Line 556  class Sin_Symbol(Symbol): Line 536  class Sin_Symbol(Symbol):
536    
537  def cos(arg):  def cos(arg):
538      """      """
539      @brief applies the sinus function to arg      @brief applies the cos function to arg
540      @param arg (input): argument      @param arg (input): argument
541      """      """
542      if isinstance(arg,Symbol):      if isinstance(arg,Symbol):
# Line 567  def cos(arg): Line 547  def cos(arg):
547         return numarray.cos(arg)         return numarray.cos(arg)
548    
549  class Cos_Symbol(Symbol):  class Cos_Symbol(Symbol):
550     """symbol representing logarithm of the argument"""     """symbol representing cos of the argument"""
551     def __init__(self,arg):     def __init__(self,arg):
552         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])
553     def __str__(self):     def __str__(self):
# Line 579  class Cos_Symbol(Symbol): Line 559  class Cos_Symbol(Symbol):
559    
560  def tan(arg):  def tan(arg):
561      """      """
562      @brief applies the sinus function to arg      @brief applies the tan function to arg
563      @param arg (input): argument      @param arg (input): argument
564      """      """
565      if isinstance(arg,Symbol):      if isinstance(arg,Symbol):
# Line 590  def tan(arg): Line 570  def tan(arg):
570         return numarray.tan(arg)         return numarray.tan(arg)
571    
572  class Tan_Symbol(Symbol):  class Tan_Symbol(Symbol):
573     """symbol representing logarithm of the argument"""     """symbol representing tan of the argument"""
574     def __init__(self,arg):     def __init__(self,arg):
575         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])
576     def __str__(self):     def __str__(self):
# Line 638  def maxval(arg): Line 618  def maxval(arg):
618         return arg         return arg
619    
620  class Max_Symbol(Symbol):  class Max_Symbol(Symbol):
621     """symbol representing the sign of the argument"""     """symbol representing the maximum value of the argument"""
622     def __init__(self,arg):     def __init__(self,arg):
623         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])
624     def __str__(self):     def __str__(self):
# Line 648  class Max_Symbol(Symbol): Line 628  class Max_Symbol(Symbol):
628    
629  def minval(arg):  def minval(arg):
630      """      """
631      @brief returns the maximum value of argument arg""      @brief returns the minimum value of argument arg""
632      @param arg (input): argument      @param arg (input): argument
633      """      """
634      if isinstance(arg,Symbol):      if isinstance(arg,Symbol):
# Line 661  def minval(arg): Line 641  def minval(arg):
641         return arg         return arg
642    
643  class Min_Symbol(Symbol):  class Min_Symbol(Symbol):
644     """symbol representing the sign of the argument"""     """symbol representing the minimum value of the argument"""
645     def __init__(self,arg):     def __init__(self,arg):
646         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])
647     def __str__(self):     def __str__(self):
# Line 671  class Min_Symbol(Symbol): Line 651  class Min_Symbol(Symbol):
651    
652  def wherePositive(arg):  def wherePositive(arg):
653      """      """
654      @brief returns the maximum value of argument arg""      @brief returns the positive values of argument arg""
655      @param arg (input): argument      @param arg (input): argument
656      """      """
657      if _testForZero(arg):      if _testForZero(arg):
# Line 699  class WherePositive_Symbol(Symbol): Line 679  class WherePositive_Symbol(Symbol):
679    
680  def whereNegative(arg):  def whereNegative(arg):
681      """      """
682      @brief returns the maximum value of argument arg""      @brief returns the negative values of argument arg""
683      @param arg (input): argument      @param arg (input): argument
684      """      """
685      if _testForZero(arg):      if _testForZero(arg):
# Line 725  class WhereNegative_Symbol(Symbol): Line 705  class WhereNegative_Symbol(Symbol):
705     def eval(self,argval):     def eval(self,argval):
706         return whereNegative(self.getEvaluatedArguments(argval)[0])         return whereNegative(self.getEvaluatedArguments(argval)[0])
707    
708    def maximum(arg0,arg1):
709        """return arg1 where arg1 is bigger then arg0 otherwise arg0 is returned"""
710        m=whereNegative(arg0-arg1)
711        return m*arg1+(1.-m)*arg0
712      
713    def minimum(arg0,arg1):
714        """return arg0 where arg1 is bigger then arg0 otherwise arg1 is returned"""
715        m=whereNegative(arg0-arg1)
716        return m*arg0+(1.-m)*arg1
717      
718  def outer(arg0,arg1):  def outer(arg0,arg1):
719     if _testForZero(arg0) or _testForZero(arg1):     if _testForZero(arg0) or _testForZero(arg1):
720        return 0        return 0
# Line 746  def outer(arg0,arg1): Line 736  def outer(arg0,arg1):
736            raise ValueError,"outer is not fully implemented yet."            raise ValueError,"outer is not fully implemented yet."
737    
738  class Outer_Symbol(Symbol):  class Outer_Symbol(Symbol):
739     """symbol representing the outer product of its two argument"""     """symbol representing the outer product of its two arguments"""
740     def __init__(self,arg0,arg1):     def __init__(self,arg0,arg1):
741         a=[arg0,arg1]         a=[arg0,arg1]
742         s=tuple(list(_identifyShape(arg0))+list(_identifyShape(arg1)))         s=tuple(list(_identifyShape(arg0))+list(_identifyShape(arg1)))
# Line 787  def Interpolated_Symbol(Symbol): Line 777  def Interpolated_Symbol(Symbol):
777         a=self.getDifferentiatedArguments(arg)         a=self.getDifferentiatedArguments(arg)
778         return integrate(a[0],where=self.getArgument(1))         return integrate(a[0],where=self.getArgument(1))
779    
780    def div(arg,where=None):
781        """
782        @brief returns the divergence of arg at where.
783    
784        @param arg:   Data object representing the function which gradient to be calculated.
785        @param where: FunctionSpace in which the gradient will be calculated. If not present or
786                      None an appropriate default is used.
787        """
788        return trace(grad(arg,where))
789    
790  def grad(arg,where=None):  def grad(arg,where=None):
791      """      """
792      @brief returns the spatial gradient of arg at where.      @brief returns the spatial gradient of arg at where.
# Line 857  def Integral_Symbol(Float_Symbol): Line 857  def Integral_Symbol(Float_Symbol):
857  #=============================  #=============================
858  #  #
859  # wrapper for various functions: if the argument has attribute the function name  # wrapper for various functions: if the argument has attribute the function name
860  # as an argument it calls the correspong methods. Otherwise the coresponsing numarray  # as an argument it calls the corresponding methods. Otherwise the corresponding
861  # function is called.  # numarray function is called.
862  #  
863  # functions involving the underlying Domain:  # functions involving the underlying Domain:
 #  
864    
865    
866  # functions returning Data objects:  # functions returning Data objects:
# Line 910  def trace(arg,axis0=0,axis1=1): Line 909  def trace(arg,axis0=0,axis1=1):
909         if s[axis0]!=s[axis1]:         if s[axis0]!=s[axis1]:
910             raise ValueError,"illegal axis in trace"             raise ValueError,"illegal axis in trace"
911         out=escript.Scalar(0.,arg.getFunctionSpace())         out=escript.Scalar(0.,arg.getFunctionSpace())
912         for i in range(s[0]):         for i in range(s[axis0]):
913            for j in range(s[1]):            out+=arg[i,i]
              out+=arg[i,j]  
914         return out         return out
915         # end hack for transpose         # end hack for trace
        return arg.transpose(axis0=axis0,axis1=axis1)  
916      else:      else:
917         return numarray.trace(arg,axis0=axis0,axis1=axis1)         return numarray.trace(arg,axis0=axis0,axis1=axis1)
918    
   
   
919  def Trace_Symbol(Symbol):  def Trace_Symbol(Symbol):
920      pass      pass
921    
# Line 935  def length(arg): Line 930  def length(arg):
930         if arg.getRank()==0:         if arg.getRank()==0:
931            return abs(arg)            return abs(arg)
932         elif arg.getRank()==1:         elif arg.getRank()==1:
933            sum=escript.Scalar(0,arg.getFunctionSpace())            out=escript.Scalar(0,arg.getFunctionSpace())
934            for i in range(arg.getShape()[0]):            for i in range(arg.getShape()[0]):
935               sum+=arg[i]**2               out+=arg[i]**2
936            return sqrt(sum)            return sqrt(out)
937         elif arg.getRank()==2:         elif arg.getRank()==2:
938            sum=escript.Scalar(0,arg.getFunctionSpace())            out=escript.Scalar(0,arg.getFunctionSpace())
939            for i in range(arg.getShape()[0]):            for i in range(arg.getShape()[0]):
940               for j in range(arg.getShape()[1]):               for j in range(arg.getShape()[1]):
941                  sum+=arg[i,j]**2                  out+=arg[i,j]**2
942            return sqrt(sum)            return sqrt(out)
943         elif arg.getRank()==3:         elif arg.getRank()==3:
944            sum=escript.Scalar(0,arg.getFunctionSpace())            out=escript.Scalar(0,arg.getFunctionSpace())
945            for i in range(arg.getShape()[0]):            for i in range(arg.getShape()[0]):
946               for j in range(arg.getShape()[1]):               for j in range(arg.getShape()[1]):
947                  for k in range(arg.getShape()[2]):                  for k in range(arg.getShape()[2]):
948                     sum+=arg[i,j,k]**2                     out+=arg[i,j,k]**2
949            return sqrt(sum)            return sqrt(out)
950         elif arg.getRank()==4:         elif arg.getRank()==4:
951            sum=escript.Scalar(0,arg.getFunctionSpace())            out=escript.Scalar(0,arg.getFunctionSpace())
952            for i in range(arg.getShape()[0]):            for i in range(arg.getShape()[0]):
953               for j in range(arg.getShape()[1]):               for j in range(arg.getShape()[1]):
954                  for k in range(arg.getShape()[2]):                  for k in range(arg.getShape()[2]):
955                     for l in range(arg.getShape()[3]):                     for l in range(arg.getShape()[3]):
956                        sum+=arg[i,j,k,l]**2                        out+=arg[i,j,k,l]**2
957            return sqrt(sum)            return sqrt(out)
958         else:         else:
959            raise SystemError,"length is not been implemented yet"            raise SystemError,"length is not been fully implemented yet"
960         # return arg.length()            # return arg.length()
961        elif isinstance(arg,float):
962           return abs(arg)
963      else:      else:
964         return sqrt((arg**2).sum())         return sqrt((arg**2).sum())
965    
# Line 988  def inner(arg0,arg1): Line 985  def inner(arg0,arg1):
985    
986      @param arg0, arg1      @param arg0, arg1
987      """      """
988      sum=escript.Scalar(0,arg0.getFunctionSpace())      if isinstance(arg0,escript.Data):
989           arg=arg0
990        else:
991           arg=arg1
992    
993        out=escript.Scalar(0,arg.getFunctionSpace())
994      if arg.getRank()==0:      if arg.getRank()==0:
995            return arg0*arg1            return arg0*arg1
996      elif arg.getRank()==1:      elif arg.getRank()==1:
997           sum=escript.Scalar(0,arg.getFunctionSpace())           out=escript.Scalar(0,arg.getFunctionSpace())
998           for i in range(arg.getShape()[0]):           for i in range(arg.getShape()[0]):
999              sum+=arg0[i]*arg1[i]              out+=arg0[i]*arg1[i]
1000      elif arg.getRank()==2:      elif arg.getRank()==2:
1001          sum=escript.Scalar(0,arg.getFunctionSpace())          out=escript.Scalar(0,arg.getFunctionSpace())
1002          for i in range(arg.getShape()[0]):          for i in range(arg.getShape()[0]):
1003             for j in range(arg.getShape()[1]):             for j in range(arg.getShape()[1]):
1004                sum+=arg0[i,j]*arg1[i,j]                out+=arg0[i,j]*arg1[i,j]
1005      elif arg.getRank()==3:      elif arg.getRank()==3:
1006          sum=escript.Scalar(0,arg.getFunctionSpace())          out=escript.Scalar(0,arg.getFunctionSpace())
1007          for i in range(arg.getShape()[0]):          for i in range(arg.getShape()[0]):
1008              for j in range(arg.getShape()[1]):              for j in range(arg.getShape()[1]):
1009                 for k in range(arg.getShape()[2]):                 for k in range(arg.getShape()[2]):
1010                    sum+=arg0[i,j,k]*arg1[i,j,k]                    out+=arg0[i,j,k]*arg1[i,j,k]
1011      elif arg.getRank()==4:      elif arg.getRank()==4:
1012          sum=escript.Scalar(0,arg.getFunctionSpace())          out=escript.Scalar(0,arg.getFunctionSpace())
1013          for i in range(arg.getShape()[0]):          for i in range(arg.getShape()[0]):
1014             for j in range(arg.getShape()[1]):             for j in range(arg.getShape()[1]):
1015                for k in range(arg.getShape()[2]):                for k in range(arg.getShape()[2]):
1016                   for l in range(arg.getShape()[3]):                   for l in range(arg.getShape()[3]):
1017                      sum+=arg0[i,j,k,l]*arg1[i,j,k,l]                      out+=arg0[i,j,k,l]*arg1[i,j,k,l]
1018      else:      else:
1019            raise SystemError,"inner is not been implemented yet"            raise SystemError,"inner is not been implemented yet"
1020      return sum      return out
1021    
1022  def matrixmult(arg0,arg1):  def matrixmult(arg0,arg1):
1023    
# Line 1031  def matrixmult(arg0,arg1): Line 1033  def matrixmult(arg0,arg1):
1033            out=escript.Data(0,(arg0.getShape()[0],),arg0.getFunctionSpace())            out=escript.Data(0,(arg0.getShape()[0],),arg0.getFunctionSpace())
1034            for i in range(arg0.getShape()[0]):            for i in range(arg0.getShape()[0]):
1035               for j in range(arg0.getShape()[1]):               for j in range(arg0.getShape()[1]):
1036                   # uses Data object slicing, plus Data * and += operators
1037                 out[i]+=arg0[i,j]*arg1[j]                 out[i]+=arg0[i,j]*arg1[j]
1038            return out            return out
1039          elif arg0.getRank()==1 and arg1.getRank()==1:
1040              return inner(arg0,arg1)
1041        else:        else:
1042            raise SystemError,"matrixmult is not fully implemented yet!"            raise SystemError,"matrixmult is not fully implemented yet!"
1043    
1044  #=========================================================  #=========================================================
1045  # reduction operations:  # reduction operations:
1046  #=========================================================  #=========================================================
# Line 1113  def dot(arg0,arg1): Line 1119  def dot(arg0,arg1):
1119    
1120  def kronecker(d):  def kronecker(d):
1121     if hasattr(d,"getDim"):     if hasattr(d,"getDim"):
1122        return numarray.identity(d.getDim())        return numarray.identity(d.getDim())*1.
1123     else:     else:
1124        return numarray.identity(d)        return numarray.identity(d)*1.
1125    
1126  def unit(i,d):  def unit(i,d):
1127     """     """
# Line 1127  def unit(i,d): Line 1133  def unit(i,d):
1133     e[i] = 1.0     e[i] = 1.0
1134     return e     return e
1135    
 #  
1136  # ============================================  # ============================================
1137  #   testing  #   testing
1138  # ============================================  # ============================================
# Line 1138  if __name__=="__main__": Line 1143  if __name__=="__main__":
1143    v=VectorSymbol(2,"v")    v=VectorSymbol(2,"v")
1144    u=VectorSymbol(2,"u")    u=VectorSymbol(2,"u")
1145    
   
1146    print u+5,(u+5).diff(u)    print u+5,(u+5).diff(u)
1147    print 5+u,(5+u).diff(u)    print 5+u,(5+u).diff(u)
1148    print u+v,(u+v).diff(u)    print u+v,(u+v).diff(u)
# Line 1180  if __name__=="__main__": Line 1184  if __name__=="__main__":
1184    g=grad(u)    g=grad(u)
1185    print diff(5*g,g)    print diff(5*g,g)
1186    4*(g+transpose(g))/2+6*trace(g)*kronecker(3)    4*(g+transpose(g))/2+6*trace(g)*kronecker(3)
1187    
1188  #  #
1189  # $Log$  # $Log$
1190    # Revision 1.16  2005/08/23 01:24:28  jgs
1191    # Merge of development branch dev-02 back to main trunk on 2005-08-23
1192    #
1193    # Revision 1.15  2005/08/12 01:45:36  jgs
1194    # erge of development branch dev-02 back to main trunk on 2005-08-12
1195    #
1196    # Revision 1.14.2.4  2005/08/18 04:39:32  gross
1197    # the constants have been removed from util.py as they not needed anymore. PDE related constants are accessed through LinearPDE attributes now
1198    #
1199    # Revision 1.14.2.3  2005/08/03 09:55:33  gross
1200    # ContactTest is passing now./mk install!
1201    #
1202    # Revision 1.14.2.2  2005/08/02 03:15:14  gross
1203    # bug inb trace fixed!
1204    #
1205    # Revision 1.14.2.1  2005/07/29 07:10:28  gross
1206    # new functions in util and a new pde type in linearPDEs
1207    #
1208    # Revision 1.2.2.21  2005/07/28 04:19:23  gross
1209    # new functions maximum and minimum introduced.
1210    #
1211    # Revision 1.2.2.20  2005/07/25 01:26:27  gross
1212    # bug in inner fixed
1213    #
1214    # Revision 1.2.2.19  2005/07/21 04:01:28  jgs
1215    # minor comment fixes
1216    #
1217    # Revision 1.2.2.18  2005/07/21 01:02:43  jgs
1218    # commit ln() updates to development branch version
1219    #
1220    # Revision 1.12  2005/07/20 06:14:58  jgs
1221    # added ln(data) style wrapper for data.ln() - also added corresponding
1222    # implementation of Ln_Symbol class (not sure if this is right though)
1223    #
1224  # Revision 1.11  2005/07/08 04:07:35  jgs  # Revision 1.11  2005/07/08 04:07:35  jgs
1225  # Merge of development branch back to main trunk on 2005-07-08  # Merge of development branch back to main trunk on 2005-07-08
1226  #  #

Legend:
Removed from v.123  
changed lines
  Added in v.148

  ViewVC Help
Powered by ViewVC 1.1.26