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

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