Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Diff of /branches/ein16/synth/d2/test_eval.py
ViewVC logotype

Diff of /branches/ein16/synth/d2/test_eval.py

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

revision 3938, Mon Jun 6 14:31:05 2016 UTC revision 3939, Tue Jun 7 18:06:23 2016 UTC
# Line 8  Line 8 
8  from obj_ty import *  from obj_ty import *
9  from obj_apply import *  from obj_apply import *
10  from obj_operator import *  from obj_operator import *
11    from obj_field import *
12    
13    
14    
# Line 15  Line 16 
16  # negation  of field  # negation  of field
17  def fn_negation(exp):  def fn_negation(exp):
18      return -1*exp      return -1*exp
19    # binary operators
20    def fn_add(exp1,exp2):
21        return exp1+exp2
22    def fn_subtract(exp1,exp2):
23        return exp1-exp2
24    # scaling operator
25    def fn_scaling(fld1, fld2):
26        def get_sca():
27            if(field.is_Scalar(fld1)):
28                return (fld1, fld2)
29            else:
30                return (fld2, fld1)
31        (s, t) = get_sca()
32        exp_s = field.get_data(s)
33        exp_t = field.get_data(t)
34        ityp1 = field.get_ty(t)
35        shape1 = fty.get_shape(ityp1)
36        print "exp_s",exp_s,"exp_t",exp_t
37        if(field.is_Scalar(t)):
38            return  exp_s*  exp_t
39        elif(field.is_Vector(t)):
40            [n1] =  shape1 #vector
41            rtn = []
42            for i in range(n1):
43                rtn.append(exp_s*exp_t[i])
44            return rtn
45        elif(field.is_Matrix(t)):
46            [n1,n2] =  shape1
47            rtn = []
48            for i in range(n1):
49                for j in range(n2):
50                    rtn.append(exp_s*exp_t[i][j])
51            return rtn
52        elif(field.is_Ten3(t)):
53            [n1,n2,n3] =  shape1
54            rtn = []
55            for i in range(n1):
56                for j in range(n2):
57                    for k in range(n3):
58                        rtn.append(exp_s*exp_t[i][j][k])
59            return rtn
60        else:
61            raise "unsupported scaling"
62    
63    #evaluate cross product
64    def fn_cross(fld1, fld2):
65        exp1 = field.get_data(fld1)
66        ityp1 = field.get_ty(fld1)
67        exp2 = field.get_data(fld2)
68        ityp2 = field.get_ty(fld2)
69        #print " exp1: ",exp1," exp2: ",exp2
70        # vectors
71        n1 = fty.get_vecLength(ityp1) #vector
72        n2 = fty.get_vecLength(ityp2)
73        if(n1==2):
74            return (exp1[0]*exp2[1]) -(exp1[1]*exp2[0])
75        elif(n1==3):
76            x0= (exp1[1]*exp2[2]) -(exp1[2]*exp2[1])
77            x1= (exp1[2]*exp2[0]) -(exp1[0]*exp2[2])
78            x2= (exp1[0]*exp2[1]) -(exp1[1]*exp2[0])
79            return [x0,x1,x2]
80        else:
81            raise "unsupported type for cross product"
82    
83  #gradient of field  #gradient of field
84  def fn_grad(exp, dim):  def fn_grad(exp, dim):
# Line 27  Line 91 
91      else:      else:
92          raise "dimension not supported"          raise "dimension not supported"
93    
94  # binary operators  #evaluate divergence
95  def fn_add(exp1,exp2):  def fn_divergence(fld):
96      return exp1+exp2      exp = field.get_data(fld)
97  def fn_subtract(exp1,exp2):      ityp = field.get_ty(fld)
98      return exp1-exp2      #print " exp1: ",exp1," exp2: ",exp2
99        # vectors
100        n1 = fty.get_vecLength(ityp) #vector
101        if(n1==2):
102            return diff(exp[0],x)+diff(exp[1],y)
103        elif(n1==3):
104    
105            return diff(exp[0],x)+diff(exp[1],y)+diff(exp[2],z)
106        else:
107            raise "unsupported type for divergence"
108    
109    #evaluate cross product
110    def fn_curl(fld):
111        exp = field.get_data(fld)
112        ityp = field.get_ty(fld)
113        dim = field.get_dim(fld)
114        n = fty.get_vecLength(ityp) #vector
115        if(n!=dim):
116            raise (" type not supported for curl")
117        if(n==2):
118           return diff(exp[1], x) - diff(exp[0], y)
119        elif(n==3):
120            x0= diff(exp[2],y) - diff(exp[1],z)
121            x1= diff(exp[0],z) - diff(exp[2],x)
122            x2= diff(exp[1],x) - diff(exp[0],y)
123            return [x0,x1,x2]
124        else:
125            raise "unsupported type for cross product"
126    
127    #evaluate jacob
128    def fn_jacob(fld):
129        exp = field.get_data(fld)
130        ityp = field.get_ty(fld)
131        dim = field.get_dim(fld)
132        #print " exp1: ",exp1," exp2: ",exp2
133        # vectors
134        n = fty.get_vecLength(ityp) #vector
135        if(n!=dim):
136           raise (" type not supported for jacob")
137        if(n==2):
138            return [diff(exp[0],x), diff(exp[0],y),
139                    diff(exp[1],x), diff(exp[1],y)]
140        elif(n==3):
141            return  [diff(exp[0],x), diff(exp[0],y), diff(exp[0],z),
142                     diff(exp[1],x), diff(exp[1],y), diff(exp[1],z),
143                     diff(exp[2],x), diff(exp[2],y), diff(exp[2],z)]
144        else:
145            raise "unsupported type for divergence"
146    
147    
148    #evaluate outer product
149    def fn_outer(fld1, fld2):
150        exp1 = field.get_data(fld1)
151        ityp1 = field.get_ty(fld1)
152        exp2 = field.get_data(fld2)
153        ityp2 = field.get_ty(fld2)
154        rtn=[]
155        if(fty.is_Vector(ityp1)):
156            n1= fty.get_vecLength(ityp1)
157            if(fty.is_Vector(ityp2)):
158                #both vectors
159                n2= fty.get_vecLength(ityp2)
160                for i in  range(n1):
161                    for j in range(n2):
162                        rtn.append(exp1[i]*exp2[j])
163                return rtn
164            elif(fty.is_Matrix(ityp2)):
165                [n2,n3] = fty.get_shape(ityp2)
166                for i in  range(n1):
167                    for j in range(n2):
168                        for k in range(n3):
169                            rtn.append(exp1[i]*exp2[j][k])
170                return rtn
171        elif(fty.is_Matrix(ityp1)):
172            [n1,n2] = fty.get_shape(ityp1)
173            if(fty.is_Vector(ityp2)):
174                n3= fty.get_vecLength(ityp2)
175                for i in  range(n1):
176                    for j in range(n2):
177                        for k in range(n3):
178                            rtn.append(exp1[i][j]*exp2[k])
179                return rtn
180            elif(fty.is_Matrix(ityp2)):
181                [n3,n4] = fty.get_shape(ityp2)
182                for i in  range(n1):
183                    for j in range(n2):
184                        for k in range(n3):
185                            for l in range(n4):
186                                rtn.append(exp1[i][j]*exp2[k][l])
187                return rtn
188            else:
189                raise "outer product is not supported"
190        else:
191            raise "outer product is not supported"
192    #evaluate inner product
193    def fn_inner(fld1, fld2):
194        exp1 = field.get_data(fld1)
195        ityp1 = field.get_ty(fld1)
196        exp2 = field.get_data(fld2)
197        ityp2 = field.get_ty(fld2)
198        #print " exp1: ",exp1," exp2: ",exp2
199        # vectors
200        if(fty.is_Vector(ityp1)):
201            n1 = fty.get_vecLength(ityp1) #vector
202            if(fty.is_Vector(ityp2)):
203                #length of vetors
204                rtn=0
205                n2 = fty.get_vecLength(ityp2)
206                for s in  range(n1):
207                    curr = exp1[s]*exp2[s]
208                    #print (" exp1[s]: ",exp1[s]," exp2[s]: ",exp2[s],"cur",curr)
209                    rtn += curr
210                return rtn
211            elif(fty.is_Matrix(ityp2)):
212                [n2] = fty.drop_last(ityp2)  #matrix
213                rtn=[]
214                for i in  range(n2):
215                    sumrtn=0
216                    for s in  range(n1):
217                        curr = exp1[s]*exp2[s][i]
218                        sumrtn += curr
219                    rtn.append(sumrtn)
220                return rtn
221            elif(fty.is_Ten3(ityp2)):
222                [n2,n3] = fty.drop_last(ityp2)
223                rtni=[]
224                for i in  range(n2):
225                    rtnj=[]
226                    for j in  range(n3):
227                        sumrtn=0
228                        for s in  range(n1):
229                            curr = exp1[s]*exp2[s][i][j]
230                            sumrtn += curr
231                        rtni.append(sumrtn)
232                        #rtnj.append(sumrtn)
233                return rtni
234            else:
235                raise "inner product is not supported"
236        elif(fty.is_Matrix(ityp1)):
237            n2 = fty.get_first_ix(ityp1)  #matrix
238            if(fty.is_Vector(ityp2)):
239                ns = fty.get_vecLength(ityp2) #vector
240                rtn=[]
241                for i in  range(n2):
242                    sumrtn=0
243                    for s in  range(ns):
244                        curr = exp1[i][s]*exp2[s]
245                        sumrtn += curr
246                    rtn.append(sumrtn)
247                return rtn
248            else:
249                raise "inner product is not supported"
250        elif(fty.is_Ten3(ityp1)):
251            [n1,n2] = fty.drop_first(ityp1)
252            if(fty.is_Vector(ityp2)):
253                ns = fty.get_vecLength(ityp2)
254                rtn=[]
255                for i in  range(n1):
256                    for j in  range(n2):
257                        sumrtn=0
258                        for s in  range(ns):
259                            curr = exp1[i][j][s]*exp2[s]
260                            sumrtn += curr
261                        rtn.append(sumrtn)
262                return rtn
263            else:
264                raise "inner product is not supported"
265        else:
266            raise "inner product is not supported"
267    
268    
269  # ***************************  generic apply operators ***************************  # ***************************  generic apply operators ***************************
270  #unary operator on a vector  #unary operator on a vector
271  def applyToVector(vec, dim, unary):  def applyToVector(vec, unary):
272      rtn = []      rtn = []
273      for v in vec:      for v in vec:
274          rtn.append(unary(v))          rtn.append(unary(v))
275      return rtn      return rtn
276  #binary operator on a vector  #binary operator on a vector
277  def applyToVectors(vecA, vecB, dim, binary):  def applyToVectors(vecA, vecB,  binary):
278      rtn = []      rtn = []
279      for (a,b) in zip(vecA,vecB):      for (a,b) in zip(vecA,vecB):
280          x= binary(a,b)          x= binary(a,b)
281          rtn.append(x)          rtn.append(x)
         print "a:",a,"b:",b,"x:",x  
     print "rtn",rtn  
282      return rtn      return rtn
283    
284  # ***************************  apply to scalars or vectors ***************************  # ***************************  apply to scalars or vectors ***************************
# Line 56  Line 286 
286  # return output types and expression  # return output types and expression
287  # unary operator  # unary operator
288  # exp: scalar types  # exp: scalar types
 def applyToExp_U_S(e):  
     fn_name=e.opr  
     fld =apply.getField1(e)  
     exp = field.getData(fld)  
     ityp1 = field.get_ty(fld)  
     dim = field.getDim(fld)  
289    
290      print fn_name  def applyToExp_U_S(fn_name, fld):
291        exp = field.get_data(fld)
292        dim = field.get_dim(fld)
293        #print fn_name
294      if(op_probe==fn_name): #probing      if(op_probe==fn_name): #probing
295          return (ityp1, exp)          return  exp
296      elif(op_negation==fn_name): #negation      elif(op_negation==fn_name): #negation
297          return (ityp1, fn_negation(exp))          return fn_negation(exp)
298      elif(op_gradient==fn_name): #gradient      elif(op_gradient==fn_name): #gradient
299          return (ty_vec2F_d2, fn_grad(exp, dim))          return fn_grad(exp, dim)
300      else:      else:
301          raise Exception("unsupported unary operator on scalar field:"+ fn_name)          raise Exception("unsupported unary operator on scalar field:"+ fn_name.name)
302    
303    # unary operator
304    # exp: vector  types
305    def applyToExp_U_V(fn_name, fld):
306        exp = field.get_data(fld)
307        if(op_probe==fn_name): #probing
308            return exp
309        elif(op_negation==fn_name): #negation
310            return applyToVector(exp, fn_negation)
311        elif(op_divergence==fn_name):
312            return fn_divergence(fld)
313        elif(op_curl==fn_name):
314            return fn_curl(fld)
315        elif(op_jacob==fn_name): #jacob
316            return fn_jacob(fld)
317        else:
318            raise Exception("unsupported unary operator:"+ fn_name.name)
319    
320    def applyToExp_U_T3(fn_name, fld):
321        exp = field.get_data(fld)
322        if(op_probe==fn_name): #probing
323            return exp
324        elif(op_negation==fn_name): #negation
325            return applyToVector(exp, fn_negation)
326        elif(op_jacob==fn_name): #jacob
327            return fn_jacob(fld)
328        else:
329            raise Exception("unsupported unary operator:"+ fn_name.name)
330    
331  # binary operator  # binary operator
332  # exp: scalar types  # exp: scalar types
333  def applyToExp_B_S(e):  def applyToExp_B_S(e):
334      fn_name=e.opr      fn_name=e.opr
335      (fld1,fld2) =  apply.getFieldsBinary(e)      (fld1,fld2) =  apply.get_binary(e)
336        exp1 = field.get_data(fld1)
337      exp1 = field.getData(fld1)      exp2 = field.get_data(fld2)
338      ityp1 = field.get_ty(fld1)      #print fn_name
   
     exp2 = field.getData(fld2)  
     ityp2 = field.get_ty(fld2)  
     dim =apply.getDimBinary(e)  
     print fn_name  
339      if(op_add==fn_name):#addition      if(op_add==fn_name):#addition
340          return (ityp1, fn_add(exp1,exp2))          return fn_add(exp1,exp2)
341      elif(op_subtract==fn_name):#subtract      elif(op_subtract==fn_name):#subtract
342          return (ityp1, fn_subtract(exp1,exp2))          return fn_subtract(exp1,exp2)
343        elif(op_scale==fn_name): #scaling
344            return fn_scaling(fld1,fld2)
345      else:      else:
346          raise Exception("unsupported binary operator on scalar fields:", op_name)          raise Exception("unsupported binary operator on scalar fields:"+ fn_name.name)
347    
348  # unary operator  # binary, args do not need to have the same shape
349  # exp: vector  types  def applyToExp_B_uneven(e):
 def applyToExp_U_V(e):  
350      fn_name=e.opr      fn_name=e.opr
351      fld =apply.getField1(e)      (fld1,fld2) =  apply.get_binary(e)
352      exp = field.getData(fld)      exp1 = field.get_data(fld1)
353      ityp1 = field.get_ty(fld)      exp2 = field.get_data(fld2)
354      dim = field.getDim(fld)      if(op_outer==fn_name):
355            return fn_outer(fld1, fld2)
356      print fn_name      elif(op_inner==fn_name):
357      if(op_probe==fn_name): #probing          return fn_inner(fld1, fld2)
358          return (ityp1, exp)      elif(op_scale==fn_name): #scaling
359      elif(op_negation==fn_name): #negation          return fn_scaling(fld1,fld2)
         return (ityp1, applyToVector(exp, dim, fn_negation))  
360      else:      else:
361          raise Exception("unsupported unary operator:",op_name)          raise Exception("unsupported unary operator:",op_name)
362    
363    
364  # binary operator  # binary operator
365  # exp: vector  types  # args have the same shape
366  def applyToExp_B_V(e):  def applyToExp_B_V(e):
367      fn_name=e.opr      fn_name=e.opr
368      (fld1,fld2) =  apply.getFieldsBinary(e)      (fld1,fld2) =  apply.get_binary(e)
369      exp1 = field.getData(fld1)      exp1 = field.get_data(fld1)
370      ityp1 = field.get_ty(fld1)      exp2 = field.get_data(fld2)
     exp2 = field.getData(fld2)  
     ityp2 = field.get_ty(fld2)  
     dim =apply.getDimBinary(e)  
   
371      if(op_add==fn_name):#addition      if(op_add==fn_name):#addition
372          return (ityp1, applyToVectors(exp1, exp2, dim, fn_add))          return applyToVectors(exp1, exp2,  fn_add)
373      elif(op_subtract==fn_name):#subtract      elif(op_subtract==fn_name):#subtract
374          return (ityp1,  applyToVectors(exp1, exp2, dim, fn_subtract))          return  applyToVectors(exp1, exp2, fn_subtract)
375        elif(op_cross==fn_name):
376            return fn_cross(fld1, fld2)
377      else:      else:
378          raise Exception("unsupported unary operator:",op_name)         return applyToExp_B_uneven(e)
379    
380    
381  # ***************************  unary/binary operators ***************************  # ***************************  unary/binary operators ***************************
382  def unary(e):  def unary(e):
383      fld =apply.getField1(e)      #apply.toStr(e)
384        fld =apply.get_unary(e)
385      if (field.isEq_id(fld,ty_scalarF_d2)): # input is a scalar field      fn_name=e.opr
386          return applyToExp_U_S(e)      exp = field.get_data(fld)
387      elif(field.isEq_id(fld,ty_vec2F_d2)): # input is a vector field      dim = field.get_dim(fld)
388          return applyToExp_U_V(e)      if (field.is_Scalar(fld)): # input is a scalar field
389            return applyToExp_U_S(fn_name, fld)
390        elif(field.is_Vector(fld)): # input is a vector field
391            return applyToExp_U_V(fn_name, fld)
392      else:      else:
393          raise Exception("unsupported tensor type", field.toStr(fld))          return applyToExp_U_T3(fn_name, fld)
394    
395  def binary(e):  def binary(e):
396      (f, g) =apply.getFieldsBinary(e)      (f, g) =apply.get_binary(e)
397      if (field.isEq_id(f,ty_scalarF_d2)): # input is a scalar field      if (field.is_Scalar(f) and field.is_Scalar(g)): # input is a scalar field
398          return applyToExp_B_S(e)          return applyToExp_B_S(e)
399      elif(field.isEq_id(g, ty_vec2F_d2)): # input is a vector field      elif (field.is_Vector(f)):# input is a vector field
400            if(field.is_Vector(g)):
401          return applyToExp_B_V(e)          return applyToExp_B_V(e)
402            else: # input is a vector field, _
403                return applyToExp_B_uneven(e)
404      else:      else:
405          raise Exception("unsupported binary operator:",op_name)           return applyToExp_B_uneven(e)
406    
407    def applyUnaryOnce(oexp_inner,app_inner,app_outer):
408        #apply.toStr(app_inner)
409        oty_inner = apply.get_oty(app_inner)
410        oty_outer = apply.get_oty(app_outer)
411        opr_outer = app_outer.opr
412        lhs_tmp = field(true, "tmp", oty_inner, "", oexp_inner, "")
413        app_tmp = apply("tmp", opr_outer, lhs_tmp, None, oty_outer, true)
414        oexp_tmp =unary(app_tmp)
415        return (oty_outer, oexp_tmp)
416    
417    
418  # operators with scalar field and vector field  # operators with scalar field and vector field
419  def sort(e):  def sort(e):
420      arity=apply.getArity(e)      #apply.toStr(e)
421        arity = apply.get_arity(e)
422        if(e.isroot): # is root
423            #print "sort is a root"
424            oty = apply.get_oty(e)
425      if (arity==1):      if (arity==1):
426          return unary(e)              return (oty, unary(e))
427      elif (arity==2): # binary operator      elif (arity==2): # binary operator
428          return binary(e)              return (oty, binary(e))
429            else:
430                raise Exception ("arity is not supported: "+str(arity_outer))
431      else:      else:
432          raise Exception ("arity is not supported: "+str(arity))          app_outer = e
433            arity_outer = arity
434            #print "not a root"
435            if (arity_outer==1):  #assuming both arity
436                app_inner = apply.get_unary(app_outer)
437                arity_inner=  app_inner.opr.arity
438                if (arity_inner==1):
439                    oexp_inner = unary(app_inner)
440                    (oty_outer, oexp_tmp) =  applyUnaryOnce(oexp_inner ,app_inner, app_outer)
441                    return (oty_outer, oexp_tmp)
442                elif(arity_inner==2):
443                    oexp_inner = binary(app_inner)
444                    (oty_outer, oexp_tmp) =  applyUnaryOnce(oexp_inner ,app_inner, app_outer)
445                    return (oty_outer, oexp_tmp)
446                else:
447                    raise Exception ("arity is not supported: "+str(arity_outer))
448            else:
449                raise Exception ("arity is not supported: "+str(arity_outer))
450    
451  # ***************************  evaluate at positions ***************************  # ***************************  evaluate at positions ***************************
452  #evaluate scalar field exp  #evaluate scalar field exp
# Line 168  Line 456 
456      exp1 = exp0.subs(y,pos1)      exp1 = exp0.subs(y,pos1)
457      return exp1      return exp1
458    
459    def eval_d3(pos0, pos1, pos2, exp):
460        #evaluate field defined by coefficients at position
461        exp0 = exp.subs(x,pos0)
462        exp1 = exp0.subs(y,pos1)
463        exp2 = exp1.subs(z,pos2)
464        return exp2
465    
466  #evaluate vector field [exp,exp]  #evaluate vector field [exp,exp]
467  def eval_vec_d2(pos0, pos1, vec):  def eval_vec_d2(pos0, pos1, vec):
468        #print "eval_vec_d2 vec:",vec
469      rtn = []      rtn = []
470      for v in vec:      for v in vec:
471          rtn.append(eval_d2(pos0, pos1, v))          rtn.append(eval_d2(pos0, pos1, v))
472      return rtn      return rtn
473    
474  def iter(k, pos, exp):  #evaluate vector field [exp,exp]
475    def eval_vec_d3(pos0, pos1, pos2, vec):
476        rtn = []
477        for v in vec:
478            rtn.append(eval_d3(pos0, pos1, pos2, v))
479        return rtn
480    
481    
482    def iter_d2(k, pos, exp):
483      corr = []      corr = []
484      print "exprn:", exp      #print "iter expr:", exp
485        #print "pos", pos
486      for p in pos:      for p in pos:
487            #print "p", p
488          x=p[0]          x=p[0]
489          y=p[1]          y=p[1]
490          val = k(x,y,exp)          val = k(x,y,exp)
491          corr.append(val)          corr.append(val)
492      return corr      return corr
493    
494    def iter_d3(k, pos, exp):
495        corr = []
496        #print "iter exp:", exp
497        for p in pos:
498            x=p[0]
499            y=p[1]
500            z=p[2]
501            val = k(x,y,z, exp)
502            #print "pos: ",x,y,z, " val:", val
503            corr.append(val)
504        return corr
505    
506  def probeField(otyp1,pos, ortn):  def probeField(otyp1,pos, ortn):
507      if (fty.isEq_id(otyp1,ty_scalarF_d2)): # output is a scalar field      dim = fty.get_dim(otyp1)
508          return iter(eval_d2,pos,ortn)      if (dim==2):
509      elif(fty.isEq_id(otyp1,ty_vec2F_d2)): # output is a vector field          def get_k():
510          return iter(eval_vec_d2,pos,ortn)              if (fty.is_ScalarField(otyp1)): # output is a scalar field
511                    return eval_d2
512                else:
513                    return eval_vec_d2
514            return iter_d2(get_k(), pos, ortn)
515        elif (dim==3):
516            def get_k():
517                if (fty.is_ScalarField(otyp1)): # output is a scalar field
518                    return eval_d3
519                else:
520                    return eval_vec_d3
521            return iter_d3(get_k(), pos, ortn)
522      else:      else:
523          raise Exception("unsupported return type:")          raise "unsupported dimension"
524    
525  # ***************************  main  ***************************  # ***************************  main  ***************************
526    
527  # operators with scalar field and vector field  # operators with scalar field and vector field
528  def eval(app, pos):  def eval(app, pos):
529        # print "inside eval exp:", field.toStr(app.exp[0])
530        #apply.toStr(app)
531      (otyp1, ortn) = sort(app) #apply operations to expressions      (otyp1, ortn) = sort(app) #apply operations to expressions
532        #print "ortn",ortn
533      return probeField(otyp1, pos, ortn) #evaluate expression at positions      return probeField(otyp1, pos, ortn) #evaluate expression at positions
534    
535    

Legend:
Removed from v.3938  
changed lines
  Added in v.3939

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0