Changeset 955


Ignore:
Timestamp:
Feb 24, 2005, 5:54:54 PM (20 years ago)
Author:
ole
Message:

Unit tested File_function (NetCDF) for interpolation and time updates

Location:
inundation/ga/storm_surge/pyvolution
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • inundation/ga/storm_surge/pyvolution/data_manager.py

    r947 r955  
    171171        #self.filename = create_filename(domain.get_datadir(),
    172172        #       domain.get_name(), extension, len(domain))
     173
    173174       
    174175        self.filename = create_filename(domain.get_datadir(),
    175176                        domain.get_name(), extension)   
    176                
     177
     178        #print 'F', self.filename
    177179        self.timestep = 0
    178180        self.number_of_volumes = len(domain)
     
    214216
    215217            fid.order = domain.default_order   
    216            
     218
     219            #Reference point
    217220            #Start time in seconds since the epoch (midnight 1/1/1970)
    218             fid.starttime = domain.starttime
     221            fid.starttime = domain.starttime
     222            fid.xllcorner = domain.xllcorner
     223            fid.yllcorner = domain.yllcorner
     224            fid.zone = str(domain.zone) #FIXME: ?
    219225
    220226            # dimension definitions
     
    13761382    y = fid.variables['y'][:]
    13771383    stage = fid.variables['stage'][:]
    1378     return [min(x),max(x),min(y),max(y),min(min(stage)),max(max(stage))]
     1384    #print "stage",stage
     1385    #print "stage.shap",stage.shape
     1386    #print "min(stage.flat), mpythonax(stage.flat)",min(stage.flat), max(stage.flat)
     1387    #print "min(stage)",min(stage)
     1388    return [min(x),max(x),min(y),max(y),min(stage.flat),max(stage.flat)]
    13791389
    13801390
  • inundation/ga/storm_surge/pyvolution/domain.py

    r907 r955  
    1616    def __init__(self, coordinates, vertices, boundary = None,
    1717                 conserved_quantities = None, other_quantities = None,
    18                  tagged_elements = None):
     18                 tagged_elements = None, zone=None, xllcorner=0, yllcorner=0):
    1919
    2020        Mesh.__init__(self, coordinates, vertices, boundary, tagged_elements)
     
    4848        #Create an empty list for explicit forcing terms
    4949        self.forcing_terms = []
    50 
    5150
    5251
     
    7069        self.finaltime = None
    7170        self.min_timestep = self.max_timestep = 0.0
    72         self.starttime = 0    #Physical starttime if any (0 is 1 Jan 1970 00:00:00)
     71        self.starttime = 0 #Physical starttime if any (0 is 1 Jan 1970 00:00:00)
     72        #Origin in UTM coordinates
     73        self.zone = zone
     74        self.xllcorner = xllcorner
     75        self.yllcorner = yllcorner       
     76       
    7377       
    7478        #Checkpointing and storage             
  • inundation/ga/storm_surge/pyvolution/shallow_water.py

    r912 r955  
    202202            #Store model data, e.g. for subsequent visualisation   
    203203            if self.store is True:
    204                 #self.store_timestep(['stage', 'xmomentum', 'ymomentum'])
    205204                self.store_timestep(self.quantities_to_be_stored)
    206205               
  • inundation/ga/storm_surge/pyvolution/test_data_manager.py

    r947 r955  
    706706        self.domain.reduction = mean
    707707        self.domain.set_datadir('.')
     708
    708709     
    709710        sww = get_dataobject(self.domain)
    710711        sww.store_connectivity()
    711712        sww.store_timestep('stage')
    712         self.domain.time = 2.
     713        self.domain.time = 2.
     714
     715        #Modify stage at second timestep
     716        stage = self.domain.quantities['stage'].vertex_values
     717        self.domain.set_quantity('stage', stage/2)
     718
    713719        sww.store_timestep('stage')
     720
    714721        file_and_extension_name = self.domain.filename + ".sww"
    715722        #print "file_and_extension_name",file_and_extension_name
  • inundation/ga/storm_surge/pyvolution/test_util.py

    r896 r955  
    195195       
    196196
     197
     198
     199    def test_spatio_temporal_file_function_time(self):
     200        """Test that File function interpolates correctly
     201        between given times.
     202        NetCDF version (x,y,t dependency)
     203        """
     204
     205        #Create NetCDF (sww) file to be read
     206        # x: 0, 5, 10, 15
     207        # y: -20, -10, 0, 10
     208        # t: 0, 60, 120, ...., 1200
     209        #
     210        # test quantities (arbitrary but non-trivial expressions):
     211        #
     212        #   stage     = 3*x - y**2 + 2*t
     213        #   xmomentum = exp( -((x-7)**2 + (y+5)**2)/20 ) * t**2
     214        #   ymomentum = x**2 + y**2 * sin(t*pi/600)
     215
     216        #Nice test that may render some of the others redundant.
     217       
     218        import os, time
     219        from config import time_format
     220        from Numeric import sin, pi, exp
     221        from mesh_factory import rectangular
     222        from shallow_water import Domain
     223        import data_manager
     224
     225        finaltime = 1200
     226        filename = 'test_file_function'
     227
     228        #Create a domain to hold test grid
     229
     230        points, vertices, boundary =\
     231                rectangular(4, 4, 15, 30, origin = (0, -20))
     232
     233       
     234        #print 'Number of elements', len(vertices)
     235        domain = Domain(points, vertices, boundary)
     236        domain.smooth = False
     237        domain.default_order = 2
     238        domain.set_datadir('.')
     239        domain.set_name(filename)
     240        domain.store = True
     241        domain.format = 'sww'   #Native netcdf visualisation format
     242
     243        #print 'E', domain.get_extent()
     244        #print points
     245        start = time.mktime(time.strptime('2000', '%Y'))
     246        domain.starttime = start
     247
     248       
     249        #Store structure
     250        domain.initialise_storage()
     251
     252        #Compute artificial time steps and store
     253        dt = 60  #One minute intervals
     254        t = 0.0
     255        while t <= finaltime:
     256            #Compute quantities
     257            f1 = lambda x,y: 3*x - y**2 + 2*t + 4
     258            domain.set_quantity('stage', f1)
     259
     260            f2 = lambda x,y: x+y+t**2
     261            domain.set_quantity('xmomentum', f2)
     262
     263            f3 = lambda x,y: x**2 + y**2 * sin(t*pi/600)
     264            domain.set_quantity('ymomentum', f3)                       
     265
     266            #Store and advance time
     267            domain.time = t
     268            domain.store_timestep(domain.conserved_quantities)
     269            t += dt
     270
     271
     272        interpolation_points = [[0,-20], [1,0], [0,1], [1.1, 3.14], [10,-12.5]]
     273
     274
     275
     276        #Set domain.starttime to too early
     277        domain.starttime = start - 1               
     278
     279        #Create file function
     280        F = file_function(filename + '.sww', domain,
     281                          quantities = domain.conserved_quantities,
     282                          interpolation_points = interpolation_points)
     283
     284        #Check that FF updates fixes domain starttime
     285        assert allclose(domain.starttime, start)
     286
     287        #Check that domain.starttime isn't updated if later
     288        domain.starttime = start + 1               
     289        F = file_function(filename + '.sww', domain,
     290                          quantities = domain.conserved_quantities,
     291                          interpolation_points = interpolation_points)
     292        assert allclose(domain.starttime, start+1)               
     293
     294        domain.starttime = start
     295
     296
     297       
     298        #Check linear interpolation in time
     299        #for id in range(len(interpolation_points)):
     300        for id in [1]:
     301            x = interpolation_points[id][0]
     302            y = interpolation_points[id][1]           
     303           
     304            for i in range(20):
     305                t = i*10
     306                k = i%6
     307           
     308                if k == 0:
     309                    q0 = F(t, point_id=id)                               
     310                    q1 = F(t+60, point_id=id)                               
     311           
     312           
     313                q = F(t, point_id=id)
     314                assert allclose(q, (k*q1 + (6-k)*q0)/6)
     315           
     316 
     317        #Another check of linear interpolation in time
     318        for id in range(len(interpolation_points)):
     319            q60 = F(60, point_id=id)
     320            q120 = F(120, point_id=id)       
     321       
     322            t = 90 #Halfway between 60 and 120
     323            q = F(t,point_id=id)
     324            assert allclose( (q120+q60)/2, q )
     325
     326            t = 100 #Two thirds of the way between between 60 and 120
     327            q = F(t, point_id=id)
     328            assert allclose(q60/3 + 2*q120/3, q)
     329
     330
     331
     332        #Check that domain.starttime isn't updated if later than file starttime but earlier
     333        #than file end time
     334        delta = 23
     335        domain.starttime = start + delta               
     336        F = file_function(filename + '.sww', domain,
     337                          quantities = domain.conserved_quantities,
     338                          interpolation_points = interpolation_points)
     339        assert allclose(domain.starttime, start+delta)               
     340
     341       
     342       
     343       
     344        #Now try interpolation with delta offset
     345        for id in [1]:
     346            x = interpolation_points[id][0]
     347            y = interpolation_points[id][1]           
     348           
     349            for i in range(20):
     350                t = i*10
     351                k = i%6
     352           
     353                if k == 0:
     354                    q0 = F(t-delta, point_id=id)     
     355                    q1 = F(t+60-delta, point_id=id)                           
     356           
     357                q = F(t-delta, point_id=id)
     358                assert allclose(q, (k*q1 + (6-k)*q0)/6)
     359           
     360       
     361        os.remove(filename + '.sww')
     362       
     363
     364
    197365    def test_file_function_time_with_domain(self):
    198366        """Test that File function interpolates correctly
     
    238406
    239407        #Check that domain.starttime isn't updated if later
    240         #domain.starttime = start + 1               
    241         #F = file_function(filename, domain)
    242         #assert allclose(domain.starttime, start+1)               
    243 
     408        domain.starttime = start + 1               
     409        F = file_function(filename, domain)
     410        assert allclose(domain.starttime, start+1)               
     411
     412        domain.starttime = start
    244413       
    245414       
     
    275444        between given times. No x,y dependency here.
    276445        Use domain with a starttime later than that of file
     446
     447        ASCII version
    277448        """
    278449
     
    304475        domain = Domain(points, vertices)
    305476
    306         #Check that domain.starttime isn't updated if later
     477        #Check that domain.starttime isn't updated if later than file starttime but earlier
     478        #than file end time
    307479        delta = 23
    308480        domain.starttime = start + delta               
     
    525697        fid.close()
    526698
     699
    527700    def test_xya_ascii(self):
    528701        import time, os
  • inundation/ga/storm_surge/pyvolution/util.py

    r901 r955  
    133133    """
    134134   
    135     def  __init__(self, filename, domain=None, quantities=None, interpolation_points=None, verbose = False):
     135    def  __init__(self, filename, domain=None, quantities=None,
     136                  interpolation_points=None, verbose = False):
    136137        """Initialise callable object from a file.
    137138
     
    171172        #Get first timestep
    172173        try:
    173             starttime = fid.starttime[0]
     174            self.starttime = fid.starttime[0]
    174175        except ValueError:   
    175176            msg = 'Could not read starttime from file %s' %filename
    176177            raise msg
    177178
     179        #Get origin
     180        self.xllcorner = fid.xllcorner[0]
     181        self.yllcorner = fid.yllcorner[0]           
    178182   
    179183        self.number_of_values = len(quantities)
    180184        self.fid = fid
    181185        self.filename = filename
    182         self.starttime = starttime
    183186        self.quantities = quantities
    184187        self.domain = domain
     
    237240           
    238241           
    239             ####self.Q = zeros( (len(time),
    240             self.T = time[:]
    241             self.index = 0 #Initial index       
     242            self.T = time[:]  #Time assumed to be relative to starttime
     243            self.index = 0    #Initial time index       
    242244
    243245            self.values = {}               
     
    268270                    interpol.interpolate(fid.variables[name][i,:])   
    269271
     272            #Report
     273            if verbose:
     274                print '------------------------------------------------'
     275                print 'File_function statistics:'
     276                print '  Name: %s' %self.filename
     277                print '  Reference:'
     278                print '    Lower left corner: [%f, %f]'\
     279                      %(self.xllcorner, self.yllcorner)
     280                print '    Start time: %f' %self.starttime
     281                print '  Extent:'
     282                print '    x in [%f, %f], len(x) == %d'\
     283                      %(min(x.flat), max(x.flat), len(x.flat))
     284                print '    y in [%f, %f], len(y) == %d'\
     285                      %(min(y.flat), max(y.flat), len(y.flat))
     286                print '    t in [%f, %f], len(t) == %d'\
     287                      %(min(self.T), max(self.T), len(self.T))
     288                print '  Quantities:'
     289                for name in self.quantities:
     290                    q = fid.variables[name][:].flat
     291                    print '    %s in [%f, %f]' %(name, min(q), max(q))
     292
     293                   
     294                print '  Interpolation points (xi, eta):'
     295                print '    xi in [%f, %f], len(xi) == %d'\
     296                      %(min(P[:,0]), max(P[:,0]), P.shape[0])
     297                print '    eta in [%f, %f], len(eta) == %d'\
     298                      %(min(P[:,1]), max(P[:,1]), P.shape[1])
     299                print '  Interpolated quantities:'
     300                for name in self.quantities:
     301                    q = self.values[name][:].flat                   
     302                    print '    %s at interpolation points in [%f, %f]'\
     303                          %(name, min(q), max(q))               
     304               
     305               
     306               
     307
     308                print '------------------------------------------------'
    270309        else:
    271             pass
     310            msg = 'File_function_NetCDF must be invoked with '
     311            msg += 'a list of interpolation points'
     312            raise msg
    272313
    273314    def __repr__(self):
     
    285326          FIXME: point_id could also be a slice     
    286327          FIXME: One could allow arbitrary x, y coordinates
    287           (requires computation of a new interpolator)
     328          (requires computation of a new interpolator)
     329          Maybe not,.,.
    288330          FIXME: What if x and y are vectors?
    289331        """
     
    291333        from math import pi, cos, sin, sqrt
    292334        from Numeric import zeros, Float
     335
     336
     337        if point_id is None:
     338            msg = 'NetCDF File function needs a point_id when invoked'
     339            raise msg
     340
    293341
    294342        #Find time tau such that
     
    300348        else:
    301349            tau = t
     350
     351        #print 'D start', self.domain.starttime
     352        #print 'S start', self.starttime
     353        #print 't', t
     354        #print 'tau', tau             
    302355               
    303         msg = 'Time interval derived from file %s (%s:%s) does not match model time: %s'\
    304               %(self.filename, self.T[0], self.T[1], tau)
     356        msg = 'Time interval derived from file %s [%s:%s]'\
     357              %(self.filename, self.T[0], self.T[1])
     358        msg += ' does not match model time: %s' %tau
     359
    305360        if tau < self.T[0]: raise msg
    306361        if tau > self.T[-1]: raise msg       
     
    323378                    (self.T[self.index+1] - self.T[self.index])
    324379
     380
     381
    325382               
    326383        #Compute interpolated values
     
    337394                q[i] = Q[self.index, point_id]
    338395
    339            
    340396        #Return vector of interpolated values
    341397        return q
Note: See TracChangeset for help on using the changeset viewer.