source: inundation/ga/storm_surge/pyvolution/generic_boundary_conditions.py @ 255

Last change on this file since 255 was 240, checked in by ole, 21 years ago

Added C implementation of compute_fluxes

File size: 6.2 KB
Line 
1"""boundary.py - Classes for implementing boundary conditions
2"""
3
4
5class Boundary:
6    """Base class for boundary conditions.
7       Specific boundary conditions must provide values for
8       the conserved_quantities
9
10       A boundary object has one neighbour; the one it
11       serves.
12    """   
13
14    def __init__(self):
15        pass
16       
17    def evaluate(self, vol_id=None, edge_id=None):
18        msg = 'Generic class Boundary must be subclassed'
19        raise msg
20
21
22class Transmissive_boundary(Boundary):
23    """Transmissive boundary returns same conserved quantities as
24    those present in its neighbour volume.
25
26    Underlying domain must be specified when boundary is instantiated
27    """
28   
29    def __init__(self, domain = None):
30        Boundary.__init__(self)
31
32        if domain is None:
33            msg = 'Domain must be specified for transmissive boundary'
34            raise msg
35       
36        self.domain = domain
37       
38    def __repr__(self):
39        return 'Transmissive_boundary(%s)' %self.domain
40
41    def evaluate(self, vol_id, edge_id):
42        """Transmissive boundaries return the edge values
43        of the volume they serve.
44        """
45       
46        q = self.domain.get_conserved_quantities(vol_id, edge = edge_id)
47        return q       
48
49
50class Dirichlet_boundary(Boundary):
51    """Dirichlet boundary returns constant values for the
52    conserved quantities
53    """
54
55
56    def __init__(self, conserved_quantities=None):
57        Boundary.__init__(self)
58
59        if conserved_quantities is None:
60            msg = 'Must specify one value for each conserved quantity'
61            raise msg
62
63        from Numeric import array, Float
64        self.conserved_quantities=array(conserved_quantities).astype(Float)
65
66    def __repr__(self):
67        return 'Dirichlet boundary (%s)' %self.conserved_quantities
68   
69    def evaluate(self, vol_id=None, edge_id=None):
70        return self.conserved_quantities
71
72
73
74class Time_boundary(Boundary):
75    """Time dependent boundary returns values for the
76    conserved quantities as a function of time.
77    Must specify domain to get access to model time and a function f(t)
78    which must return conserved quantities as a function time
79    """
80
81
82    def __init__(self, domain = None, f=None):
83        Boundary.__init__(self)
84
85        try:
86            q = f(0.0)
87        except Exception, e:
88            msg = 'Function for time boundary could not be executed:\n%s' %e
89            raise msg
90       
91
92        from Numeric import array, Float       
93        try:
94            q = array(q).astype(Float)
95        except:
96            msg = 'Return value from time boundary function could '
97            msg += 'not be converted into a Numeric array of floats.\n'
98            msg += 'Specified function should return either list or array.' 
99            raise msg
100
101        msg = 'ERROR: Time boundary function must return a 1d list or array '
102        assert len(q.shape) == 1, msg
103           
104        d = len(domain.conserved_quantities)
105        msg = 'Return value for f must be a list or an array of length %d' %d
106        assert len(q) == d, msg
107
108        self.f = f
109        self.domain = domain
110
111    def __repr__(self):
112        return 'Time boundary'
113
114    def evaluate(self, vol_id=None, edge_id=None):
115        return self.f(self.domain.time)
116
117
118
119#THIS FAR (10/8/4)
120class Connective_boundary(Boundary):
121    """Connective boundary returns values for the
122    conserved quantities from a volume as defined by a connection table
123    mapping between tuples of (volume id, face id) for volumes that
124    have their boundaries connected.
125
126    FIXME: Perhaps include possibility of mapping between
127    different domains as well
128
129    FIXME: In case of shallow water we may want to have a
130    special version that casts this in terms of height rather than stage
131    """
132
133
134    def __init__(self, table):
135        from domain import Volume
136       
137        Boundary.__init__(self)
138
139        self.connection_table = table
140        self.Volume = Volume
141
142    def __repr__(self):
143        return 'Connective boundary'       
144
145    #FIXME: IF we ever need to get field_values from connected volume,
146    #that method could be overridden here (using same idea as in
147    #get_conserved_quantities
148    #def get_field_values()
149   
150    def get_conserved_quantities(self, volume, face=0):
151
152        id = volume.id
153        if self.connection_table.has_key((id, face)):
154            other_id, other_face = self.connection_table[(id, face)] 
155           
156            other_volume = self.Volume.instances[other_id]
157            cmd = 'q = other_volume.conserved_quantities_face%d' %face;
158            exec(cmd)       
159            return q
160        else:
161            msg = 'Volume, face tuple ($d, %d) has not been mapped'\
162                  %(id, face)
163            raise msg
164           
165       
166
167
168
169#FIXME: Add a boundary with a general function of x,y, and t
170
171#FIXME: Add periodic boundaries e.g.:
172# Attempt at periodic conditions from advection_spik. Remember this
173#
174#first = 2*(N-1)*N
175#for i in range(1,2*N+1,2):
176#    k = first + i-1#
177#
178#    print i,k
179#   
180#    domain[i].faces[2].neighbour = domain[k].faces[1]
181#    domain[k].faces[1].neighbour = domain[i].faces[2]   
182   
183
184
185class General_boundary(Boundary):
186    """General boundary which can compute conserved quantities based on
187    their previous value, conserved quantities of its neighbour and model time.
188
189    Must specify initial conserved quantities,
190    neighbour,
191    domain to get access to model time
192    a function f(q_old, neighbours_q, t) which must return
193    new conserved quantities q as a function time
194
195    FIXME: COMPLETE UNTESTED - JUST AN IDEA
196    """
197
198    def __init__(self, neighbour=None, conserved_quantities=None, domain=None, f=None):
199        Boundary.__init__(self, neighbour=neighbour, conserved_quantities=conserved_quantities)
200
201        self.f = f
202        self.domain = domain
203
204
205    def get_conserved_quantities(self, volume=None, face=0):
206        return self.f(self.conserved_quantities,
207                      neighbour.conserved_quantities,
208                      self.domain.time)
209
210   
211   
212       
Note: See TracBrowser for help on using the repository browser.