Changeset 8154


Ignore:
Timestamp:
Mar 17, 2011, 5:51:42 PM (14 years ago)
Author:
steve
Message:

Adding in kinematic viscosity. Added in some procedures to change boundary_values of
quantities

Location:
trunk/anuga_core/source/anuga
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/anuga_core/source/anuga/__init__.py

    r8133 r8154  
    2929
    3030from anuga.shallow_water.shallow_water_domain import Domain
     31
     32from anuga.abstract_2d_finite_volumes.quantity import Quantity
    3133
    3234from anuga.abstract_2d_finite_volumes.util import file_function, \
     
    132134
    133135#---------------------------
    134 # Structures
     136# Structure Operators
    135137#---------------------------
    136138from anuga.structures.structure_operator import Structure_operator
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/generic_domain.py

    r8148 r8154  
    100100        self.vertex_coordinates = self.mesh.vertex_coordinates
    101101        self.boundary = self.mesh.boundary
     102        self.boundary_enumeration = self.mesh.boundary_enumeration
    102103        self.neighbours = self.mesh.neighbours
    103104        self.surrogate_neighbours = self.mesh.surrogate_neighbours
     
    708709                if B is not None:
    709710                    self.boundary_objects.append(((vol_id, edge_id), B))
    710                     self.neighbours[vol_id, edge_id] = \
    711                                         -len(self.boundary_objects)
     711                    #self.neighbours[vol_id, edge_id] = \
     712                                        #-len(self.boundary_objects)
    712713                else:
    713714                    pass
     
    721722                raise Exception(msg)
    722723
     724    ##
     725    # @brief Set quantities based on a regional tag.
     726    # @param args
     727    # @param kwargs
    723728    def set_region(self, *args, **kwargs):
    724729        """Set quantities based on a regional tag.
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/neighbour_mesh.py

    r8124 r8154  
    178178        if verbose: log.critical('Mesh: Building boundary dictionary')
    179179        self.build_boundary_dictionary(boundary)
     180
     181        #Update boundary_enumeration
     182        self.build_boundary_neighbours()
    180183
    181184        #Build tagged element  dictionary mapping (tag) to array of elements
     
    441444
    442445            self.neighbours[id, edge] = index
     446
     447            self.boundary_enumeration[id,edge] = index
     448
    443449            index -= 1
     450
     451    def build_boundary_neighbours(self):
     452        """Traverse boundary and
     453        enumerate neighbour indices from -1 and
     454        counting down.
     455
     456        Precondition:
     457            self.boundary is defined.
     458        Post condition:
     459            neighbours array has unique negative indices for boundary
     460            boundary_segments array imposes an ordering on segments
     461            (not otherwise available from the dictionary)
     462
     463        """
     464
     465        if self.boundary is None:
     466            msg = 'Boundary dictionary must be defined before '
     467            msg += 'building boundary structure'
     468            raise Exception(msg)
     469
     470        self.boundary_enumeration = {}
     471
     472        X = self.boundary.keys()
     473        X.sort()
     474
     475        index = -1
     476        for id, edge in X:
     477            self.neighbours[id, edge] = index
     478
     479            self.boundary_enumeration[id,edge] = -index -1
     480
     481            index -= 1
     482
    444483
    445484
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/quantity.py

    r8149 r8154  
    234234        self.beta = beta
    235235
     236    ##
     237    # @brief Get the current beta value.
     238    # @return The current beta value.
    236239    def get_beta(self):
    237240        """Get default beta value for limiting"""
     
    239242        return self.beta
    240243
     244
     245
     246    ##
     247    # @brief Set boundary values using a function or array or scalar
     248    # @param numeric: function or array or scalar
     249    def set_boundary_values(self, numeric = 0.0):
     250        """Set boundary values """
     251
     252        if isinstance(numeric, (list, num.ndarray)):
     253            self._set_boundary_values_from_array(numeric)
     254        elif callable(numeric):
     255            self._set_boundary_values_from_function(numeric)
     256        else:   # see if it's coercible to a float (float, int or long, etc)
     257            try:
     258                numeric = float(numeric)
     259            except ValueError:
     260                msg = ("Illegal type for variable 'numeric': %s"
     261                           % type(numeric))
     262                raise Exception(msg)
     263            self._set_boundary_values_from_constant(numeric)
     264
     265
     266    ##
     267    # @brief Set boundary values using a function
     268    # @param numeric: function
     269    def _set_boundary_values_from_function(self, function):
     270        """Set boundary values from function of x,y """
     271
     272        for (vol_id, edge_id) , j in self.domain.boundary_enumeration.items():
     273            [x,y] = self.domain.get_edge_midpoint_coordinates(vol_id)[edge_id]
     274            self.boundary_values[j] = function(x,y)
     275
     276    ##
     277    # @brief Set boundary values using a scalar
     278    # @param numeric: scalar
     279    def _set_boundary_values_from_constant(self, scalar):
     280        """Set boundary values from scalar """
     281
     282        for (vol_id, edge_id) , j in self.domain.boundary_enumeration.items():
     283            [x,y] = self.domain.get_edge_midpoint_coordinates(vol_id)[edge_id]
     284            self.boundary_values[j] = scalar
     285
     286    ##
     287    # @brief Set boundary values using a scalar
     288    # @param numeric: scalar
     289    def _set_boundary_values_from_array(self, array):
     290        """Set boundary values from array """
     291
     292        assert len(array)  == len(self.domain.boundary_enumeration)
     293       
     294        for (vol_id, edge_id) , j in self.domain.boundary_enumeration.items():
     295            [x,y] = self.domain.get_edge_midpoint_coordinates(vol_id)[edge_id]
     296            self.boundary_values[j] = array[j]
     297
     298    ##
     299    # @brief Compute interpolated values at edges and centroid.
     300    # @note vertex_values must be set before calling this.
    241301    def interpolate(self):
    242302        """Compute interpolated values at edges and centroid
     
    583643                assert values.shape[0] == N, msg
    584644
    585                 self.centroid_values = values
     645                self.centroid_values[:] = values
    586646            else:
    587647                msg = 'Number of values must match number of indices'
     
    610670
    611671                if indices is None:
    612                     self.vertex_values = values
     672                    self.vertex_values[:] = values
    613673                else:
    614674                    for element_index, value in map(None, indices, values):
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/test_neighbour_mesh.py

    r8124 r8154  
    12331233
    12341234        neighbours = mesh.get_triangle_neighbours(0)
    1235         assert num.allclose(neighbours, [-1,1,-1])
     1235        assert num.allclose(neighbours, [-1,1,-2])
    12361236        neighbours = mesh.get_triangle_neighbours(-10)
    12371237        assert neighbours == []
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/test_quantity.py

    r8124 r8154  
    9797                                                     [0.,0.,0.], [0.,0.,0.]])
    9898
     99    def test_set_boundary_values(self):
     100
     101        quantity = Quantity(self.mesh1)
     102
     103        quantity.set_boundary_values()
     104
     105        assert  num.allclose(quantity.boundary_values, [0.0, 0.0, 0.0])
     106
     107
     108    def test_set_boundary_values_with_function(self):
     109
     110        quantity = Quantity(self.mesh1)
     111        #assert num.allclose(quantity.vertex_values, [[0.,0.,0.]])
     112
     113        def simple(x,y):
     114            return x+3*y
     115
     116        quantity.set_boundary_values(simple)
     117
     118        assert  num.allclose(quantity.boundary_values, [1.0, 4.0, 3.0])
     119
     120    def test_set_boundary_values_with_constant(self):
     121
     122        quantity = Quantity(self.mesh1)
     123        #assert num.allclose(quantity.vertex_values, [[0.,0.,0.]])
     124
     125        quantity.set_boundary_values(10.0)
     126
     127        assert  num.allclose(quantity.boundary_values, [10.0, 10.0, 10.0])
     128
     129
     130    def test_set_boundary_values_with_array(self):
     131
     132        quantity = Quantity(self.mesh1)
     133        #assert num.allclose(quantity.vertex_values, [[0.,0.,0.]])
     134
     135
     136        quantity.set_boundary_values([10.0, 4.0, 5.0])
     137
     138        assert  num.allclose(quantity.boundary_values, [10.0, 4.0, 5.0])
     139
     140    def test_set_boundary_values_with_wrong_sized_array(self):
     141
     142        quantity = Quantity(self.mesh1)
     143        #assert num.allclose(quantity.vertex_values, [[0.,0.,0.]])
     144
     145        try:
     146            quantity.set_boundary_values([10.0, 4.0, 5.0, 8.0])
     147        except:
     148            pass
     149        else:
     150            msg = 'Should have caught this'
     151            raise Exception(msg)
    99152
    100153    def test_interpolation(self):
     
    247300        quantity = Quantity(self.mesh4)
    248301
     302        # get referece to data arrays
     303        centroid_values = quantity.centroid_values
     304        vertex_values = quantity.vertex_values
    249305
    250306        quantity.set_values([[1,2,3], [5,5,5], [0,0,9], [-6, 3, 3]],
     
    252308        assert num.allclose(quantity.vertex_values,
    253309                            [[1,2,3], [5,5,5], [0,0,9], [-6, 3, 3]])
     310
     311        assert id(vertex_values) == id(quantity.vertex_values)
    254312        assert num.allclose(quantity.centroid_values, [2., 5., 3., 0.]) #Centroid
    255313        assert num.allclose(quantity.edge_values, [[2.5, 2.0, 1.5],
     
    281339
    282340
     341
    283342        try:
    284343            quantity.set_values([[1,2,3], [0,0,9]])
    285         except AssertionError:
     344        except ValueError:
    286345            pass
    287346        except:
    288             raise Exception('should have raised Assertionerror')
     347            raise Exception('should have raised ValueeError')
    289348
    290349
     
    23682427
    23692428if __name__ == "__main__":
    2370     suite = unittest.makeSuite(Test_Quantity, 'test')   
     2429    suite = unittest.makeSuite(Test_Quantity, 'test')
    23712430    runner = unittest.TextTestRunner()
    23722431    runner.run(suite)
  • trunk/anuga_core/source/anuga/operators/kinematic_viscosity.py

    r8152 r8154  
    99import anuga.utilities.log as log
    1010
     11
     12
    1113class Kinematic_Viscosity:
    1214    """
     
    3537    """
    3638
    37     def __init__(self, domain, diffusivity = None, use_triangle_areas=True, verbose=False):
     39    def __init__(self, domain, use_triangle_areas=True, verbose=False):
    3840        if verbose: log.critical('Kinematic Viscosity: Beginning Initialisation')
    3941        #Expose the domain attributes
     
    4446        self.boundary_enumeration = domain.boundary_enumeration
    4547       
    46         # Setup diffusivity quantity
    47         if diffusivity is None:
    48             diffusivity = Quantity(domain)
    49             diffusivity.set_values(1.0)
    50             diffusivity.set_boundary_values(1.0)
    51         #check that diffusivity is a quantity associated with domain
    52         assert diffusivity.domain == domain
    53 
    54         self.diffusivity = diffusivity
    55         #self.diffusivity_bdry_data = self.diffusivity.boundary_values
    56         #self.diffusivity_cell_data = self.diffusivity.centroid_values
    57 
     48        # Dummy diffusivity quantity
     49        diffusivity = Quantity(domain)
     50        diffusivity.set_values(1.0)
     51        diffusivity.set_boundary_values(1.0)
    5852
    5953        self.n = len(self.domain)
    60         self.dt = 1e-6 #Need to set to domain.timestep
     54        self.dt = 1.0 #Need to set to domain.timestep
    6155        self.boundary_len = len(domain.boundary)
    6256        self.tot_len = self.n + self.boundary_len
     
    9589
    9690        # Build matrix self.elliptic_matrix [A B]
    97         self.build_elliptic_matrix()
    98 
    99         # Build self.boundary_term
    100         #self.build_elliptic_boundary_term()
    101 
    102         self.parabolic_solve = False #Are we doing a parabolic solve at the moment?
     91        self.build_elliptic_matrix(diffusivity)
     92
     93        self.boundary_term = num.zeros((self.n, ), num.float)
     94
     95        self.parabolic = False #Are we doing a parabolic solve at the moment?
    10396
    10497        if verbose: log.critical('Kinematic Viscosity: Initialisation Done')
     
    109102       
    110103
    111     def set_qty_considered(self, qty):
    112         # FIXME SR: Probably should just be set by quantity to which operation is applied
    113         if qty == 1 or qty == 'u':
    114             self.qty_considered = 1
    115         elif qty == 2 or qty == 'v':
    116             self.qty_considered = 2
    117         else: #Raise an exception
    118             msg = "Incorrect input qty"
    119             assert 0 == 1, msg
    120 
    121     def build_elliptic_matrix(self):
     104    def set_parabolic_solve(self,flag):
     105
     106        self.parabolic = flag
     107
     108
     109    def build_elliptic_matrix(self, a):
    122110        """
    123111        Builds matrix representing
    124112
    125         div ( diffusivity grad )
     113        div ( a grad )
    126114
    127115        which has the form [ A B ]
     
    131119        # are setup via this call
    132120        kinematic_viscosity_ext.build_elliptic_matrix(self, \
    133                 self.diffusivity.centroid_values, \
    134                 self.diffusivity.boundary_values)
     121                a.centroid_values, \
     122                a.boundary_values)
    135123
    136124        self.elliptic_matrix = Sparse_CSR(None, \
     
    138126                self.n, self.tot_len)
    139127
    140         #print 'elliptic_matrix'
    141         #print self.elliptic_matrix
    142 
    143 #        #Set up the scaling matrix
    144 #        data = h
    145 #        num.putmask(data, data != 0, 1 / data) #take the reciprocal of each entry unless it is zero
    146 #        self.stage_heights_scaling = \
    147 #            Sparse_CSR(None, self.diffusivity_data, num.arange(self.n), num.arange(self.n +1), self.n, self.n)
    148 
    149     def update_elliptic_matrix(self):
     128
     129    def update_elliptic_matrix(self, a=None):
    150130        """
    151131        Updates the data values of matrix representing
    152132
    153         div ( diffusivity grad )
    154 
    155         (as when diffusivitiy has changed)
     133        div ( a grad )
     134
     135        If a == None then we set a = quantity which is set to 1
    156136        """
    157137
     
    159139        # through to the Sparse_CSR matrix.
    160140
     141        if a == None:
     142            a = Quantity(self.domain)
     143            a.set_values(1.0)
     144            a.set_boundary_values(1.0)
     145           
    161146        kinematic_viscosity_ext.update_elliptic_matrix(self, \
    162                 self.diffusivity.centroid_values, \
    163                 self.diffusivity.boundary_values)
    164        
    165 
    166     def build_elliptic_boundary_term(self,quantity):
    167         """
    168         Operator has form [A B] and U = [ u ; b]
    169 
    170         This procedure calculates B b which can be calculated as
     147                a.centroid_values, \
     148                a.boundary_values)
     149       
     150
     151
     152
     153
     154    def update_elliptic_boundary_term(self, boundary):
     155
     156
     157        if isinstance(boundary, Quantity):
     158
     159            self._update_elliptic_boundary_term(boundary.boundary_values)
     160
     161        elif isinstance(boundary, num.ndarray):
     162
     163            self._update_elliptic_boundary_term(boundary.boundary_values)
     164
     165        else:
     166
     167            raise  TypeError('expecting quantity or numpy array')
     168
     169
     170    def _update_elliptic_boundary_term(self, b):
     171        """
     172        Operator has form [A B] and u = [ u_1 ; b]
     173
     174        u_1 associated with centroid values of u
     175        u_2 associated with boundary_values of u
     176
     177        This procedure calculates B u_2 which can be calculated as
    171178
    172179        [A B] [ 0 ; b]
     180
     181        Assumes that update_elliptic_matrix has just been run.
    173182        """
    174183
     
    176185        tot_len = self.tot_len
    177186
    178         self.boundary_term = num.zeros((n, ), num.float)
    179        
    180187        X = num.zeros((tot_len,), num.float)
    181188
    182         X[n:] = quantity.boundary_values
     189        X[n:] = b
    183190        self.boundary_term[:] = self.elliptic_matrix * X
    184191
     
    188195
    189196
    190     def elliptic_multiply(self, quantity_in, quantity_out=None, include_boundary=True):
     197
     198    def elliptic_multiply(self, input, output=None):
     199
     200
     201        if isinstance(input, Quantity):
     202
     203            assert isinstance(output, Quantity) or output is None
     204
     205            output = self._elliptic_multiply_quantity(input, output)
     206
     207        elif isinstance(input, num.ndarray):
     208
     209            assert isinstance(output, num.ndarray) or output is None
     210
     211            output = self._elliptic_multiply_array(input, output)
     212
     213        else:
     214
     215            raise TypeError('expecting quantity or numpy array')
     216       
     217        return output
     218
     219
     220    def _elliptic_multiply_quantity(self, quantity_in, quantity_out):
     221        """
     222        Assumes that update_elliptic_matrix has been run
     223        """
     224
     225        if quantity_out is None:
     226            quantity_out = Quantity(self.domain)
     227
     228        array_in = quantity_in.centroid_values
     229        array_out = quantity_out.centroid_values
     230
     231        X = self._elliptic_multiply_array(array_in, array_out)
     232
     233        quantity_out.set_values(X, location = 'centroids')
     234       
     235        return quantity_out
     236
     237    def _elliptic_multiply_array(self, array_in, array_out):
     238        """
     239        calculates [A B] [array_in ; 0]
     240        """
    191241
    192242        n = self.n
     
    194244
    195245        V = num.zeros((tot_len,), num.float)
    196         X = num.zeros((n,), num.float)
     246
     247        assert len(array_in) == n
     248
     249        if array_out is None:
     250            array_out = num.zeros_like(array_in)
     251
     252        V[0:n] = array_in
     253        V[n:] = 0.0
     254
     255
     256        if self.apply_triangle_areas:
     257            V[0:n] = self.triangle_areas * V[0:n]
     258
     259
     260        array_out[:] = self.elliptic_matrix * V
     261
     262
     263        return array_out
     264
     265
     266
     267
     268
     269    def parabolic_multiply(self, input, output=None):
     270
     271
     272        if isinstance(input, Quantity):
     273
     274            assert isinstance(output, Quantity) or output is None
     275
     276            output = self._parabolic_multiply_quantity(input, output)
     277
     278        elif isinstance(input, num.ndarray):
     279
     280            assert isinstance(output, num.ndarray) or output is None
     281
     282            output = self._parabolic_multiply_array(input, output)
     283
     284        else:
     285
     286            raise TypeError('expecting quantity or numpy array')
     287
     288        return output
     289
     290
     291    def _parabolic_multiply_quantity(self, quantity_in, quantity_out):
     292        """
     293        Assumes that update_elliptic_matrix has been run
     294        """
    197295
    198296        if quantity_out is None:
    199297            quantity_out = Quantity(self.domain)
    200298
    201         V[0:n] = quantity_in.centroid_values
     299        array_in = quantity_in.centroid_values
     300        array_out = quantity_out.centroid_values
     301
     302        X = self._parabolic_multiply_array(array_in, array_out)
     303
     304        quantity_out.set_values(X, location = 'centroids')
     305
     306        return quantity_out
     307
     308    def _parabolic_multiply_array(self, array_in, array_out):
     309        """
     310        calculates ( [ I 0 ; 0  0] + dt [A B] ) [array_in ; 0]
     311        """
     312
     313        n = self.n
     314        tot_len = self.tot_len
     315
     316        V = num.zeros((tot_len,), num.float)
     317
     318        assert len(array_in) == n
     319
     320        if array_out is None:
     321            array_out = num.zeros_like(array_in)
     322
     323        V[0:n] = array_in
    202324        V[n:] = 0.0
    203 
    204 
    205         # FIXME SR: These sparse matrix vector multiplications
    206         # should be done in such a way to reuse memory, ie
    207         # should have a procedure
    208         # matrix.multiply(vector_in, vector_out)
    209325
    210326
     
    213329
    214330
    215         X[:] = self.elliptic_matrix * V
    216 
    217         if include_boundary:
    218             self.build_elliptic_boundary_term(quantity_in)
    219             X[:] += self.boundary_term
    220 
    221 
    222         quantity_out.set_values(X, location = 'centroids')
    223         return quantity_out
    224 
    225     #parabolic_multiply(V) = identity - dt*elliptic_multiply(V)
    226     #We do not need include boundary, as we will only use this
    227     #method for solving (include_boundary = False)
    228     #Here V is already either (u) or (v), not (uh) or (vh)
    229     def parabolic_multiply(self, V):
    230         msg = "(KV_Operator.parabolic_multiply) V vector has incorrect dimensions"
    231         assert V.shape == (self.n, ) or V.shape == (self.n, 1), msg
    232 
    233         D = V #The return value
    234         X = V #a temporary array
    235 
    236         #Apply triangle areas
    237         if self.apply_triangle_areas:
    238             X = self.triangle_areas * X
    239 
    240         #Multiply out
    241         X = num.append(X, num.zeros((self.boundary_len, )), axis=0)
    242         D = D - self.dt * (self.elliptic_matrix * X)
    243 
    244         return num.array(D).reshape(self.n, )
    245 
    246     def __mul__(self, other):
    247         try:
    248             B = num.array(other)
    249         except:
    250             msg = "Trying to multiply the Kinematic Viscosity Operator against a non-numeric type"
    251             raise msg
    252 
    253         if len(B.shape) == 0:
    254             #Scalar
    255             R = B * self
    256         elif len(B.shape) == 1 or (len(B.shape) == 2 and B.shape[1] == 1):
    257             #Vector
    258             if self.parabolic_solve:
    259                 R = self.parabolic_multiply(other)
    260             else:
    261                 #include_boundary=False is this is *only* used for cg_solve()
    262                 R = self.elliptic_multiply(other, include_boundary=False)
     331        array_out[:] = array_in - self.dt * (self.elliptic_matrix * V)
     332
     333        return array_out
     334
     335
     336
     337
     338    def __mul__(self, vector):
     339       
     340        #Vector
     341        if self.parabolic:
     342            R = self.parabolic_multiply(vector)
    263343        else:
    264             raise ValueError, 'Dimension too high: d=%d' % len(B.shape)
     344            #include_boundary=False is this is *only* used for cg_solve()
     345            R = self.elliptic_multiply(vector)
     346
    265347        return R
    266348   
     
    271353        except:
    272354            msg = 'Sparse matrix can only "right-multiply" onto a scalar'
    273             raise TypeError, msg
     355            raise TypeError(msg)
    274356        else:
    275357            new = self.elliptic_matrix * new
    276358        return new
    277359
    278     def cg_solve(self, B, qty_to_consider=None):
    279         if len(B.shape) == 1:
    280             return self.cg_solve_vector(B, qty_to_consider)
    281         elif len(B.shape) == 2:
    282             return self.cg_solve_matrix(B)
    283         else:
    284             raise ValueError, 'Dimension too high: d=%d' % len(B.shape)
    285 
    286     def cg_solve_matrix(self, B):
    287         assert B.shape[1] < 3, "Input matrix has too many columns (max 2)"
    288 
    289         X = num.zeros(B.shape, num.float)
    290         for i in range(B.shape[1]):
    291             X[:, i] = self.cg_solve_vector(B[:, i], i + 1) #assuming B columns are (uh) and (vh)
    292         return X
    293360   
    294     def cg_solve_vector(self, b, qty_to_consider=None):
    295         if not qty_to_consider == None:
    296             self.set_qty_considered(qty_to_consider)
    297             #Call the ANUGA conjugate gradient utility
    298         x = conjugate_gradient(self, b - self.boundary_vector[:, self.qty_considered-1])
    299         return x
    300 
    301     #Solve the parabolic equation to find u^(n+1), where u = u^n
    302     #Here B = [uh vh] where uh,vh = n*1 column vectors
    303     def parabolic_solver(self, B):
    304         assert B.shape == (self.n, 2), "Input matrix has incorrect dimensions"
    305 
    306         next_B = num.zeros((self.n, 2), num.float)
    307         #The equation is self.parabolic_multiply*u^(n+1) = u^n + (dt)*self.boundary_vector
    308         self.parabolic_solve = True
    309         #Change (uh) and (vh) to (u) and (v)
    310         b = self.stage_heights_scaling * B
    311 
    312         next_B = conjugate_gradient(self, b + (self.dt * self.boundary_vector), iprint=1)
    313 
    314         #Return (u) and (v) back to (uh) and (vh)
    315         next_B = self.stage_heights_scaling * next_B
    316 
    317         self.parabolic_solve = False
    318 
    319         return next_B
     361    def elliptic_solve(self, u_in, b, a = None, u_out = None, \
     362                       imax=10000, tol=1.0e-8, atol=1.0e-8, iprint=None):
     363        """ Solving div ( a grad u ) = b
     364        u | boundary = g
     365
     366        u_in, u_out, f anf g are Quantity objects
     367
     368        Dirichlet BC g encoded into u_in boundary_values
     369
     370        Initial guess for iterative scheme is given by
     371        centroid values of u_in
     372
     373        Centroid values of a and b provide diffusivity and rhs
     374
     375        Solution u is retruned in u_out
     376        """
     377
     378        if u_out == None:
     379            u_out = Quantity(self.domain)
     380
     381       
     382        self.update_elliptic_matrix(a)       
     383        self.update_elliptic_boundary_term(u_in)
     384
     385        # Pull out arrays and a matrix operator
     386        A = self
     387        rhs = b.centroid_values - self.boundary_term
     388        x0 = u_in.centroid_values
     389
     390        x = conjugate_gradient(A,rhs,x0,imax=imax, tol=tol, atol=atol, iprint=iprint)
     391
     392        u_out.set_values(x, location='centroids')
     393        u_out.set_boundary_values(u_in.boundary_values)
     394
     395        return u_out
     396   
     397
     398    def parabolic_solve(self, u_in, b, a = None, u_out = None, \
     399                       imax=10000, tol=1.0e-8, atol=1.0e-8, iprint=None):
     400        """
     401        Solve for u in the equation
     402
     403        ( I + dt div a grad ) u = b
     404
     405        u | boundary = g
     406
     407
     408        u_in, u_out, f anf g are Quantity objects
     409
     410        Dirichlet BC g encoded into u_in boundary_values
     411
     412        Initial guess for iterative scheme is given by
     413        centroid values of u_in
     414
     415        Centroid values of a and b provide diffusivity and rhs
     416
     417        Solution u is retruned in u_out
     418
     419        """
     420
     421        if u_out == None:
     422            u_out = Quantity(self.domain)
     423
     424
     425        self.update_elliptic_matrix(a)
     426        self.update_elliptic_boundary_term(u_in)
     427
     428        self.set_parabolic_solve(True)
     429
     430
     431        # Pull out arrays and a matrix operator
     432        IdtA = self
     433        rhs = b.centroid_values + (self.dt * self.boundary_term)
     434        x0 = u_in.centroid_values
     435
     436        x = conjugate_gradient(IdtA,rhs,x0,imax=imax, tol=tol, atol=atol, iprint=iprint)
     437
     438        self.set_parabolic_solve(False)
     439
     440        u_out.set_values(x, location='centroids')
     441        u_out.set_boundary_values(u_in.boundary_values)
     442
     443        return u_out
     444
     445 
  • trunk/anuga_core/source/anuga/operators/test_kinematic_viscosity.py

    r8152 r8154  
     1import operator
    12from anuga import Domain
    23from anuga import Quantity
     
    104105        operator = self.operator1()
    105106        domain = operator.domain
    106        
    107         operator.update_elliptic_matrix()
     107
     108        a = Quantity(operator.domain)
     109        a.set_values(1.0)
     110        a.set_boundary_values(1.0)
     111       
     112        operator.update_elliptic_matrix(a)
    108113
    109114        A = operator.elliptic_matrix
     
    111116        assert num.allclose(A.todense(), num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)]))
    112117
    113         diffusivity = operator.diffusivity
    114         diffusivity.set_values(10.0)
    115         diffusivity.set_boundary_values(10.0)
    116        
    117         operator.update_elliptic_matrix()
     118        a.set_values(10.0)
     119        a.set_boundary_values(10.0)
     120       
     121        operator.update_elliptic_matrix(a)
    118122
    119123        assert num.allclose(A.todense(), 10*num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)]))
     
    126130
    127131        domain = operator.domain
    128         diffusivity = operator.diffusivity
     132
     133        a = Quantity(operator.domain)
     134        a.set_values(1.0)
     135        a.set_boundary_values(1.0)
     136        operator.update_elliptic_matrix(a)
    129137
    130138        A = operator.elliptic_matrix
    131139
    132         diffusivity.set_values(1.0)
    133         diffusivity.set_boundary_values(1.0)
    134         operator.update_elliptic_matrix()
    135 
     140   
    136141        A0 = num.array([[-3.0,3.0,0.0,0.0,0.0,0.0],
    137142                        [0.0,-6.0/sqrt(5.0),0.0,0.0,6.0/sqrt(5.0),0.0]])
     
    144149        assert num.allclose(A.todense(), A0+A1+A2)
    145150
    146         diffusivity.set_values([2.0, 1.0], location = 'centroids')
    147         diffusivity.set_boundary_values(1.0)
    148         operator.update_elliptic_matrix()
     151        a.set_values([2.0, 1.0], location = 'centroids')
     152        a.set_boundary_values(1.0)
     153        operator.update_elliptic_matrix(a)
    149154
    150155        A = operator.elliptic_matrix
     
    154159        assert num.allclose(A.todense()[1,:], A0[1,:]+1.5*A1[1,:]+A2[1,:])
    155160
    156         diffusivity.set_values([-2.0, -2.0], location = 'centroids')
    157         diffusivity.set_boundary_values(1.0)
    158         operator.update_elliptic_matrix()
     161        a.set_values([-2.0, -2.0], location = 'centroids')
     162        a.set_boundary_values(1.0)
     163        operator.update_elliptic_matrix(a)
    159164
    160165        assert num.allclose(A.todense()[0,:], -2*A0[0,:]-0.5*A1[0,:]-0.5*A2[0,:])
     
    166171
    167172        print operator.apply_triangle_areas
    168        
    169         n = operator.n
     173
     174        a = Quantity(operator.domain)
     175        a.set_values(1.0)
     176        a.set_boundary_values(1.0)
     177
     178        operator.update_elliptic_matrix()
     179
     180       
     181
     182        q_in = Quantity(operator.domain)
     183        q_in.set_values(1.0)
     184        q_in.set_boundary_values(1.0)
     185       
     186        n = operator.n
     187       
     188        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
     189
     190
     191        q_1 = operator.elliptic_multiply(q_in)
     192
     193        q_2 = operator.elliptic_multiply(q_in, quantity_out = q_in)
     194
     195        assert id(q_in) == id(q_2)
     196
     197        assert num.allclose(q_1.centroid_values,q_2.centroid_values)
     198
     199        assert num.allclose( num.zeros((n,), num.float), q_1.centroid_values )
     200
     201        #Now have different boundary values
     202
     203        q_in.set_values(1.0)
     204        q_in.set_boundary_values(0.0)
     205        operator.update_elliptic_matrix(a)
     206
     207
     208        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
     209
     210
     211        q_1 = operator.elliptic_multiply(q_in)
     212
     213        assert num.allclose( [-6.0-12.0/sqrt(5)], q_1.centroid_values )
     214       
     215    def test_elliptic_multiply_exclude_boundary_one_triangle(self):
     216        operator = self.operator1()
     217        operator.set_triangle_areas(False)
     218
     219        print operator.apply_triangle_areas
     220        #n = operator.n
    170221
    171222        q_in = Quantity(operator.domain)
     
    174225        operator.update_elliptic_matrix()
    175226
    176        
     227
     228        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
     229
     230
     231        q_1 = operator.elliptic_multiply(q_in, include_boundary=False)
     232
     233
     234        assert num.allclose( [-6.0-12.0/sqrt(5)], q_1.centroid_values )
     235
     236    def test_elliptic_multiply_include_boundary_one_triangle(self):
     237        operator = self.operator1()
     238        operator.set_triangle_areas(True)
     239
     240        n = operator.n
     241
     242        q_in = Quantity(operator.domain)
     243        q_in.set_values(1.0)
     244        q_in.set_boundary_values(1.0)
     245       
     246        operator.update_elliptic_matrix()
     247
     248
    177249        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    178250
     
    180252        q_1 = operator.elliptic_multiply(q_in)
    181253
    182         q_2 = operator.elliptic_multiply(q_in, quantity_out = q_in)
     254        q_2 = operator.elliptic_multiply(q_in, output = q_in)
    183255
    184256        assert id(q_in) == id(q_2)
     
    186258        assert num.allclose(q_1.centroid_values,q_2.centroid_values)
    187259
    188         assert num.allclose( num.zeros((n,), num.float), q_1.centroid_values )
     260        assert num.allclose( [-12.0-24.0/sqrt(5)], q_1.centroid_values )
    189261
    190262        #Now have different boundary values
     
    200272        q_1 = operator.elliptic_multiply(q_in)
    201273
    202         assert num.allclose( [-6.0-12.0/sqrt(5)], q_1.centroid_values )
    203        
     274        assert num.allclose( [-12.0-24.0/sqrt(5)], q_1.centroid_values )
     275
    204276    def test_elliptic_multiply_exclude_boundary_one_triangle(self):
    205277        operator = self.operator1()
    206         operator.set_triangle_areas(False)
    207 
    208         print operator.apply_triangle_areas
    209         #n = operator.n
     278        operator.set_triangle_areas(True)
    210279
    211280        q_in = Quantity(operator.domain)
     
    218287
    219288
    220         q_1 = operator.elliptic_multiply(q_in, include_boundary=False)
    221 
    222 
    223         assert num.allclose( [-6.0-12.0/sqrt(5)], q_1.centroid_values )
    224 
    225     def test_elliptic_multiply_include_boundary_one_triangle(self):
    226         operator = self.operator1()
    227         operator.set_triangle_areas(True)
    228 
    229         n = operator.n
    230 
    231         q_in = Quantity(operator.domain)
    232         q_in.set_values(1.0)
    233         q_in.set_boundary_values(1.0)
     289        q_1 = operator.elliptic_multiply(q_in)
     290
     291
     292        assert num.allclose( [-12.0-24.0/sqrt(5)], q_1.centroid_values )
     293
     294    def test_mul_arg(self):
     295        operator = self.operator1()
     296
     297        u = Quantity(operator.domain)
     298        u.set_values(2.0)
     299        #q boundary_values should equal 0.0
     300
     301
     302
     303        operator.update_elliptic_boundary_term(u)
     304
     305        r = 2.0
     306
     307        try:
     308            q_out = operator * 2.0
     309        except TypeError:
     310            pass
     311        else:
     312            raise Exception('Should have caught an TypeError')
     313
     314
     315    def test_mul(self):
     316        operator = self.operator1()
     317
     318        u = Quantity(operator.domain)
     319        u.set_values(2.0)
     320        #q boundary_values should equal 0.0
     321
    234322        operator.update_elliptic_matrix()
    235323
    236 
    237         A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    238 
    239 
    240         q_1 = operator.elliptic_multiply(q_in)
    241 
    242         q_2 = operator.elliptic_multiply(q_in, quantity_out = q_in)
    243 
    244         assert id(q_in) == id(q_2)
    245 
    246         assert num.allclose(q_1.centroid_values,q_2.centroid_values)
    247 
    248         assert num.allclose( num.zeros((n,), num.float), q_1.centroid_values )
    249 
    250         #Now have different boundary values
    251 
    252         q_in.set_values(1.0)
    253         q_in.set_boundary_values(0.0)
    254         operator.update_elliptic_matrix()
    255 
    256 
    257         A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    258 
    259 
    260         q_1 = operator.elliptic_multiply(q_in)
    261 
    262         assert num.allclose( [-12.0-24.0/sqrt(5)], q_1.centroid_values )
    263 
    264     def test_elliptic_multiply_exclude_boundary_one_triangle(self):
    265         operator = self.operator1()
    266         operator.set_triangle_areas(True)
    267 
    268         q_in = Quantity(operator.domain)
    269         q_in.set_values(1.0)
    270         q_in.set_boundary_values(1.0)
    271         operator.update_elliptic_matrix()
    272 
    273 
    274         A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    275 
    276 
    277         q_1 = operator.elliptic_multiply(q_in, include_boundary=False)
    278 
    279 
    280         assert num.allclose( [-12.0-24.0/sqrt(5)], q_1.centroid_values )
    281 
    282 
    283 
    284     def test_mul(self):
    285         operator = self.operator1()
    286 
    287         q = Quantity(operator.domain)
    288         q.set_values(2.0)
    289         #q boundary_values should equal 0.0
    290 
    291         operator.build_elliptic_boundary_term()
    292         A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    293         V1 = num.array([2.0]) #(uh)=2
     324        operator.update_elliptic_boundary_term(u)
     325
     326        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
     327        V1 = num.array([2.0]) #u=2
    294328        U1 = num.array([[2.0],[0.0],[0.0],[0.0]])
    295         assert num.allclose(operator * q, 2*num.array(num.mat(A)*num.mat(U1)).reshape(1,))
    296 
    297     def test_cg_solve(self):
    298         #cf self.test_mul()
    299         operator1 = self.operator1()
    300         operator1.apply_stage_heights(num.array([[1.0]])) #h=1
    301         operator1.set_qty_considered('u')
    302         V = num.array([2.0]) #h=1, (uh)=2
    303         A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    304         U = num.array([[2.0,2.0],[2.0,1.0],[1.0,2.0],[1.0,0.0]])
    305         test = 2*num.mat(A)*num.mat(U[:,0].reshape(4,1))
    306         X = operator1.cg_solve(num.array(test).reshape(1,))
    307         assert num.allclose(V, X)
    308 
    309     def test_parabolic_solve(self):
    310         operator1 = self.operator1()
    311         operator1.apply_stage_heights(num.array([[1.0]])) #h=1
    312         A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
    313         U = num.array([[2.0,1.0],[2.0,1.0],[1.0,2.0],[1.0,0.0]])
    314         u = num.array([[2.0,1.0]])
    315         U_new = operator1.parabolic_solver(u)
    316         U_mod = num.array([[0.0,0.0],[2.0,1.0],[1.0,2.0],[1.0,0.0]])
    317         U_mod[0,:] = U_new
    318         assert num.allclose(U_new - operator1.dt * 2 * num.mat(A)*num.mat(U_mod), U[0,:])
     329
     330        q_out = operator * u
     331       
     332        assert num.allclose(q_out.centroid_values, 2*num.array(num.mat(A)*num.mat(U1)).reshape(1,))
     333
     334    def test_elliptic_solve_one_triangle(self):
     335
     336        operator = self.operator1()
     337        n = operator.n
     338       
     339        U = num.array([2.0,2.0,1.0,1.0])
     340
     341        u_in = Quantity(operator.domain)
     342        u_in.set_values(U[:1], location='centroids')
     343        u_in.set_boundary_values(U[1:])
     344
     345        a = Quantity(operator.domain)
     346        a.set_values(1.0)
     347        a.set_boundary_values(1.0)
     348
     349        # Do this to get access to the matrix
     350        # This is also called inside elliptic_solve
     351        operator.update_elliptic_matrix(a)
     352
     353        V = num.array([2.0]) #h=1, u=2
     354        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
     355        #U = num.array([[2.0,2.0],[2.0,1.0],[1.0,2.0],[1.0,0.0]])
     356
     357        #Setup up rhs as b = A u
     358        X = num.array(2*num.mat(A)*num.mat(U.reshape(4,1))).reshape(1,)
     359        b = Quantity(operator.domain)
     360        b.set_values(X, location='centroids')
     361
     362        u_in.set_values(0.0)
     363
     364        u_out = operator.elliptic_solve(u_in, b, a, iprint=1)
     365
     366        assert num.allclose(u_out.centroid_values, U[:n])
     367
     368
     369    def test_elliptic_solve_two_triangle(self):
     370
     371        operator = self.operator2()
     372        n = operator.n
     373       
     374        U = num.array([2.0,3.0,1.0,1.0,4.0,3.0])
     375
     376        u_in = Quantity(operator.domain)
     377        u_in.set_values(U[:2], location='centroids')
     378        u_in.set_boundary_values(U[2:])
     379
     380        a = Quantity(operator.domain)
     381        a.set_values(1.0)
     382        a.set_boundary_values(1.0)
     383
     384        # Do this to get access to the matrix
     385        # This is also called inside elliptic_solve
     386        operator.update_elliptic_matrix(a)
     387
     388        V1 = U[:n]
     389        V2 = U[n:]
     390
     391        A = num.mat(operator.elliptic_matrix.todense())
     392        U = num.mat(U.reshape(6,1))
     393
     394        #Setup up rhs as b = A u
     395        X = num.array(2*A*U).reshape(2,)
     396
     397        b = Quantity(operator.domain)
     398        b.set_values(X, location='centroids')
     399
     400        u_in.set_values(0.0)
     401
     402        u_out = operator.elliptic_solve(u_in, b, a, iprint=1)
     403
     404        assert num.allclose(u_out.centroid_values, V1)
     405        assert num.allclose(u_out.boundary_values, V2)
     406
     407    def test_elliptic_solve_rectangular_cross(self):
     408
     409        from anuga import rectangular_cross_domain
     410
     411        m1 = 10
     412        n1 = 10
     413        domain = rectangular_cross_domain(m1,n1)
     414
     415        # Diffusivity
     416        a = Quantity(domain)
     417        a.set_values(1.0)
     418        a.set_boundary_values(1.0)
     419
     420        # Quantity to solve
     421        u = Quantity(domain)
     422        u.set_values(0.0)
     423        u.set_boundary_values(1.0)
     424
     425        # Quantity for rhs
     426        b = Quantity(domain)
     427        b.set_values(0.0)
     428        b.set_boundary_values(0.0)
     429
     430        operator = Kinematic_Viscosity(domain)
     431
     432        n = operator.n
     433        tot_len = operator.tot_len
     434
     435        u_out = operator.elliptic_solve(u, b, a, iprint=1)
     436   
     437        assert num.allclose(u_out.centroid_values, num.ones_like(u_out.centroid_values))
     438        assert num.allclose(u_out.boundary_values, num.ones_like(u_out.boundary_values))
     439
     440
     441
     442    def test_parabolic_solve_one_triangle(self):
     443        operator = self.operator1()
     444        n = operator.n
     445        dt = operator.dt
     446
     447        U = num.array([2.0,2.0,1.0,1.0])
     448        U_mod = num.array([10.0, 2.0, 1.0, 1.0])
     449
     450        u_in = Quantity(operator.domain)
     451        u_in.set_values(U[:n], location='centroids')
     452        u_in.set_boundary_values(U_mod[n:])
     453
     454        a = Quantity(operator.domain)
     455        a.set_values(1.0)
     456        a.set_boundary_values(1.0)
     457
     458
     459        V = num.array([2.0])
     460        A = num.array([-6.0-12.0/sqrt(5), 6.0,  6.0/sqrt(5), 6.0/sqrt(5)])
     461
     462        #Setup up rhs
     463        X = U_mod[:n] - dt*2*num.array(num.mat(A)*num.mat(U_mod.reshape(4,1))).reshape(n,)
     464        b = Quantity(operator.domain)
     465        b.set_values(X, location='centroids')
     466
     467
     468        u_out = operator.parabolic_solve(u_in, b, a, iprint=1)
     469
     470
     471        assert num.allclose(u_out.centroid_values, U_mod[:n])
     472
     473
     474    def test_parabolic_solve_two_triangles(self):
     475        operator = self.operator2()
     476        n = operator.n
     477        nt = operator.tot_len
     478
     479        dt = operator.dt
     480
     481        U = num.array([2.0,3.0,1.0,1.0,4.0,3.0])
     482        U_mod = num.array([4.0,2.0,1.0,1.0,4.0,3.0])
     483
     484
     485        u_in = Quantity(operator.domain)
     486        u_in.set_values(U[:n], location='centroids')
     487        u_in.set_boundary_values(U_mod[n:])
     488
     489        a = Quantity(operator.domain)
     490        a.set_values(1.0)
     491        a.set_boundary_values(1.0)
     492
     493        operator.update_elliptic_matrix(a)
     494
     495
     496        A = num.array([[-8.36656315,  3., 2.68328157,  2.68328157,  0.,  0. ],
     497                       [ 3., -8.36656315 , 0. , 0. ,  2.68328157,  2.68328157]])
     498
     499        assert num.allclose(A,operator.elliptic_matrix.todense())
     500
     501
     502
     503        #Setup up rhs
     504        X = U_mod[:n] - dt*2*num.array(num.mat(A)*num.mat(U_mod.reshape(nt,1))).reshape(n,)
     505        b = Quantity(operator.domain)
     506        b.set_values(X, location='centroids')
     507
     508
     509        u_out = operator.parabolic_solve(u_in, b, a, iprint=1)
     510
     511
     512        assert num.allclose(u_out.centroid_values, U_mod[:n])
     513
     514    def test_parabolic_solve_rectangular_cross(self):
     515
     516        from anuga import rectangular_cross_domain
     517
     518        m1 = 10
     519        n1 = 10
     520        domain = rectangular_cross_domain(m1,n1)
     521
     522        # Diffusivity
     523        a = Quantity(domain)
     524        a.set_values(1.0)
     525        a.set_boundary_values(1.0)
     526
     527        # Quantity initial condition
     528        u_in = Quantity(domain)
     529        #u_in.set_values( 0.0 )
     530        u_in.set_values(lambda x,y : 16.0*x*(1-x)*y*(1-y))
     531        u_in.set_boundary_values(0.0)
     532
     533        # Quantity to solve
     534        u_mod = Quantity(domain)
     535        u_mod.set_values(lambda x,y : 15.9*x*(1-x)*y*(1-y) )
     536        u_mod.set_boundary_values(0.0)
     537
     538        # Quantity for rhs
     539        b = Quantity(domain)
     540        b.set_values(0.0)
     541        b.set_boundary_values(0.0)
     542
     543        operator = Kinematic_Viscosity(domain)
     544
     545        dt = 0.01
     546        operator.dt = dt
     547        n = operator.n
     548        nt = operator.tot_len
     549
     550        operator.update_elliptic_matrix(a)
     551
     552        A = num.mat(operator.elliptic_matrix.todense())
     553        D = num.mat(operator.triangle_areas.todense())
     554        U_mod = num.concatenate( (u_mod.centroid_values, u_mod.boundary_values) )
     555
     556
     557        #Setup up rhs
     558        X = U_mod[:n] - dt*num.array(D*A*num.mat(U_mod.reshape(nt,1))).reshape(n,)
     559        b = Quantity(operator.domain)
     560        b.set_values(X, location='centroids')
     561
     562
     563        u_out = operator.parabolic_solve(u_in, b, a, iprint=1)
     564
     565        assert num.allclose(u_out.centroid_values, U_mod[:n])
     566
    319567
    320568################################################################################
  • trunk/anuga_core/source/anuga/shallow_water/test_shallow_water_domain.py

    r8124 r8154  
    512512                    (3, 1): 'Second',
    513513                    (3, 2): 'Third',
    514                     (0, 1): 'Internal'}
     514                    (0, 1): 'Internal',
     515                    (1, 2): 'Internal'}
    515516
    516517        domain = Domain(points, vertices, boundary)
     
    532533        domain.update_boundary()
    533534        domain.check_integrity()
     535
     536    def test_boundary_conditions_inconsistent_internal(self):
     537        a = [0.0, 0.0]
     538        b = [0.0, 2.0]
     539        c = [2.0, 0.0]
     540        d = [0.0, 4.0]
     541        e = [2.0, 2.0]
     542        f = [4.0, 0.0]
     543
     544        points = [a, b, c, d, e, f]
     545        #             bac,     bce,     ecf,     dbe
     546        vertices = [[1,0,2], [1,2,4], [4,2,5], [3,1,4]]
     547        boundary = {(0, 0): 'Third',
     548                    (0, 2): 'First',
     549                    (2, 0): 'Second',
     550                    (2, 1): 'Second',
     551                    (3, 1): 'Second',
     552                    (3, 2): 'Third',
     553                    (0, 1): 'Internal'}
     554
     555        domain = Domain(points, vertices, boundary)
     556
     557        try:
     558            domain.check_integrity()
     559        except AssertionError:
     560            pass
     561        else:
     562            msg = 'should have thrown assertion exception'
     563            raise Exception(msg)
     564
     565
     566
     567
    534568
    535569    def test_boundary_conditionsIII(self):
     
    678712
    679713        assert num.allclose(domain.neighbours,
    680                             [[-1,1,-1], [2,3,0], [-1,-1,1],[1,-1,-1]])
     714                            [[-1,1,-2], [2,3,0], [-3,-4,1],[1,-5,-6]])
    681715        assert num.allclose(domain.neighbour_edges,
    682716                            [[-1,2,-1], [2,0,1], [-1,-1,0],[1,-1,-1]])
  • trunk/anuga_core/source/anuga/utilities/cg_solve.py

    r8025 r8154  
    88
    99
    10 def conjugate_gradient(A,b,x0=None,imax=10000,tol=1.0e-8,atol=1.0e-14,iprint=None):
     10def conjugate_gradient(A, b, x0=None, imax=10000, tol=1.0e-8, atol=1.0e-14, iprint=None):
    1111    """
    1212    Try to solve linear equation Ax = b using
     
    2323
    2424    b  = num.array(b, dtype=num.float)
    25     if len(b.shape) != 1 :
     25    if len(b.shape) != 1:
    2626       
    2727        for i in range(b.shape[1]):
    28             x0[:,i] = _conjugate_gradient(A, b[:,i], x0[:,i],
    29                                           imax, tol, atol, iprint)
     28            x0[:, i] = _conjugate_gradient(A, b[:, i], x0[:, i],
     29                                           imax, tol, atol, iprint)
    3030    else:
    3131        x0 = _conjugate_gradient(A, b, x0, imax, tol, atol, iprint)
     
    3434   
    3535def _conjugate_gradient(A, b, x0,
    36                         imax=10000, tol=1.0e-8, atol=1.0e-14, iprint=None):
    37    """
     36                        imax=10000, tol=1.0e-8, atol=1.0e-10, iprint=None):
     37    """
    3838   Try to solve linear equation Ax = b using
    3939   conjugate gradient method
     
    5151   """
    5252
     53    b  = num.array(b, dtype=num.float)
     54    if len(b.shape) != 1:
     55        raise VectorShapeError, 'input vector should consist of only one column'
    5356
    54    b  = num.array(b, dtype=num.float)
    55    if len(b.shape) != 1 :
    56       raise VectorShapeError, 'input vector should consist of only one column'
    57 
    58    if x0 is None:
    59       x0 = num.zeros(b.shape, dtype=num.float)
    60    else:
    61       x0 = num.array(x0, dtype=num.float)
     57    if x0 is None:
     58        x0 = num.zeros(b.shape, dtype=num.float)
     59    else:
     60        x0 = num.array(x0, dtype=num.float)
    6261
    6362
    64    #FIXME: Should test using None
    65    if iprint == None  or iprint == 0:
    66       iprint = imax
     63    if iprint == None  or iprint == 0:
     64        iprint = imax
    6765
    68    i=1
    69    x = x0
    70    r = b - A*x
    71    d = r
    72    rTr = num.dot(r,r)
    73    rTr0 = rTr
     66    i = 1
     67    x = x0
     68    r = b - A * x
     69    d = r
     70    rTr = num.dot(r, r)
     71    rTr0 = rTr
    7472
    75    #FIXME Let the iterations stop if starting with a small residual
    76    while (i<imax and rTr>tol**2*rTr0 and rTr>atol**2 ):
    77        q = A*d
    78        alpha = rTr/num.dot(d,q)
    79        x = x + alpha*d
    80        if i%50 :
    81            r = b - A*x
    82        else:
    83            r = r - alpha*q
    84        rTrOld = rTr
    85        rTr = num.dot(r,r)
    86        bt = rTr/rTrOld
    8773
    88        d = r + bt*d
    89        i = i+1
    90        if i%iprint == 0 :
    91           log.info('i = %g rTr = %20.15e' %(i,rTr))
     74   
     75    #FIXME Let the iterations stop if starting with a small residual
     76    while (i < imax and rTr > tol ** 2 * rTr0 and rTr > atol ** 2):
     77        q = A * d
     78        alpha = rTr / num.dot(d, q)
     79        xold = x
     80        x = x + alpha * d
    9281
    93        if i==imax:
     82        dx = num.linalg.norm(x-xold)
     83        if dx < atol :
     84            break
     85           
     86        if i % 50:
     87            r = b - A * x
     88        else:
     89            r = r - alpha * q
     90        rTrOld = rTr
     91        rTr = num.dot(r, r)
     92        bt = rTr / rTrOld
     93
     94        d = r + bt * d
     95        i = i + 1
     96        if i % iprint == 0:
     97            log.info('i = %g rTr = %15.8e dx = %15.8e' % (i, rTr, dx))
     98
     99        if i == imax:
    94100            log.warning('max number of iterations attained')
    95             msg = 'Conjugate gradient solver did not converge: rTr==%20.15e' %rTr
     101            msg = 'Conjugate gradient solver did not converge: rTr==%20.15e' % rTr
    96102            raise ConvergenceError, msg
    97103
    98    return x
     104    #print x
     105    return x
    99106
  • trunk/anuga_core/source/anuga/utilities/sparse.py

    r8127 r8154  
    291291
    292292    def __repr__(self):
    293         return '%d X %d sparse matrix:\n' %(self.M, self.N) + `self.data`
     293        return '%d X %d sparse matrix:\n' %(self.M, self.N) + 'data '+ `self.data` + '\ncolind ' + \
     294            `self.colind` + '\nrow_ptr ' + `self.row_ptr`
    294295
    295296    def __len__(self):
Note: See TracChangeset for help on using the changeset viewer.