Changeset 9292


Ignore:
Timestamp:
Aug 12, 2014, 12:10:51 PM (11 years ago)
Author:
davies
Message:

Adding local extrapolation and flux updating

Location:
trunk
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/generic_domain.py

    r9282 r9292  
    16221622
    16231623            self.number_of_steps += 1
     1624
    16241625            if self._order_ == 1:
    16251626                self.number_of_first_order_steps += 1
     
    16781679        # Update timestep to fit yieldstep and finaltime
    16791680        self.update_timestep(yieldstep, finaltime)
     1681
     1682        if self.max_flux_update_frequency is not 1:
     1683            # Update flux_update_frequency using the new timestep
     1684            self.compute_flux_update_frequency()
    16801685
    16811686        # Update conserved quantities
  • trunk/anuga_core/source/anuga/advection/advection.py

    r8124 r9292  
    8080       
    8181        self.smooth = True
     82        self.max_flux_update_frequency=1
    8283
    8384    def check_integrity(self):
  • trunk/anuga_core/source/anuga/shallow_water/shallow_water_domain.py

    r9290 r9292  
    291291        self.boundary_flux_integral=boundary_flux_integral_operator(self)
    292292        # Make an integer counting how many times we call compute_fluxes_central -- so we know which substep we are on
    293         self.call=1
     293        #self.call=1
    294294
    295295        # List to store the volumes we computed before
     
    297297       
    298298        # Work arrays [avoid allocate statements in compute_fluxes or extrapolate_second_order]
    299         self.edge_flux_work=num.zeros(len(self.edge_coordinates[:,0])*3)
    300         self.pressuregrad_work=num.zeros(len(self.edge_coordinates[:,0]))
    301         self.x_centroid_work=num.zeros(len(self.edge_coordinates[:,0])/3)
     299        self.edge_flux_work=num.zeros(len(self.edge_coordinates[:,0])*3) # Advective fluxes
     300        self.pressuregrad_work=num.zeros(len(self.edge_coordinates[:,0])) # Gravity related terms
     301        self.x_centroid_work=num.zeros(len(self.edge_coordinates[:,0])/3) 
    302302        self.y_centroid_work=num.zeros(len(self.edge_coordinates[:,0])/3)
     303
     304        ############################################################################
     305        ## Local-timestepping information
     306        #
     307        # Fluxes can be updated every 1, 2, 4, 8, .. max_flux_update_frequency timesteps
     308        # The global timestep is not allowed to increase except when
     309        # number_of_timesteps%max_flux_update_frequency==0
     310        self.max_flux_update_frequency=2**0 # Must be a power of 2.
     311       
     312        # flux_update_frequency. The edge flux terms are re-computed only when
     313        #    number_of_timesteps%flux_update_frequency[myEdge]==0
     314        self.flux_update_frequency=num.zeros(len(self.edge_coordinates[:,0])).astype(int)+1
     315        # Flag: should we update the flux on the next compute fluxes call?
     316        self.update_next_flux=num.zeros(len(self.edge_coordinates[:,0])).astype(int)+1
     317        # Flag: should we update the extrapolation on the next extrapolation call?
     318        # (Only do this if one or more of the fluxes on that triangle will be computed on
     319        # the next timestep, assuming only the flux computation uses edge/vertex values)
     320        self.update_extrapolation=num.zeros(len(self.edge_coordinates[:,0])/3).astype(int)+1
     321
     322        # edge_timestep [wavespeed/radius] -- not updated every timestep
     323        self.edge_timestep=num.zeros(len(self.edge_coordinates[:,0]))+1.0e+100
     324     
     325        # Do we allow the timestep to increase (not every time if local
     326        # extrapolation/flux updating is used)
     327        self.allow_timestep_increase=num.zeros(1).astype(int)+1
    303328
    304329    def _set_defaults(self):
     
    841866
    842867
    843 
     868    def set_local_extrapolation_and_flux_updating(self,nlevels=8):
     869        """
     870            Use local flux and extrapolation updating
     871
     872            nlevels == number of flux_update_frequency levels > 1
     873
     874                   For example, to allow flux updating every 1,2,4,8
     875                   timesteps, do:
     876
     877                    domain.set_local_extrapolation_and_flux_updating(nlevels=3)
     878
     879                   (since 2**3==8)
     880        """
     881
     882        self.max_flux_update_frequency=2**nlevels
     883
     884        if(self.max_flux_update_frequency is not 1):
     885            if self.timestepping_method is not 'euler':
     886                raise Exception, 'Local extrapolation and flux updating only supported with euler timestepping'
     887            if self.compute_fluxes_method is not 'DE':
     888                raise Exception, 'Local extrapolation and flux updating only supported for discontinuous flow algorithms'
    844889
    845890
     
    16681713            height = self.quantities['height']
    16691714
    1670             timestep = float(sys.maxint)
    1671 
    1672             # Keep track of number of calls to compute_fluxes_ext
    1673             # Note that in ANUGA, all sub-steps within an rk2/rk3 timestep have the same timestep
    1674             self.call+=1
     1715            timestep = self.evolve_max_timestep
     1716
    16751717            flux_timestep = compute_fluxes_ext(timestep,
    16761718                                               self.epsilon,
     
    17061748                                               Bed.centroid_values,
    17071749                                               height.centroid_values,
    1708                                                #Bed.vertex_values,
    17091750                                               self.edge_flux_type,
    17101751                                               self.riverwallData.riverwall_elevation,
     
    17131754                                               self.riverwallData.hydraulic_properties,
    17141755                                               self.edge_flux_work,
    1715                                                self.pressuregrad_work)
     1756                                               self.pressuregrad_work,
     1757                                               self.edge_timestep,
     1758                                               self.update_next_flux,
     1759                                               self.allow_timestep_increase)
    17161760
    17171761            self.flux_timestep = flux_timestep
     
    18211865                      int(self.extrapolate_velocity_second_order),
    18221866                      self.x_centroid_work,
    1823                       self.y_centroid_work)
     1867                      self.y_centroid_work,
     1868                      self.update_extrapolation)
    18241869        else:
    18251870            # Code for original method
     
    25802625        return message       
    25812626         
     2627    def compute_flux_update_frequency(self):
     2628        """
     2629            Update the 'flux_update_frequency' and 'update_extrapolate' variables
     2630            Used to control updating of fluxes / extrapolation for 'local-time-stepping'
     2631        """
     2632        from swDE1_domain_ext import compute_flux_update_frequency \
     2633                                  as compute_flux_update_frequency_ext
     2634
     2635        compute_flux_update_frequency_ext(
     2636                self.timestep,
     2637                self.neighbours,
     2638                self.neighbour_edges,
     2639                self.already_computed_flux,
     2640                self.edge_timestep,
     2641                self.flux_update_frequency,
     2642                self.update_extrapolation,
     2643                self.max_flux_update_frequency,
     2644                self.update_next_flux,
     2645                self.allow_timestep_increase)
     2646       
    25822647    def report_water_volume_statistics(self, verbose=True, returnStats=False):
    25832648        """
  • trunk/anuga_core/source/anuga/shallow_water/swDE1_domain_ext.c

    r9289 r9292  
    2828
    2929const double pi = 3.14159265358979;
     30
     31// Trick to compute n modulo 2 when d is a power of 2
     32unsigned int Mod_of_power_2(unsigned int n, unsigned int d)
     33{
     34  return ( n & (d-1) );
     35}
     36
    3037
    3138// Computational function for rotation
     
    111118                           double *edgeflux, double *max_speed,
    112119                           double *pressure_flux, double hc,
    113                            double hc_n, double speed_max_last)
     120                           double hc_n)
    114121{
    115122
     
    285292                           double *edgeflux, double *max_speed,
    286293                           double *pressure_flux, double hc,
    287                            double hc_n, double speed_max_last)
     294                           double hc_n)
    288295{
    289296
     
    441448  return 0;
    442449}
     450
     451////////////////////////////////////////////////////////////////
     452
     453int _compute_flux_update_frequency(int number_of_elements,
     454                                  long *neighbours, long *neighbour_edges,
     455                                  long *already_computed_flux,
     456                                  int max_flux_update_frequency, double *edge_timestep,
     457                                  double timestep, double notSoFast,
     458                                  long *flux_update_frequency,
     459                                  long *update_extrapolation,
     460                                  long *update_next_flux,
     461                                  long *allow_timestep_increase){
     462    // Compute the 'flux_update_frequency' for each edge.
     463    //
     464    // This determines how regularly we need
     465    // to update the flux computation (not every timestep)
     466    //
     467    // Allowed values are 1,2,4,8,... max_flux_update_frequency.
     468    //
     469    // For example, an edge with flux_update_frequency = 4 would
     470    // only have the flux updated every 4 timesteps
     471    //
     472    //
     473    // Local variables
     474    int k, i, k3, ki, m, n, nm, ii, j, ii2;
     475    long fuf;
     476    static int cyclic_number_of_steps=-1;
     477
     478    // QUICK EXIT
     479    if(max_flux_update_frequency==1){
     480        return 0;
     481    }
     482   
     483    // Count the steps
     484    cyclic_number_of_steps++;
     485    if(cyclic_number_of_steps==max_flux_update_frequency){
     486        // The flux was just updated in every cell
     487        cyclic_number_of_steps=0;
     488    }
     489
     490
     491    // PART 1: ONLY OCCURS FOLLOWING FLUX UPDATE
     492
     493    for ( k = 0; k < number_of_elements; k++){
     494        for ( i = 0; i < 3; i++){
     495            ki = k*3 + i;
     496            if((Mod_of_power_2(cyclic_number_of_steps, flux_update_frequency[ki])==0)){
     497                // The flux was just updated, along with the edge_timestep
     498                // So we better recompute the flux_update_frequency
     499                n=neighbours[ki];
     500                if(n>=0){
     501                    m = neighbour_edges[ki];
     502                    nm = n * 3 + m; // Linear index (triangle n, edge m)
     503                }
     504
     505                // Check if we have already done this edge
     506                // (Multiply already_computed_flux by -1 on the first update,
     507                // and again on the 2nd)
     508                if(already_computed_flux[ki] > 0 ){
     509                    // We have not fixed this flux value yet
     510                    already_computed_flux[ki] *=-1;
     511                    if(n>=0){
     512                        already_computed_flux[nm] *=-1;
     513                    }
     514                }else{
     515                    // We have fixed this flux value already
     516                    already_computed_flux[ki] *=-1;
     517                    if(n>=0){
     518                        already_computed_flux[nm] *=-1;
     519                    }
     520                    continue;
     521                }
     522
     523                // Basically int( edge_ki_timestep/timestep ) with upper limit + tweaks
     524                // notSoFast is ideally = 1.0, but in practice values < 1.0 can enhance stability
     525                // NOTE: edge_timestep[ki]/timestep can be very large [so int overflows].
     526                //       Do not pull the (int) inside the min term
     527                fuf = (int)min((edge_timestep[ki]/timestep)*notSoFast,max_flux_update_frequency*1.);
     528                // Account for neighbour
     529                if(n>=0){
     530                    fuf = min( (int)min(edge_timestep[nm]/timestep*notSoFast, max_flux_update_frequency*1.), fuf);
     531                }
     532
     533                // Deal with notSoFast<1.0
     534                if(fuf<1){
     535                    fuf=1;
     536                }
     537                // Deal with large fuf
     538                if(fuf>max_flux_update_frequency){
     539                    fuf = max_flux_update_frequency;
     540                }
     541                //// Deal with intermediate cases
     542                ii=2;
     543                while(ii<max_flux_update_frequency){
     544                    // Set it to 1,2,4, 8, ...
     545                    ii2=2*ii;
     546                    if((fuf>ii) && (fuf<ii2)){
     547                        fuf = ii;
     548                        continue;
     549                    }
     550                    ii=ii2;
     551                }
     552
     553                // Set the values
     554                flux_update_frequency[ki]=fuf;
     555                if(n>=0){
     556                    flux_update_frequency[nm]= fuf;
     557                }
     558               
     559            }
     560        }
     561    }
     562
     563    //// PART 2 -- occcurs every timestep
     564
     565    // At this point, both edges have the same flux_update_frequency.
     566    // Next, ensure that flux_update_frequency varies within a constant over each triangle
     567    // Experiences suggests this is numerically important
     568    // (But, it can result in the same edge having different flux_update_freq)
     569    for( k=0; k<number_of_elements; k++){
     570        k3=3*k;
     571        ii = 1*min(flux_update_frequency[k3],
     572                 min(flux_update_frequency[k3+1],
     573                     flux_update_frequency[k3+2]));
     574       
     575        flux_update_frequency[k3]=min(ii, flux_update_frequency[k3]);
     576        flux_update_frequency[k3+1]=min(ii, flux_update_frequency[k3+1]);
     577        flux_update_frequency[k3+2]=min(ii,flux_update_frequency[k3+2]);
     578           
     579    }
     580           
     581    // Now enforce the same flux_update_frequency on each edge
     582    // (Could have been broken above when we limited the variation on each triangle)
     583    // This seems to have nice behaviour. Notice how an edge
     584    // with a large flux_update_frequency, near an edge with a small flux_update_frequency,
     585    // will have its flux_update_frequency updated after a few timesteps (i.e. before max_flux_update_frequency timesteps)
     586    // OTOH, could this cause oscillations in flux_update_frequency?
     587    for( k = 0; k < number_of_elements; k++){
     588        update_extrapolation[k]=0;
     589        for( i = 0; i< 3; i++){
     590            ki=3*k+i;
     591            // Account for neighbour
     592            n=neighbours[ki];
     593            if(n>=0){
     594                m = neighbour_edges[ki];
     595                nm = n * 3 + m; // Linear index (triangle n, edge m)
     596                flux_update_frequency[ki]=min(flux_update_frequency[ki], flux_update_frequency[nm]);
     597            }
     598            // Do we need to update the extrapolation?
     599            // (We do if the next flux computation will actually compute a flux!)
     600            if(Mod_of_power_2((cyclic_number_of_steps+1),flux_update_frequency[ki])==0){
     601                update_next_flux[ki]=1;
     602                update_extrapolation[k]=1;
     603            }else{
     604                update_next_flux[ki]=0;
     605            }
     606        }
     607    }
     608
     609    // Check whether the timestep can be increased in the next compute_fluxes call
     610    if(cyclic_number_of_steps+1==max_flux_update_frequency){
     611        // All fluxes will be updated on the next timestep
     612        // We also allow the timestep to increase then
     613        allow_timestep_increase[0]=1;
     614    }else{
     615        allow_timestep_increase[0]=0;
     616    }
     617
     618    return 0;
     619}
     620
    443621
    444622double adjust_edgeflux_with_weir(double* edgeflux,
     
    574752        double* riverwall_hydraulic_properties,
    575753        double* edge_flux_work,
    576         double* pressuregrad_work) {
     754        double* pressuregrad_work,
     755        double* edge_timestep,
     756        long* update_next_flux,
     757        long* allow_timestep_increase) {
    577758    // Local variables
    578759    double max_speed, length, inv_area, zl, zr;
     
    582763    //
    583764    int k, i, m, n,j, ii;
    584     int ki, nm = 0, ki2,ki3, nm3; // Index shorthands
     765    int ki,k3, nm = 0, ki2,ki3, nm3; // Index shorthands
    585766    // Workspace (making them static actually made function slightly slower (Ole))
    586767    double ql[3], qr[3], edgeflux[3]; // Work array for summing up fluxes
    587768    double stage_edges[3];//Work array
    588     double bedslope_work, local_timestep;
     769    double bedslope_work;
     770    static double local_timestep;
    589771    int neighbours_wet[3];//Work array
    590     int RiverWall_count, substep_count;
     772    long RiverWall_count, substep_count;
    591773    double hle, hre, zc, zc_n, Qfactor, s1, s2, h1, h2;
    592     double stage_edge_lim, outgoing_mass_edges, bedtop, bedbot, pressure_flux, hc, hc_n, tmp, tmp2;
     774    double stage_edge_lim, outgoing_mass_edges, pressure_flux, hc, hc_n, tmp, tmp2;
    593775    double h_left_tmp, h_right_tmp;
    594776    static long call = 1; // Static local variable flagging already computed flux
    595     double speed_max_last, vol, smooth, local_speed, weir_height;
     777    double speed_max_last, vol, weir_height;
    596778
    597779    call++; // Flag 'id' of flux calculation for this timestep
     
    602784    memset((char*) xmom_explicit_update, 0, number_of_elements * sizeof (double));
    603785    memset((char*) ymom_explicit_update, 0, number_of_elements * sizeof (double));
    604     memset((char*) edge_flux_work, 0, 9*number_of_elements * sizeof (double));
    605     memset((char*) pressuregrad_work, 0, 3*number_of_elements * sizeof (double));
    606 
    607     local_timestep=timestep;
     786
     787
     788    // Counter for riverwall edges
    608789    RiverWall_count=0;
     790    // Which substep of the timestepping method are we on?
    609791    substep_count=(call-2)%timestep_fluxcalls;
    610 
     792   
     793    // Fluxes are not updated every timestep,
     794    // but all fluxes ARE updated when the following condition holds
     795    if(allow_timestep_increase[0]==1){
     796        // We can only increase the timestep if all fluxes are allowed to be updated
     797        // If this is not done the timestep can't increase (since local_timestep is static)
     798        local_timestep=1.0e+100;
     799    }
    611800
    612801    // For all triangles
    613802    for (k = 0; k < number_of_elements; k++) {
    614803        speed_max_last=0.0;
     804
    615805        // Loop through neighbours and compute edge flux for each
    616806        for (i = 0; i < 3; i++) {
     
    619809            ki3 = 3*ki;
    620810
    621             if (already_computed_flux[ki] == call) {
     811            if ((already_computed_flux[ki] == call) || (update_next_flux[ki]!=1)) {
    622812                // We've already computed the flux across this edge
    623813                // Check if it is a riverwall
     
    693883                    normals[ki2], normals[ki2 + 1],
    694884                    epsilon, z_half, limiting_threshold, g,
    695                     edgeflux, &max_speed, &pressure_flux, hc, hc_n,
    696                     speed_max_last);
     885                    edgeflux, &max_speed, &pressure_flux, hc, hc_n);
    697886
    698887            // Force weir discharge to match weir theory
     
    701890                // If the weir height is zero, avoid the weir computation entirely
    702891                if(weir_height>0.){
     892                    ////////////////////////////////////////////////////////////////////////////////////
     893                    // Use first-order h's for weir -- as the 'upstream/downstream' heads are
     894                    //  measured away from the weir itself
     895                    h_left_tmp= max(stage_centroid_values[k]-z_half,0.);
     896                    if(n>=0){
     897                        h_right_tmp= max(stage_centroid_values[n]-z_half,0.);
     898                    }else{
     899                        h_right_tmp= max(hc_n+zr-z_half,0.);
     900                    }
     901
     902                    //////////////////////////////////////////////////////////////////////////////////
    703903                    // Get Qfactor index - multiply the idealised weir discharge by this constant factor
    704904                    ii=riverwall_rowIndex[RiverWall_count-1]*ncol_riverwall_hydraulic_properties;
     
    717917                    h2=riverwall_hydraulic_properties[ii];
    718918                   
    719                     // Use first-order h's for weir -- as the 'upstream/downstream' heads are
    720                     //  measured away from the weir itself
    721                     h_left_tmp= max(stage_centroid_values[k]-z_half,0.);
    722                     if(n>=0){
    723                         h_right_tmp= max(stage_centroid_values[n]-z_half,0.);
    724                     }else{
    725                         h_right_tmp= max(hc_n+zr-z_half,0.);
    726                     }
    727 
     919                    // Weir flux adjustment
    728920                    adjust_edgeflux_with_weir(edgeflux, h_left_tmp, h_right_tmp, g,
    729921                                              weir_height, Qfactor,
     
    782974
    783975            // Update timestep based on edge i and possibly neighbour n
    784             // NOTE: We should only change the timestep between rk2 or rk3
    785             // steps, NOT within them (since a constant timestep is used within
    786             // each rk2/rk3 sub-step)
    787             if ((tri_full_flag[k] == 1) & (substep_count==0)) {
    788 
    789                 speed_max_last=max(speed_max_last, max_speed);
    790 
    791                 if (max_speed > epsilon) {
    792                     // Apply CFL condition for triangles joining this edge (triangle k and triangle n)
    793 
    794                     // CFL for triangle k
    795                     local_timestep = min(local_timestep, radii[k] / max_speed);
    796 
    797                     if (n >= 0) {
    798                         // Apply CFL condition for neigbour n (which is on the ith edge of triangle k)
    799                         local_timestep = min(local_timestep, radii[n] / max_speed);
     976            // NOTE: We should only change the timestep on the 'first substep'
     977            //  of the timestepping method [substep_count==0]
     978            if(substep_count==0){
     979
     980                // Compute the 'edge-timesteps' (useful for setting flux_update_frequency)
     981                edge_timestep[ki] = radii[k] / max(max_speed, epsilon);
     982                if (n >= 0) {
     983                    edge_timestep[nm] = radii[n] / max(max_speed, epsilon);
     984                }
     985
     986                // Update the timestep
     987                if ((tri_full_flag[k] == 1)) {
     988
     989                    speed_max_last=max(speed_max_last, max_speed);
     990
     991                    if (max_speed > epsilon) {
     992                        // Apply CFL condition for triangles joining this edge (triangle k and triangle n)
     993
     994                        // CFL for triangle k
     995                        local_timestep = min(local_timestep, edge_timestep[ki]);
     996
     997                        if (n >= 0) {
     998                            // Apply CFL condition for neigbour n (which is on the ith edge of triangle k)
     999                            local_timestep = min(local_timestep, edge_timestep[nm]);
     1000                        }
    8001001                    }
    801 
    8021002                }
    8031003            }
    804        
     1004
    8051005        } // End edge i (and neighbour n)
    8061006        // Keep track of maximal speeds
     
    8091009
    8101010    } // End triangle k
    811  
     1011
    8121012    //// Limit edgefluxes, for mass conservation near wet/dry cells
    8131013    //// This doesn't seem to be needed anymore
     
    8671067    for(k=0; k<number_of_elements; k++){
    8681068        hc = max(stage_centroid_values[k] - bed_centroid_values[k],0.);
    869         stage_explicit_update[k]=0.;
    870         xmom_explicit_update[k]=0.;
    871         ymom_explicit_update[k]=0.;
    8721069
    8731070        for(i=0;i<3;i++){
     1071            // FIXME: Make use of neighbours to efficiently set things
    8741072            ki=3*k+i;   
    8751073            ki2=ki*2;
     
    9061104            //    ymom_explicit_update[k] *= 0.;
    9071105            //}
     1106           
    9081107
    9091108        } // end edge i
     
    9201119    // Ensure we only update the timestep on the first call within each rk2/rk3 step
    9211120    if(substep_count==0) timestep=local_timestep;
    922             
     1121         
    9231122    return timestep;
    9241123}
     
    10751274                                 int extrapolate_velocity_second_order,
    10761275                                 double* x_centroid_work,
    1077                                  double* y_centroid_work) {
     1276                                 double* y_centroid_work,
     1277                                 long* update_extrapolation) {
    10781278                 
    10791279  // Local variables
     
    11221322  // some situations
    11231323  for (k=0; k<number_of_elements;k++){
    1124 
     1324     
    11251325      k3=k*3;
    11261326      k0 = surrogate_neighbours[k3];
     
    11451345  for (k = 0; k < number_of_elements; k++)
    11461346  {
     1347
     1348    // Don't update the extrapolation if the flux will not be computed on the
     1349    // next timestep
     1350    if(update_extrapolation[k]==0){
     1351       continue;
     1352    }
     1353
    11471354
    11481355    // Useful indices
     
    12231430      k2 = surrogate_neighbours[k3 + 2];
    12241431
     1432
    12251433      // Get the auxiliary triangle's vertex coordinates
    12261434      // (really the centroids of neighbouring triangles)
     
    12641472          height_edge_values[k3+2] = dk;
    12651473         
    1266           //stage_edge_values[k3]   = elevation_centroid_values[k]+dk;
    1267           //stage_edge_values[k3+1] = elevation_centroid_values[k]+dk;
    1268           //stage_edge_values[k3+2] = elevation_centroid_values[k]+dk;
    1269           //stage_edge_values[k3] = elevation_edge_values[k3]+dk;
    1270           //stage_edge_values[k3+1] = elevation_edge_values[k3+1]+dk;
    1271           //stage_edge_values[k3+2] = elevation_edge_values[k3+2]+dk;
    1272 
    1273           //xmom_centroid_values[k]=0.;
    1274           //ymom_centroid_values[k]=0.;
    1275           //x_centroid_work[k] = 0.;
    1276           //y_centroid_work[k] = 0.;
    1277 
    12781474          xmom_edge_values[k3]    = xmom_centroid_values[k];
    12791475          xmom_edge_values[k3+1]  = xmom_centroid_values[k];
     
    17111907  // Compute vertex values of quantities
    17121908  for (k=0; k<number_of_elements; k++){
     1909      if(extrapolate_velocity_second_order==1){
     1910          //Convert velocity back to momenta at centroids
     1911          xmom_centroid_values[k] = x_centroid_work[k];
     1912          ymom_centroid_values[k] = y_centroid_work[k];
     1913      }
     1914     
     1915      // Don't proceed if we didn't update the edge/vertex values
     1916      if(update_extrapolation[k]==0){
     1917         continue;
     1918      }
     1919
    17131920      k3=3*k;
    1714 
     1921     
    17151922      // Compute stage vertex values
    17161923      stage_vertex_values[k3] = stage_edge_values[k3+1] + stage_edge_values[k3+2] -stage_edge_values[k3] ;
     
    17251932      // If needed, convert from velocity to momenta
    17261933      if(extrapolate_velocity_second_order==1){
    1727           //Convert velocity back to momenta at centroids
    1728           xmom_centroid_values[k] = x_centroid_work[k];
    1729           ymom_centroid_values[k] = y_centroid_work[k];
    1730      
    17311934          // Re-compute momenta at edges
    17321935          for (i=0; i<3; i++){
     
    18472050    *riverwall_hydraulic_properties,
    18482051    *edge_flux_work,
    1849     *pressuregrad_work;
     2052    *pressuregrad_work,
     2053    *edge_timestep,
     2054    *update_next_flux,
     2055    *allow_timestep_increase;
    18502056   
    18512057  double timestep, epsilon, H0, g;
    18522058  int optimise_dry_cells, timestep_fluxcalls, ncol_riverwall_hydraulic_properties;
     2059 
    18532060   
    18542061  // Convert Python arguments to C
    1855   if (!PyArg_ParseTuple(args, "ddddOOOOOOOOOOOOOOOOOOOOOOiiOOOOOOOOiOOO",
     2062  if (!PyArg_ParseTuple(args, "ddddOOOOOOOOOOOOOOOOOOOOOOiiOOOOOOOOiOOOOOO",
    18562063            &timestep,
    18572064            &epsilon,
     
    18922099            &riverwall_hydraulic_properties,
    18932100            &edge_flux_work,
    1894             &pressuregrad_work
     2101            &pressuregrad_work,
     2102            &edge_timestep,
     2103            &update_next_flux,
     2104            &allow_timestep_increase
    18952105            )) {
    18962106    report_python_error(AT, "could not parse input arguments");
     
    19322142  CHECK_C_CONTIG(edge_flux_work);
    19332143  CHECK_C_CONTIG(pressuregrad_work);
     2144  CHECK_C_CONTIG(edge_timestep);
     2145  CHECK_C_CONTIG(update_next_flux);
     2146  CHECK_C_CONTIG(allow_timestep_increase);
    19342147
    19352148  int number_of_elements = stage_edge_values -> dimensions[0];
     
    19782191                     (double*) riverwall_hydraulic_properties ->data,
    19792192                     (double*) edge_flux_work-> data,
    1980                      (double*) pressuregrad_work->data);
     2193                     (double*) pressuregrad_work->data,
     2194                     (double*) edge_timestep->data,
     2195                     (long*) update_next_flux->data,
     2196                     (long*) allow_timestep_increase->data
     2197                     );
    19812198  // Return updated flux timestep
    19822199  return Py_BuildValue("d", timestep);
     
    20292246             &pressure_flux,
    20302247                         ((double*) normal -> data)[0],
    2031                          ((double*) normal -> data)[1],
    20322248                         ((double*) normal -> data)[1]
    20332249             );
     
    21072323}
    21082324
     2325PyObject *compute_flux_update_frequency(PyObject *self, PyObject *args) {
     2326  /*Compute how often we should update fluxes and extrapolations (not every timestep)
     2327
     2328    python_call
     2329        compute_flux_update_frequency_ext(
     2330                self.timestep,
     2331                self.neighbours,
     2332                self.neighbour_edges,
     2333                self.already_computed_flux,
     2334                self.edge_timestep,
     2335                self.flux_update_frequency,
     2336                self.update_extrapolation,
     2337                self.max_flux_update_frequency,
     2338                self.update_next_flux)
     2339
     2340
     2341
     2342  */
     2343
     2344
     2345  PyArrayObject *neighbours, *neighbour_edges,
     2346    *already_computed_flux, //Tracks whether the flux across an edge has already been computed
     2347    *edge_timestep,
     2348    *flux_update_frequency,
     2349    *update_extrapolation,
     2350    *update_next_flux,
     2351    *allow_timestep_increase;
     2352   
     2353  double timestep;
     2354  int max_flux_update_frequency;
     2355 
     2356   
     2357  // Convert Python arguments to C
     2358  if (!PyArg_ParseTuple(args, "dOOOOOOiOO",
     2359            &timestep,
     2360            &neighbours,
     2361            &neighbour_edges,
     2362            &already_computed_flux,
     2363            &edge_timestep,
     2364            &flux_update_frequency,
     2365            &update_extrapolation,
     2366            &max_flux_update_frequency,
     2367            &update_next_flux,
     2368            &allow_timestep_increase
     2369            )) {
     2370    report_python_error(AT, "could not parse input arguments");
     2371    return NULL;
     2372  }
     2373
     2374  // check that numpy array objects arrays are C contiguous memory
     2375  CHECK_C_CONTIG(neighbours);
     2376  CHECK_C_CONTIG(neighbour_edges);
     2377  CHECK_C_CONTIG(already_computed_flux);
     2378  CHECK_C_CONTIG(edge_timestep);
     2379  CHECK_C_CONTIG(flux_update_frequency);
     2380  CHECK_C_CONTIG(update_extrapolation);
     2381  CHECK_C_CONTIG(update_next_flux);
     2382  CHECK_C_CONTIG(allow_timestep_increase);
     2383
     2384  int number_of_elements = update_extrapolation -> dimensions[0];
     2385  // flux_update_frequency determined by rounding edge_timestep/timestep*notSoFast
     2386  // So notSoFast<1 might increase the number of flux calls a cell has to do, but
     2387  // can be useful for increasing numerical stability
     2388  double notSoFast=1.00;
     2389
     2390  // Call underlying flux computation routine and update
     2391  // the explicit update arrays
     2392  _compute_flux_update_frequency(number_of_elements,
     2393                                 (long*) neighbours->data,
     2394                                 (long*) neighbour_edges->data,
     2395                                 (long*) already_computed_flux->data,
     2396                                 max_flux_update_frequency,
     2397                                 (double*) edge_timestep->data,
     2398                                 timestep,
     2399                                 notSoFast,
     2400                                 (long*) flux_update_frequency->data,
     2401                                 (long*) update_extrapolation->data,
     2402                                 (long*) update_next_flux->data,
     2403                                 (long*) allow_timestep_increase->data
     2404                                 );
     2405  // Return
     2406  return Py_BuildValue("");
     2407}
     2408
    21092409
    21102410PyObject *extrapolate_second_order_edge_sw(PyObject *self, PyObject *args) {
     
    21512451    *height_vertex_values,
    21522452    *x_centroid_work,
    2153     *y_centroid_work;
     2453    *y_centroid_work,
     2454    *update_extrapolation;
    21542455 
    21552456  PyObject *domain;
     
    21612462 
    21622463  // Convert Python arguments to C
    2163   if (!PyArg_ParseTuple(args, "OOOOOOOOOOOOOOOOOOOOOiiOO",
     2464  if (!PyArg_ParseTuple(args, "OOOOOOOOOOOOOOOOOOOOOiiOOO",
    21642465            &domain,
    21652466            &surrogate_neighbours,
     
    21862487            &extrapolate_velocity_second_order,
    21872488            &x_centroid_work,
    2188             &y_centroid_work)) {         
     2489            &y_centroid_work,
     2490            &update_extrapolation)) {         
    21892491
    21902492    report_python_error(AT, "could not parse input arguments");
     
    22152517  CHECK_C_CONTIG(x_centroid_work);
    22162518  CHECK_C_CONTIG(y_centroid_work);
     2519  CHECK_C_CONTIG(update_extrapolation);
    22172520 
    22182521  // Get the safety factor beta_w, set in the config.py file.
     
    22672570                   extrapolate_velocity_second_order,
    22682571                   (double*) x_centroid_work -> data,
    2269                    (double*) y_centroid_work -> data);
     2572                   (double*) y_centroid_work -> data,
     2573                   (long*) update_extrapolation -> data);
    22702574
    22712575  if (e == -1) {
     
    23462650  {"flux_function_central", flux_function_central, METH_VARARGS, "Print out"}, 
    23472651  {"extrapolate_second_order_edge_sw", extrapolate_second_order_edge_sw, METH_VARARGS, "Print out"},
     2652  {"compute_flux_update_frequency", compute_flux_update_frequency, METH_VARARGS, "Print out"},
    23482653  {"protect",          protect, METH_VARARGS | METH_KEYWORDS, "Print out"},
    23492654  {NULL, NULL, 0, NULL}
  • trunk/anuga_work/development/gareth/tests/dam_break/dam_break.py

    r9007 r9292  
    1414from numpy import zeros, float
    1515from time import localtime, strftime, gmtime
    16 from bal_and import *
     16#from bal_and import *
    1717#from anuga_tsunami import *
    1818
     
    4242points, vertices, boundary = anuga.rectangular_cross(int(L/dx), int(W/dy), L, W, (0.0, -W/2))
    4343
    44 #domain = anuga.Domain(points, vertices, boundary)
    45 domain = Domain(points, vertices, boundary)
     44domain = anuga.Domain(points, vertices, boundary)
     45#domain = Domain(points, vertices, boundary)
    4646
    4747domain.set_name(output_file)               
     
    5656print domain.get_timestepping_method()
    5757
     58domain.set_flow_algorithm('DE0')
     59#domain.set_local_extrapolation_and_flux_updating(nlevels=8)
    5860#domain.use_edge_limiter = True
    5961#domain.use_edge_limiter = False
  • trunk/anuga_work/development/gareth/tests/dam_break/plotme.py

    r9038 r9292  
    44"""
    55from anuga.utilities import plot_utils as util
    6 from bal_and import plot_utils as util2
    76from matplotlib import pyplot as pyplot
    87
    9 p_st = util.get_output('dam_break_20120305_124724/dam_break.sww')
     8p_st = util.get_output('dam_break_20140811_130209/dam_break.sww')
    109p2_st=util.get_centroids(p_st)
    1110
    1211
    13 p_dev = util2.get_output('dam_break_20131204_145613/dam_break.sww', 0.001)
    14 p2_dev=util2.get_centroids(p_dev, velocity_extrapolation=True)
     12p_dev = util.get_output('dam_break_20140811_130049/dam_break.sww', 0.001)
     13p2_dev=util.get_centroids(p_dev, velocity_extrapolation=True)
    1514
    1615pyplot.clf()
  • trunk/anuga_work/development/gareth/tests/runup_sinusoid/runup_sinusoid.py

    r9260 r9292  
    2020domain.set_name('runup_sinusoid_v2')                         # Output to file runup.sww
    2121#domain.set_store_centroids(True)
    22 domain.set_flow_algorithm('DE1')
     22domain.set_flow_algorithm('DE0')
    2323domain.set_quantities_to_be_stored({'stage': 2, 'xmomentum': 2,
    2424         'ymomentum': 2, 'elevation': 2})
     
    4242bumpiness=50. # Higher = shorter wavelength oscillations in topography
    4343tstep=0.2
    44 lasttime=90.
     44lasttime=30.
    4545
    4646#domain.minimum_allowed_height=domain.minimum_allowed_height*scale_me # Seems needed to make the algorithms behave
     
    110110    print 'Their difference is:', vol-flux_integral
    111111    #print 'Volume less flux int', sum(dd_raw*domain.areas) - domain.boundary_flux_integral
    112    
     112    print 'Update_next_flux range:'
     113    print domain.update_extrapolation.min(), domain.update_extrapolation.max()
     114    print 'Flux_update_frequency range:'
     115    print domain.flux_update_frequency.min(), domain.flux_update_frequency.max()
    113116
    114117vel_final_inds=(vv>1.0e-01).nonzero()
Note: See TracChangeset for help on using the changeset viewer.