source: trunk/anuga_core/source/anuga/structures/riverwall.py @ 9105

Last change on this file since 9105 was 9105, checked in by davies, 11 years ago

Fixed conflicts

File size: 26.9 KB
Line 
1import numpy
2
3class RiverWall:
4    """Define the elevation of 'riverwalls'.
5
6    These are located along each cell edge, and can have an elevation different
7    from the bed elevation.
8
9    For the DE1 algorithm, they are used in computing the 'z_half' value [if they
10    are greater than either edge elevation].
11
12    In addition, the DE1 fluxes at riverwalls are adjusted to agree with a weir relation,
13    so long as the riverwall is not too deeply submerged.
14
15    As of 22/04/2014, they are only implemented for DE1 [the shallow water
16    component would be more difficult to implement with other algorithms]
17       
18    How the flux over the riverwall is computed:
19    # We have a riverwall, which is treated as a weir.
20    #
21    # Say the headwater-head is the upstream water depth above the weir elevation (min 0), and
22    #   the tailwater head is the downstream water depth above the weir elevation (min 0).
23    #   By definition headwater-head > tailwater-head.
24    #
25    # Let s = (headwater head) / (tailwater head), and h = (tailwater head)/(weir height)
26    #  where 'weir height' is the elevation of the weir crest above the minimum
27    #  of the left/right bed elevations
28    #
29    # Denote ID as the 'ideal' weir flow, computed from the hydraulic
30    # formula (including a submergence correction factor from Villemonte,
31    # 1947),
32    #      Q1 = 2/3*headwater_head*sqrt(g*2/3*headwater_head)*Qfactor
33    #      Q2 = 2/3*tailwater_head*sqrt(g*2/3*headwater_head)*Qfactor
34    # ID = Q1*(1-Q2/Q1)**0.385
35    #
36    # Denote SW as the 'shallow-water' weir flux, computed from the approximate
37    # reimann solver, where the mid-edge-elevation is the weir crest elevation.
38    # This makes clear sense for DE1. Cell centroid stage/height/bed_elevation
39    # are used in the flux computation
40    #
41    # Then the flux over the weir is computed from:
42    #   w1 = min( max(s-s1, 0.)/(s2-s1), 1.0) # Factor describing relative submergence
43    #   w1' = min( max(h-h1,0.)/(h2-h1), 1.0) # Factor describing absolute submergence
44    #  flux_over_weir = (w1*SW + (1-w1)*ID)*( 1-w1') + (w1')*SW
45    #
46    # The key idea is that if s<s1, h<h1, then the ideal weir solution is
47    # used. Otherwise, we linearly blend with the SW solution,
48    # and the SW solution is used completely if s>s2 or h>h2
49
50    """
51   
52    def __init__(self, domain):
53        """Riverwall data structure
54
55        Allows reasonably efficient storage of riverwall elevations and hydraulic
56        properties
57
58        NOTE: In domain.edge_flux_type, riverwalls correspond to the value 1
59
60        RiverWall variables are initialised to dummy values, because even
61        if no riverwalls are used, some values have to be passed to the flux computation
62
63        Hydraulic parameters are
64        Qfactor -- Multiplicative factor for ideal weir relation (calibration coef)
65        s1 --  Submergence ratio at which we start blending with the shallow water solution (<s2)
66        s2 -- Submergence ratio at which we entirely use the shallow water solution  (>s1)
67        h1 -- Tailwater head / weir height at which we start blending with the shallow water solution (<h2)
68        h2 -- Tailwater head / weir height at which we entirely use the shallow water solution (>h1)
69
70        # Default riverwall hydraulic parameters
71        default_riverwallPar={'Qfactor':1.0, 
72                              's1': 0.9,     
73                              's2': 0.95,     
74                              'h1': 1.0,     
75                              'h2': 1.5       
76                              }
77
78        Other variables are:
79
80            riverwall_elevation -- Variable to hold riverwall elevations.
81                                   len = number of riverwall edges in the domain.
82                                   First entry corresponds to first riverwall edge in domain.edge_coordinates,
83                                   second entry to second riverwall edge in domain.edge_coordinates, etc
84
85            hydraulic_properties_rowIndex --  Variable to hold the row-index of the hydraulic properties table
86                                               len = number of riverwall edges
87                                                     in the domain, ordered like riverwall_elevation
88
89            riverwall_edges -- Holds indices of edges in domain which are riverwalls, ordered like riverwall_elevation
90
91            names -- list with the names of the riverwalls
92                     len = number of riverwalls which cover edges in the domain
93
94            hydraulic_variable_names -- Variables to hold the names of variables in columns of the hydraulic
95                                        properties table. THE ORDER IS IMPORTANT -- C code ASSUMES IT
96
97            ncol_hydraulic_properties -- Number of columns in the hydraulic properties table
98                                        [ = len(hydraulic_variable_names) ]
99
100            hydraulic_properties -- Array with the hydraulic parameters for each riverwall.
101                                      number of rows = number of riverwalls which cover edges in the domain
102                                      number of cols = number of hydraulic variable names
103
104                                   
105            input_riverwall_geo, input_riverwall_par -- holds input information
106
107        """
108        self.domain=domain
109
110        default_float=-9.0e+20
111        default_int=-9e+20
112        self.riverwall_elevation=numpy.array([default_float])
113
114        self.hydraulic_properties_rowIndex=numpy.array([default_int])
115
116        self.names=[ ]
117
118        # Default riverwall hydraulic parameters
119        self.default_riverwallPar={'Qfactor':1.0, 
120                                   's1': 0.9,     
121                                   's2': 0.95,     
122                                   'h1': 1.0,     
123                                   'h2': 1.5       
124                                   }
125
126
127        self.hydraulic_variable_names=['Qfactor', 's1', 's2', 'h1', 'h2']
128        #self.hydraulic_variable_names=('Qfactor',)
129
130        self.ncol_hydraulic_properties=len(self.hydraulic_variable_names)
131        # Variable to hold the riverwall hydraulic properties in a table
132        #  number of rows = number of riverwalls which cover edges in the domain
133        #  number of cols = number of hydraulic variable names
134        self.hydraulic_properties=numpy.array([ [default_float] ])
135
136        # Variable to hold the indices of riverwall edges
137        #    len = number of riverwall edges in the domain
138        self.riverwall_edges=numpy.array([default_int])
139
140        # Input info
141        self.input_riverwall_geo=None
142        self.input_riverwallPar=None
143
144
145    def create_riverwalls(self, riverwalls, riverwallPar={ },
146                          default_riverwallPar={ },
147                          tol=1.0e-04, verbose=True):
148        """Add riverwalls at chosen locations along the mesh
149
150        As of 22/04/2014, these only work with DE1 [for which the concept is natural]
151
152        The walls MUST EXACTLY COINCIDE with edges along the mesh
153       
154        You can force the mesh to do this by passing riverwalls.values()
155        to the 'breaklines' argument in the function create_mesh_from_regions. You
156        may also need to set the maximum_triangle_area for regions, if the breaklines
157        split the region.  Do this with the regionPtArea argument in
158        create_mesh_from_regions.
159
160        As of 22/04/2014, the computational method used here is very 'brute-force'
161        For each segment on each riverwall, every point in the mesh is checked to see
162        if it is on the segment. A possibly faster/less memory method would be to
163        'walk' through connected edges on the mesh.
164
165        Inputs:
166            riverwalls: Dictionary of '3D polygons', containing xyz locations of named riverwalls.
167
168                exampleRiverWalls = { # Left bank n1 --
169                                      'n1': [[1.0, 1000., 2.],
170                                             [1.0, 50., 3.]],
171                                      # Left bank n2
172                                       'n2': [[2.0, 30., 1.0],
173                                              [3.0, 20., 2.],
174                                              [2.5, 15., 1.5]]
175                                    }
176
177            riverwallPar: Dictionary containing a dictionary of named hydraulic parameters for each named riverwall
178                          If parameters are not provided, default values will be used.
179                          See the help for class 'RiverWall' for an explanation of these
180
181                exampleRiverWallPar = {'n2': {'Qfactor':0.5} }
182                    This would use a Qfactor of 0.5 for riverwall 'n2', while the other riverwall would have the default values
183
184            default_riverwallPar:  Dictionary containing default values of the riverwall parameters, to be used
185                                   if they are not explicitly set.
186                                   If not provided, defaults from __init__ are used. See the help for class 'RiverWall' for more info
187
188                example_default_riverwallPar = {'Qfactor':1.5, 
189                                                's1': 0.9,     
190                                                's2': 0.95,     
191                                                'h1': 1.0,     
192                                                'h2': 1.5       
193                                               }
194
195                example_default_riverwallPar = {'Qfactor':1.5, 
196                                                's1': 10000.,     
197                                                's2': 20000.     
198                                               } # Here h1/h2 defaults will come from __init__
199                 
200
201            tol: Edges will be assigned a riverwall elevation if they are within 'tol' of
202                 a segment in riverwalls. Round-off error means this should not be too small.
203
204            verbose: TRUE/FALSE Print lots of information
205
206        Outputs:
207            None, but it sets domain.edge_flux_type = 1 for every edge on a riverwall
208            Also, it adds a RiverWall object domain.riverwallData to the domain
209            The latter contains the riverwall heights, names, and hydraulic properties for each edge, in
210              a way we can pass in/out of C code.
211
212        """
213
214        if(verbose):       
215            print ' '
216            print 'WARNING: Riverwall is an experimental feature'
217            print '         At each riverwall edge, we place a thin "wall" between'
218            print '          the 2 edges -- so each sees its neighbour edge as having'
219            print '          bed elevation = max(levee height, neighbour bed elevation)'
220            print '         We also force the discharge with a weir relation, blended with'
221            print '          the shallow water flux solution as the ratio (min_head)/(weir_height) becomes '
222            print '          large, or the ratio (downstream_head)/(upstream_head) becomes large'
223            print ' '
224            print '  It works in parallel, but you must use domain.riverwallData.create_riverwall AFTER distributing the mesh'
225            print ' '
226
227        # NOTE: domain.riverwallData is initialised in shallow_water_domain.py for DE1
228
229        domain=self.domain
230
231       
232        # Check flow algorithm
233        if(domain.flow_algorithm!='DE1'):
234            raise Exception, 'Riverwalls are currently only supported when domain.flow_algorithm="DE1"'
235
236        if(len(self.names)>0):
237            # Delete any existing riverwall data
238            # The function cannot presently be used to partially edit riverwall data
239            if(verbose):
240                print 'Warning: There seems to be existing riverwall data'
241                print 'It will be deleted and overwritten with this function call'
242            domain.riverwallData.__init__(domain)
243
244        # Store input parameters
245        # FIXME: Is this worth it?
246        self.input_riverwall_geo=riverwalls
247        self.input_riverwallPar=riverwallPar
248
249        # Update self.default_riverwallPar
250        for i in self.default_riverwallPar.keys():
251            if(default_riverwallPar.has_key(i)):
252                self.default_riverwallPar[i]=default_riverwallPar[i]
253
254        # Check that all the keys in default_riverwallPar are allowed
255        for i in default_riverwallPar.keys():
256            if(not self.default_riverwallPar.has_key(i)):
257                msg='Key ', i + ' in default_riverwallPar not recognized'
258                raise Exception, msg
259        # Final default river-wall parameters
260        default_riverwallPar=self.default_riverwallPar
261       
262        # Check that all named inputs in riverwallPar correspond to names in
263        # riverwall
264        for i in riverwallPar.keys():
265            if not riverwalls.has_key(i):
266                msg= 'Key ', i, ' in riverwallPar has no corresponding key in riverwall'
267                raise Exception, msg
268            #
269            # Check that all hydraulic parameter names in riverwallPar correspond
270            # to names in default_riverwallPar
271            #
272            for j in riverwallPar[i].keys():
273                if not default_riverwallPar.has_key(j):
274                    msg = 'Hydraulic parameter named ', j ,\
275                          ' not recognised in default_riverwallPar'
276                    raise Exception, msg
277       
278        if(verbose):
279            print 'Setting riverwall elevations ...'
280
281        # Set up geometry
282        exy=domain.edge_coordinates
283        llx=domain.mesh.geo_reference.get_xllcorner()
284        lly=domain.mesh.geo_reference.get_yllcorner()
285
286        # Temporary variables
287        from anuga.config import max_float
288        riverwall_elevation=exy[:,0]*0. - max_float
289        riverwall_Qfactor=exy[:,0]*0.
290        riverwall_rowIndex=exy[:,0]*0 -1.
291        riverwall_rowIndex.astype(int)
292
293        # Loop over all segments in each riverwall, and set its elevation
294        nw=range(len(riverwalls))
295        nw_names=riverwalls.keys() # Not guarenteed to be in deterministic order
296        for i in nw:
297            # Name of riverwall
298            riverwalli_name=nw_names[i]
299            # Look at the ith riverwall
300            riverwalli=riverwalls[riverwalli_name]
301
302            ns=len(riverwalli)-1
303
304            if(verbose):
305                print 'Wall ' + str(i) +' ....'
306
307            for j in range(ns):
308                if(verbose):
309                    print '    Segment ' + str(j) +' ....'
310                # Start and end xyz coordinates
311                start=riverwalli[j]
312                end=riverwalli[j+1]
313
314                if(len(start)!=3 | len(end)!=3):
315                    msg='Each riverwall coordinate must have at exactly 3 values [xyz]'
316                    raise Exception, msg
317
318                # Find length
319                segLen=( (start[0]-end[0])**2+(start[1]-end[1])**2)**0.5
320                if(segLen<tol):
321                    print 'Segment with length < tolerance ' + str(tol) +' ignored'
322                    continue 
323               
324                # Find edge indices which are within 'tol' of the segment
325                # We use a simple, inefficient method [but likely ok in practice
326                # except for very complex riverwalls]
327               
328                # Unit vector along segment
329                se_0=-(start[0]-end[0])/segLen
330                se_1=-(start[1]-end[1])/segLen
331
332                # Vector from 'start' to every point on mesh
333                # NOTE: We account for georeferencing
334                pv_0 = exy[:,0]-(start[0]-llx)
335                pv_1 = exy[:,1]-(start[1]-lly)
336
337                pvLen=( pv_0**2 + pv_1**2)**0.5
338
339                # Dot product of pv and se == along-segment distance of projection
340                # of each point onto segment
341                pv_dot_se = pv_0*se_0+pv_1*se_1
342                # Normal distance^2 of each point to segment
343                perp_len_sq = pvLen**2.-pv_dot_se**2.
344               
345                # Point is on a levee if the perpendicular distance is < tol,
346                # AND it is between start and end [within a tolerance]
347                onLevee=(perp_len_sq<tol**2)*(pv_dot_se > 0.-tol)*(pv_dot_se<segLen+tol)
348                onLevee=onLevee.nonzero()
349                onLevee=onLevee[0]
350                if(len(onLevee)==0):
351                    continue
352
353                if(verbose):
354                    print '       Finding ' + str(len(onLevee)) + ' edges on this segment '
355           
356                # Levee has Edge_flux_type=1 
357                domain.edge_flux_type[onLevee]=1
358     
359                # Get edge elevations as weighted averages of start/end elevations
360                w0=pv_dot_se[onLevee]/segLen
361                w0=w0*(w0>=0.0) # Enforce min of 0
362                w0=w0*(w0<=1.0) + 1.0*(w0>1.0) # Max of 1
363                riverwall_elevation[onLevee]= start[2]*(1.0-w0)+w0*end[2]
364
365                # Record row index
366                riverwall_rowIndex[onLevee] = i
367
368        # Now, condense riverwall_elevation to array with length = number of riverwall edges
369        #
370        # FIXME: We do this to avoid storing a riverwall_elevation for every edge in the mesh
371        #        However, the data structure ends up being quite complex -- maybe there is a better way?
372        #
373        # The zeroth index in domain.edge_flux_type which = 1 will correspond to riverwall_elevation[0]
374        # The first index will correspond to riverwall_elevation[1]
375        # etc
376        #
377        riverwallInds=(domain.edge_flux_type==1).nonzero()[0]
378        # elevation
379        self.riverwall_elevation=\
380            riverwall_elevation[riverwallInds]
381        # corresponding row in the hydraulic properties table
382        self.hydraulic_properties_rowIndex=\
383            riverwall_rowIndex[riverwallInds].astype(int)
384        # index of edges which are riverwalls [FIXME: Not really needed, can easily back-calculate from edge_flux_type]
385        self.riverwall_edges=riverwallInds
386
387        # Record the names of the riverwalls
388        self.names=nw_names
389
390       
391        # Now create the hydraulic properties table
392
393        # Temporary variable to hold hydraulic properties table
394        # This will have as many rows are there are distinct riverwalls,
395        # and as many columns as there are hydraulic variables
396        hydraulicTmp=numpy.zeros((len(riverwalls), len(default_riverwallPar)))*numpy.nan
397       
398        if(verbose):
399            print ' ' 
400        # Loop over every riverwall / hydraulic parameter, and set its value
401        for i in nw:
402            # Get the riverwall's name and specified parameters
403            name_riverwalli=nw_names[i]
404            if(riverwallPar.has_key(name_riverwalli)):
405                riverwalli_Par=riverwallPar[name_riverwalli]
406            else:
407                riverwalli_Par=None
408
409            # Set the ith riverwall's hydraulic properties
410            for j, hydraulicVar in enumerate(self.hydraulic_variable_names):   
411                if((riverwalli_Par is not None) and (riverwalli_Par.has_key(hydraulicVar))):
412                    if(verbose): 
413                        print 'Using provided ', hydraulicVar,\
414                           riverwalli_Par[hydraulicVar], ' for riverwall ', name_riverwalli
415                    hydraulicTmp[i,j]=riverwalli_Par[hydraulicVar] 
416                else:
417                    if(verbose): 
418                        print 'Using default ',  hydraulicVar,\
419                            default_riverwallPar[hydraulicVar], ' for riverwall ', name_riverwalli
420                    hydraulicTmp[i,j]=default_riverwallPar[hydraulicVar]
421
422        if(verbose):
423            print ' '
424
425        # Check that s1 < s2
426        for i in nw:
427            if(hydraulicTmp[i,1]>= hydraulicTmp[i,2]):
428                msg = 's1 >= s2 on riverwall ' + nw_names[i] +'. This is not allowed' 
429                raise Exception, msg
430            if( (hydraulicTmp[i,1]<0.) or (hydraulicTmp[i,2] < 0.)):
431                raise Exception, 's1 and s2 must be positive, with s1<s2'
432
433        # Check that h1 < h2
434        for i in nw:
435            if(hydraulicTmp[i,3]>= hydraulicTmp[i,4]):
436                msg = 'h1 >= h2 on riverwall ' + nw_names[i] +'. This is not allowed' 
437                raise Exception, msg
438            if((hydraulicTmp[i,3]<0.) or (hydraulicTmp[i,4] < 0.)):
439                raise Exception, 'h1 and h2 must be positive, with h1<h2'
440       
441        # Define the hydraulic properties
442        self.hydraulic_properties=hydraulicTmp
443
444        # Check for riverwall 'connectedness' errors (e.g. theoretically possible
445        # to miss an edge due to round-off)
446        self.check_riverwall_connectedness(domain, verbose,tol=tol)
447         
448        return()
449   
450    #####################################################################################
451
452    def get_centroids_corresponding_to_edgeInds(self, riverwalledgeInds):
453        """
454          Get indices of centroids containing edges with indices riverwalledgeInds
455        """
456        riverwallCentInds=numpy.floor(riverwalledgeInds/3.)
457        riverwallCentInds=riverwallCentInds.astype(int)
458
459        return riverwallCentInds
460
461    #####################################################################################
462
463    def get_vertices_corresponding_to_edgeInds(self, riverwalledgeInds, tol=1.0e-04):
464        """
465         Get indices of vertices corresponding to edges at index riverwalledgeInds
466         Since each edge has 2 vertices, use V1 and V2
467         We have to work to compute these, I can't see a simple formula
468        """
469
470        domain=self.domain
471
472        riverwallCentInds=self.get_centroids_corresponding_to_edgeInds(riverwalledgeInds)
473
474        rwV0Inds=3*riverwallCentInds #+((resid+1)%3)
475        rwV1Inds=3*riverwallCentInds+1 #((resid+2)%3)
476        rwV2Inds=3*riverwallCentInds+2 #((resid+2)%3)
477
478        # Find which 2 vertices have the edge value, by testing the
479        # x coordinate.
480        X01=0.5*(domain.vertex_coordinates[rwV0Inds,0]+domain.vertex_coordinates[rwV1Inds,0]) 
481        k01=(abs(X01- domain.edge_coordinates[riverwalledgeInds,0])<tol)
482        X12=0.5*(domain.vertex_coordinates[rwV2Inds,0]+domain.vertex_coordinates[rwV1Inds,0])
483        k12=(abs(X12 - domain.edge_coordinates[riverwalledgeInds,0])<tol)
484        X02=0.5*(domain.vertex_coordinates[rwV2Inds,0]+domain.vertex_coordinates[rwV0Inds,0])
485        k02=(abs(X02 - domain.edge_coordinates[riverwalledgeInds,0])<tol)
486
487        riverwallV2Inds=riverwallCentInds*0
488        riverwallV1Inds=riverwallCentInds*0
489     
490        t1=(k01==1).nonzero()[0]
491        riverwallV2Inds[t1]=rwV0Inds[t1]
492        riverwallV1Inds[t1]=rwV1Inds[t1]
493       
494        t1=(k12==1).nonzero()[0]
495        riverwallV2Inds[t1]=rwV2Inds[t1]
496        riverwallV1Inds[t1]=rwV1Inds[t1]
497       
498        t1=(k02==1).nonzero()[0]
499        riverwallV2Inds[t1]=rwV0Inds[t1]
500        riverwallV1Inds[t1]=rwV2Inds[t1]
501
502        return riverwallV1Inds, riverwallV2Inds
503   
504    #####################################################################################
505
506    def check_riverwall_connectedness(self, warn_only=False, verbose=True, tol=1.0e-04):
507        """
508            We expect riverwalls to be connected [unless they pass over a hole]
509            However, round-off could potentially cause riverwalls to be dis-connected
510            Use this routine to check for that
511
512            Basically, we search for edges which are connected to vertices which
513                themselves are not connected to other edges
514           
515            For a continuous riverwall, this should only occur twice (at the end points)
516
517            Otherwise, the riverwall appears discontinous
518        """
519
520        domain=self.domain
521
522        if(len(self.names)==0):
523            print 'There are no riverwalls'
524            return
525
526        # Shorthand notation
527        rwd=self
528           
529        for i, name in enumerate(rwd.names):
530            # Get indices of edges on this riverwall
531            riverwalledgeInds=rwd.riverwall_edges[(rwd.hydraulic_properties_rowIndex==i).nonzero()[0]]
532            # Get their corresponding centroids
533            riverwallCentInds=rwd.get_centroids_corresponding_to_edgeInds(riverwalledgeInds)
534            # Get their corresponding vertices
535            riverwallV1Inds, riverwallV2Inds = rwd.get_vertices_corresponding_to_edgeInds(riverwalledgeInds, tol=tol)
536
537            # With discontinuous triangles, we expect edges to occur twice
538            # Let's remove duplicates to simplify the analysis
539            repeat=riverwalledgeInds*0
540            lre=len(riverwalledgeInds)
541            # edge coordinates as a complex number, for easy equality checking
542            complex_edge_coordinates=domain.edge_coordinates[riverwalledgeInds,0]+\
543                                     1j*domain.edge_coordinates[riverwalledgeInds,1]
544            for j in range(lre-1):
545                # Ignore if already checked
546                if(repeat[j]==1):
547                    continue 
548                # Check for a dupulicate 
549                dups=(complex_edge_coordinates[(j+1):lre]==complex_edge_coordinates[j]).nonzero()[0]
550                if(len(dups)>0):
551                    repeat[dups+j+1]=1
552           
553            unique_riverwall_edge_indices=(repeat==0).nonzero()[0]
554
555            # Finally, get 'unqiue' edges in the riverwall
556            uEdges=riverwalledgeInds[unique_riverwall_edge_indices]
557            #uCentroids=riverwallCentInds[unique_riverwall_edge_indices]
558            uV1=riverwallV1Inds[unique_riverwall_edge_indices]
559            uV2=riverwallV2Inds[unique_riverwall_edge_indices]
560
561            # Next, count how many times each vertex value occurs.
562            # For a 'connected' riverwall, we only want 2 edges where a vertex occurs only once.
563            lure=len(uEdges)
564            complex_v1_coordinates=domain.vertex_coordinates[uV1,0]+\
565                                   1j*domain.vertex_coordinates[uV1,1]
566            complex_v2_coordinates=domain.vertex_coordinates[uV2,0]+\
567                                   1j*domain.vertex_coordinates[uV2,1]
568            v1Counter=uEdges*0
569            v2Counter=uEdges*0
570            for j in range(lure):
571                v1Counter[j]=(complex_v1_coordinates==complex_v1_coordinates[j]).sum()+\
572                             (complex_v2_coordinates==complex_v1_coordinates[j]).sum()
573                v2Counter[j]=(complex_v1_coordinates==complex_v2_coordinates[j]).sum()+\
574                             (complex_v2_coordinates==complex_v2_coordinates[j]).sum()
575
576            num_disconnected_edges=(v1Counter==1).sum()+(v2Counter==1).sum()
577           
578            if(verbose):   
579                print 'There are ', num_disconnected_edges, ' vertices with only 1 connection on riverwall ', name
580
581            if(num_disconnected_edges==0):
582                print 'Riverwall '+name+' is not on this mesh [typical for a sub-mesh in parallel]'
583            elif(num_disconnected_edges==2):
584                if(verbose):
585                    print "  That's Good, it means the wall is continuous"
586                    print ' '
587            else:
588                msg='Riverwall ' + name +', appears to be discontinuous, possibly due to round-off issues,'+\
589                    ' be careful [try adjusting tol, or use warn_only=True to avoid error] '
590                if(warn_only):
591                    print msg
592                else:
593                    raise Exception, msg
594
595        return
596
Note: See TracBrowser for help on using the repository browser.