1 | from anuga.shallow_water.shallow_water_domain import Domain |
---|
2 | |
---|
3 | # The different states the model can be in |
---|
4 | STATE_SETUP, STATE_BUILT, STATE_RUNNING = range(0, 3) |
---|
5 | |
---|
6 | class Model: |
---|
7 | def __init__(self, name): |
---|
8 | self.domain = None # Domain class will be removed as we refactor the API |
---|
9 | self.geometry_data = None |
---|
10 | self.quantities = [] |
---|
11 | self.boundaries = [] |
---|
12 | self._state = STATE_SETUP |
---|
13 | self.name = name |
---|
14 | |
---|
15 | |
---|
16 | def set_geometry(self, *args, **kwargs): |
---|
17 | if self.geometry_data: |
---|
18 | raise RuntimeError, 'geometry already defined in model.' |
---|
19 | elif self._state != STATE_SETUP: |
---|
20 | raise RuntimeError, 'Model already built - call this before build().' |
---|
21 | else: |
---|
22 | self.geometry_data = (args, kwargs) |
---|
23 | |
---|
24 | |
---|
25 | def set_quantity(self, *args, **kwargs): |
---|
26 | """Set values for named quantity |
---|
27 | """ |
---|
28 | if self._state != STATE_SETUP: |
---|
29 | raise RuntimeError, 'Model already built - call this before build().' |
---|
30 | |
---|
31 | self.quantities.append((args, kwargs)) |
---|
32 | |
---|
33 | def get_quantity(self, name): |
---|
34 | if self._state != STATE_RUNNING: |
---|
35 | raise RuntimeError, 'Model needs to be running - call this after run().' |
---|
36 | |
---|
37 | return self.domain.get_quantity(name) |
---|
38 | |
---|
39 | |
---|
40 | def set_boundary(self, *args, **kwargs): |
---|
41 | """Set the boundary properties. |
---|
42 | """ |
---|
43 | if self._state == STATE_SETUP: |
---|
44 | # dont apply boundaries until model is built |
---|
45 | self.boundaries.append((args, kwargs)) |
---|
46 | else: |
---|
47 | # model is running, apply boundaries right away |
---|
48 | self.domain.set_boundary(*args, **kwargs) |
---|
49 | |
---|
50 | def get_normals(self): |
---|
51 | # FIXME: This is a wrapper to allow reflective boundary to work. |
---|
52 | # Should be refactored and removed. |
---|
53 | return domain.get_normals() |
---|
54 | |
---|
55 | def build(self): |
---|
56 | if not self.geometry_data: |
---|
57 | raise RuntimeError, 'Model needs geometry. Set mesh or geometry.' |
---|
58 | |
---|
59 | if self._state != STATE_SETUP: |
---|
60 | raise RuntimeError, 'Model already built.' |
---|
61 | |
---|
62 | if len(self.geometry_data[0]) == 1: |
---|
63 | raise RuntimeError, 'Load mesh not implemented.' |
---|
64 | else: |
---|
65 | args, kwargs = self.geometry_data |
---|
66 | |
---|
67 | self.domain = Domain(*args, **kwargs) |
---|
68 | self.domain.set_name(self.name) |
---|
69 | |
---|
70 | for args, kwargs in self.quantities: |
---|
71 | self.domain.set_quantity(*args, **kwargs) |
---|
72 | |
---|
73 | for args, kwargs in self.boundaries: |
---|
74 | self.domain.set_boundary(*args, **kwargs) |
---|
75 | |
---|
76 | self._state = STATE_BUILT |
---|
77 | self.geometry_data = None |
---|
78 | self.quantities = None |
---|
79 | |
---|
80 | |
---|
81 | def run(self, yieldstep, finaltime, verbose = False, timestep_function = None): |
---|
82 | if self._state != STATE_BUILT: |
---|
83 | msg = 'Model is not built, cannot run yet.' |
---|
84 | msg += ' Call build() before run().' |
---|
85 | raise RuntimeError, msg |
---|
86 | |
---|
87 | self._state = STATE_RUNNING |
---|
88 | |
---|
89 | for t in self.domain.evolve(yieldstep, finaltime): |
---|
90 | if verbose == True: |
---|
91 | print self.domain.timestepping_statistics() |
---|
92 | |
---|
93 | # call the user's function at every timestep |
---|
94 | if timestep_function: |
---|
95 | timestep_function(self, t) |
---|