/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/sedflux/run_bedload.c

Go to the documentation of this file.
00001 //---
00002 //
00003 // This file is part of sedflux.
00004 //
00005 // sedflux is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // sedflux is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with sedflux; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //
00019 //---
00020 
00021 #define SED_BEDLOAD_PROC_NAME "bedload dumping"
00022 #define EH_LOG_DOMAIN SED_BEDLOAD_PROC_NAME
00023 
00024 #include <stdio.h>
00025 #include <limits.h>
00026 #include <string.h>
00027 #include <math.h>
00028 #include <utils/utils.h>
00029 #include <sed/sed_sedflux.h>
00030 #include "my_processes.h"
00031 #include "sedflux.h"
00032 
00033 #define BED_LOAD_SPREADING_ANGLE (14.*S_RADS_PER_DEGREE)
00034 
00035 typedef struct
00036 {
00037    double x_0;
00038    double y_0;
00039    double dx;
00040    double dy;
00041    double r_max;
00042    double min_angle;
00043    double max_angle;
00044 }
00045 Bed_load_data;
00046 
00047 double   deposit_in_ocean  ( Sed_cube p , Sed_riv r , double vol , Eh_dbl_grid fraction_grid );
00048 double   deposit_in_river  ( Sed_cube p , Sed_riv r , double vol );
00049 gboolean bed_load_2d_domain( double x , double y , Bed_load_data *user_data );
00050 gboolean bed_load_1d_domain( double x , double y , Bed_load_data *user_data );
00051 
00052 Sed_process_info
00053 run_bedload( Sed_process p , Sed_cube prof )
00054 {
00055    Bedload_dump_t*  data       = sed_process_user_data(p);
00056    Sed_process_info info       = SED_EMPTY_INFO;
00057    Sed_riv          this_river = sed_cube_river_by_name( prof , data->river_name );
00058 
00059    if ( this_river )
00060    { /* If there is a river by this name. */
00061       Eh_pt_2*      river_mouth;
00062 
00063       /* The river mouth's position. */
00064       if ( sed_mode_is_3d() )
00065          river_mouth = sed_cube_river_mouth_position( prof , this_river );
00066       else
00067       {
00068          river_mouth    = eh_new( Eh_pt_2 , 1 );
00069          river_mouth->x = sed_cube_col_x(prof,0);
00070          river_mouth->y = sed_cube_col_y(prof,sed_cube_river_mouth_1d( prof ) );
00071       }
00072 
00073       /* If there is a river mouth. */
00074       if ( river_mouth )
00075       {
00076 //         Sed_cell    bed_load_cell = sed_cell_new_env( );
00077          gint        bed_load_n_x  = data->bed_load_dump_length / sed_cube_x_res( prof ) + 1;
00078          gint        bed_load_n_y  = data->bed_load_dump_length / sed_cube_y_res( prof ) + 1;
00079          double      mass_ocean    = 0;
00080          double      mass_delta    = 0;
00081          Eh_dbl_grid fraction_grid;
00082 
00083          eh_upper_bound( bed_load_n_x , sed_cube_n_x(prof) );
00084          eh_upper_bound( bed_load_n_y , sed_cube_n_y(prof) );
00085 
00086          //---
00087          // Create a grid to hold the bed load.  The river mouth will be at i=0,
00088          // j=0, and will point in the j-direction.
00089          //---
00090          fraction_grid = eh_grid_new( double , 2.*bed_load_n_x , 2.*bed_load_n_y );
00091 
00092          if ( fraction_grid )
00093          { /* Determine what fraction of each cell is filled with sediment. */
00094             Bed_load_data bed_load_data;
00095             double bed_load_spreading_angle = BED_LOAD_SPREADING_ANGLE;
00096 
00097             fraction_grid = eh_grid_reindex( fraction_grid , -bed_load_n_x , -bed_load_n_y );
00098 
00099             river_mouth->x /= sed_cube_x_res( prof );
00100             river_mouth->y /= sed_cube_y_res( prof );
00101             river_mouth->x -= sed_river_mouth(this_river).i;
00102             river_mouth->y -= sed_river_mouth(this_river).j;
00103 
00104             bed_load_data.x_0       = river_mouth->x;
00105             bed_load_data.y_0       = river_mouth->y;
00106             bed_load_data.dx        = sed_cube_x_res( prof );
00107             bed_load_data.dy        = sed_cube_y_res( prof );
00108             bed_load_data.r_max     = data->bed_load_dump_length;
00109             bed_load_data.min_angle = sed_river_angle( this_river )
00110                                     - bed_load_spreading_angle;
00111             bed_load_data.max_angle = sed_river_angle( this_river )
00112                                     + bed_load_spreading_angle;
00113 
00114             //---
00115             // Add the bed load into its grid.  The bed load is distributed evenly over
00116             // an arc.  The user defines the radius and interior angle of the arc.
00117             //---
00118             if ( sed_mode_is_3d() )
00119                eh_dbl_grid_populate( fraction_grid                      ,
00120                                      (Populate_func)&bed_load_2d_domain ,
00121                                      &bed_load_data );
00122             else
00123                eh_dbl_grid_populate( fraction_grid                      ,
00124                                      (Populate_func)&bed_load_1d_domain ,
00125                                      &bed_load_data );
00126          }
00127 
00128          { /* Set non-zero elements of fraction to 1. */
00129             gint i, j;
00130             const gint low_x  = eh_grid_low_x(fraction_grid);
00131             const gint low_y  = eh_grid_low_y(fraction_grid);
00132             const gint high_x = low_x + eh_grid_n_x(fraction_grid);
00133             const gint high_y = low_y + eh_grid_n_y(fraction_grid);
00134 
00135             /* Note: this should probably be changed so that some elements are only fractionally filled. */
00136             for ( i=low_x ; i<high_x ; i++ )
00137                for ( j=low_y ; j<high_y ; j++ )
00138                {
00139                   if ( eh_dbl_grid_val(fraction_grid,i,j) > 0 )
00140                      eh_dbl_grid_set_val( fraction_grid , i , j , 1. );
00141                }
00142          }
00143 
00144          { /* Set the bedload cell's facies, age, and type */
00145 /*
00146             bed_load_cell = sed_cell_new_bedload( NULL , 0 );
00147 
00148             sed_cell_set_facies  ( bed_load_cell , S_FACIES_BEDLOAD                    );
00149             sed_cell_set_age     ( bed_load_cell ,   sed_cube_age_in_years( prof )
00150                                                    - sed_cube_time_step( prof )    );
00151 */
00152          }
00153 
00154 /*
00155          {
00156             double area      = eh_dbl_grid_sum( fraction_grid )
00157                              * sed_cube_x_res( prof )
00158                              * sed_cube_y_res( prof );
00159             double vol_total = (sed_river_bedload(this_river)*S_SECONDS_PER_DAY)
00160                              * sed_cube_time_step_in_days( prof )
00161                              / sed_cell_density_0( bed_load_cell );
00162             double vol_delta = vol_total * data->f_retained;
00163 
00164             thickness = (vol_tot-vol_delta) / area;
00165 
00166             if ( sed_mode_is_2d() && data->bed_load_dump_length > sed_cube_x_res(prof) )
00167                thickness *= sed_cube_x_res(prof)/data->bed_load_dump_length;
00168 
00169          }
00170 */
00171 
00172          { /* Deposit the sediment landward and seaward of the river mouth. */
00173             double vol_total = (sed_river_bedload(this_river)*S_SECONDS_PER_DAY)
00174                              * sed_cube_time_step_in_days( prof )
00175                              / sed_type_rho_sat( sed_sediment_type( NULL , 0 ) );
00176 /* / sed_cell_density_0( bed_load_cell ); */
00177             double vol_delta = vol_total*data->f_retained;
00178             double vol_ocean = vol_total*(1.-data->f_retained);
00179 
00180             if ( vol_ocean>0 ) mass_ocean = deposit_in_ocean( prof , this_river , vol_ocean , fraction_grid );
00181             if ( vol_delta>0 ) mass_delta = deposit_in_river( prof , this_river , vol_delta );
00182          }
00183 
00184          { /* Mass balance */
00185             double input_mass = sed_river_bedload( this_river )
00186                               * sed_cube_time_step_in_seconds( prof );
00187             double add_mass   = mass_ocean + mass_delta;
00188             //double add_mass   = area*thickness*sed_type_rho_sat( sed_sediment_type( NULL , 0 ) );
00189             //double add_mass   = area*thickness*sed_cell_density_0( bed_load_cell );
00190 
00191             info.mass_added = sed_river_bedload( this_river )
00192                             * sed_cube_time_step_in_seconds( prof );
00193             info.mass_lost  = 0.;
00194 
00195             //eh_message( "bedload dump thickness (m): %f"       , thickness  );
00196             eh_message( "bedload input (kg): %g"               , input_mass   );
00197             eh_message( "bedload added (kg): %g"               , add_mass     );
00198             eh_message( "mass added to delta plain (kg): %g"   , mass_delta   );
00199             eh_message( "mass added to ocean (kg): %g"         , mass_ocean   );
00200          }
00201 
00202          eh_grid_destroy ( fraction_grid , TRUE );
00203 //         sed_cell_destroy( bed_load_cell );
00204       }
00205 
00206       eh_free( river_mouth );
00207    }
00208 
00209    return info;
00210 }
00211 
00212 #define BEDLOAD_KEY_DUMP_LEN   "distance to dump bedload"
00213 #define BEDLOAD_KEY_RATIO      "ratio of flood plain to bedload rate"
00214 #define BEDLOAD_KEY_RETAINED   "fraction of bedload retained in the delta plain"
00215 #define BEDLOAD_KEY_RIVER_NAME "river name"
00216 
00217 static gchar* bedload_req_labels[] =
00218 {
00219    BEDLOAD_KEY_DUMP_LEN   ,
00220    BEDLOAD_KEY_RATIO      ,
00221    BEDLOAD_KEY_RETAINED   ,
00222    BEDLOAD_KEY_RIVER_NAME ,
00223    NULL
00224 };
00225 
00226 gboolean
00227 init_bedload( Sed_process p , Eh_symbol_table t , GError** error )
00228 {
00229    Bedload_dump_t* data    = sed_process_new_user_data( p , Bedload_dump_t );
00230    GError*         tmp_err = NULL;
00231    gboolean        is_ok   = TRUE;
00232    gchar**         err_s   = NULL;
00233 
00234    if ( eh_symbol_table_require_labels( t , bedload_req_labels , &tmp_err ) )
00235    {
00236       data->bed_load_dump_length = eh_symbol_table_dbl_value( t , BEDLOAD_KEY_DUMP_LEN   );
00237       data->bedload_ratio        = eh_symbol_table_dbl_value( t , BEDLOAD_KEY_RATIO      );
00238       data->f_retained           = eh_symbol_table_dbl_value( t , BEDLOAD_KEY_RETAINED   );
00239       data->river_name           = eh_symbol_table_value    ( t , BEDLOAD_KEY_RIVER_NAME );
00240 
00241       eh_check_to_s( data->bed_load_dump_length>0 , "Dump length positive"            , &err_s );
00242       eh_check_to_s( data->bedload_ratio>=0       , "Bedload ratio positive"          , &err_s );
00243       eh_check_to_s( data->f_retained>=0          , "Bedload retention positive"      , &err_s );
00244       eh_check_to_s( data->f_retained<=1.         , "Bedload retention less than one" , &err_s );
00245 
00246       if ( !tmp_err && err_s )
00247          eh_set_error_strv( &tmp_err , SEDFLUX_ERROR , SEDFLUX_ERROR_BAD_PARAM , err_s );
00248    }
00249 
00250    if ( tmp_err )
00251    {
00252       g_propagate_error( error , tmp_err );
00253       is_ok = FALSE;
00254    }
00255 
00256    return is_ok;
00257 }
00258 
00259 gboolean
00260 destroy_bedload( Sed_process p )
00261 {
00262    if ( p )
00263    {
00264       Bedload_dump_t* data = sed_process_user_data( p );
00265 
00266       if ( data )
00267       {
00268          eh_free( data->river_name );
00269          eh_free( data             );
00270       }
00271    }
00272 
00273    return TRUE;
00274 }
00275 
00276 double
00277 deposit_in_ocean( Sed_cube p , Sed_riv r , double vol , Eh_dbl_grid fraction_grid )
00278 {
00279    double dep_vol = 0.;
00280 
00281    eh_require( p             );
00282    eh_require( r             );
00283    eh_require( fraction_grid );
00284    eh_require( vol>=0        );
00285 
00286    if ( vol>0 )
00287    { /* If there is sediment to deposit */
00288       Sed_cell_grid in_suspension = sed_cube_in_suspension( p , r );
00289 
00290       if ( in_suspension )
00291       {
00292          const double area = eh_dbl_grid_sum( fraction_grid )
00293                            * sed_cube_x_res( p )
00294                            * sed_cube_y_res( p );
00295 
00296          if ( area>0 )
00297          {  /* Add the bed load to the cube's in-suspension grid to be deposited later. */
00298             Sed_cell c     = sed_cell_new_bedload( NULL , area/vol );
00299 
00300          { /* The thickness of sediment to be deposited. */
00301 /*
00302             if ( sed_mode_is_2d() && data->bed_load_dump_length > sed_cube_x_res(p) )
00303                thickness *= sed_cube_x_res(p)/data->bed_load_dump_length;
00304 */
00305          }
00306 
00307          {
00308             gint   i, j;
00309             const gint   low_x  = eh_grid_low_x(fraction_grid);
00310             const gint   low_y  = eh_grid_low_y(fraction_grid);
00311             const gint   high_x = low_x + eh_grid_n_x(fraction_grid);
00312             const gint   high_y = low_y + eh_grid_n_y(fraction_grid);
00313             const double t      = area / vol;
00314 
00315             for ( i=low_x ; i<high_x ; i++ )
00316                for ( j=low_y ; j<high_y ; j++ )
00317                {
00318                   if( eh_dbl_grid_val(fraction_grid,i,j) > 0 )
00319                   {
00320                      sed_cell_resize( c , t*eh_dbl_grid_val(fraction_grid,i,j) );
00321                      sed_cell_add   ( sed_cell_grid_val(in_suspension,i,j) , c );
00322                   }
00323                }
00324 
00325             sed_cell_destroy( c );
00326          }
00327          }
00328       }
00329       else
00330          eh_require_not_reached();
00331    }
00332 
00333    return dep_vol;
00334 }
00335 
00344 double
00345 deposit_in_river( Sed_cube p , Sed_riv r , double vol )
00346 {
00347    double vol_dep = 0;
00348 
00349    eh_require( p      );
00350    eh_require( r      );
00351    eh_require( vol>=0 );
00352 
00353    if ( p && r && vol>0 )
00354    {
00355       gssize* river_path = sed_cube_river_path_id( p , r , TRUE );
00356 
00357       eh_require( river_path );
00358 
00359       if ( river_path )
00360       { /* If there is a river path. */
00361          Sed_cube  river_profile = sed_cube_cols( p , river_path );
00362          Sed_hydro river_data    = sed_river_hydro( r );
00363          gint      i_river       = sed_cube_river_mouth_1d( river_profile ) - 1;
00364 
00365          eh_require( river_data    );
00366          eh_require( river_profile );
00367 
00368          if ( i_river>0 )
00369          {  /* If the river has some length. */
00370 
00371             if ( sed_mode_is_3d() )
00372             {
00373                sed_cube_set_x_res( river_profile , sed_river_width(r) );
00374                sed_cube_set_y_res( river_profile , .5*(sed_cube_x_res(p)+sed_cube_y_res(p)) );
00375             }
00376             else
00377             {
00378                sed_cube_set_x_res( river_profile , sed_cube_x_res(p) );
00379                sed_cube_set_y_res( river_profile , sed_cube_y_res(p) );
00380             }
00381    
00382             { /* Deposit the sediment. */
00383                gint   i;
00384                double area    = sed_cube_x_res( river_profile )
00385                               * sed_cube_y_res( river_profile )
00386                               * i_river;
00387                Sed_cell c     = sed_cell_new_bedload( NULL , area/vol );
00388 
00389                for ( i=0 ; i<i_river ; i++ )
00390                   sed_column_add_cell( sed_cube_col(river_profile,i) , c );
00391                vol_dep = vol;
00392 
00393                sed_cell_destroy( c );
00394             }
00395 
00396          }
00397 
00398          eh_free          ( river_path );
00399          sed_cube_free    ( river_profile , FALSE );
00400       }
00401    }
00402 
00403    return vol_dep;
00404 }
00405 
00406 /*
00407 Sed_cell
00408 sed_cube_add_cell( Sed_cube c , Sed_cell c )
00409 {
00410    Sed_cell eroded_sed = sed_cell_new_env();
00411 
00412    eh_require( river_profile );
00413 
00414    if (    river_profile 
00415         && sed_cube_river_mouth_1d( river_profile) > 0 )
00416    {
00417       gint     i_river = sed_cube_river_mouth_1d( river_profile ) - 1;
00418 
00419       Sed_cell eroded  = sed_cell_new_env( );
00420       double   dx      = sed_cube_y_res( river_profile );
00421       double   width   = sed_cube_x_res( river_profile );
00422       Erosion_lin_st linear_const = erosion_get_linear_constants( slope );
00423       gint i;
00424       double x;
00425       double height;
00426       double river_height;
00427       double erode_height;
00428          
00429       river_height = sed_cube_top_height( river_profile , 0 , i_river );
00430       
00431       for ( i=i_river-1 ; i>=0 ; i-- )
00432       {
00433          x      = (i-i_river)*dx;
00434          height = erosion_get_linear_height( x , linear_const ) + river_height;
00435          
00436          erode_height = sed_cube_top_height(river_profile,0,i)-height;
00437          if ( erode_height > 1e-12 )
00438          {
00439             sed_column_extract_top( sed_cube_col(river_profile,i) ,
00440                                     erode_height                 ,
00441                                     eroded);
00442             sed_cell_add( eroded_sed , eroded );
00443          }
00444       }
00445          
00446       // convert time step to seconds.
00447       //dt = sed_cube_time_step_in_seconds( river_profile );
00448          
00449             // add the eroded sediment to the river discharge.
00450    //         river_data = sed_cube_river_data( river_profile );
00451          
00452 //      volume_eroded = sed_cell_size(eroded_sed)*dx*width;
00453 
00454       sed_cell_resize( eroded_sed , sed_cell_size(eroded_sed)*dx*width );
00455          
00456       //sed_hydro_add_cell( river_data  , eroded_sed );
00457          
00458 //      eh_message( "eroded sediment (m^3): %.3g" , volume_eroded );
00459          
00460       sed_cell_destroy( eroded );
00461    }
00462 
00463    return eroded_sed;
00464 }
00465 */
00466 
00467 gboolean bed_load_1d_domain( double x , double y , Bed_load_data *user_data )
00468 {
00469    double y_0 = user_data->y_0;
00470    double dy  = user_data->dy;
00471    double r_max = user_data->r_max;
00472 
00473    y*=dy;
00474 
00475    if ( y >= y_0 && y <= y_0+r_max && x>0 )
00476       return TRUE;
00477    
00478    return FALSE;
00479 }
00480 
00481 gboolean bed_load_2d_domain( double x , double y , Bed_load_data *user_data )
00482 {
00483    double x_0 = user_data->x_0;
00484    double y_0 = user_data->y_0;
00485    double dx  = user_data->dx;
00486    double dy  = user_data->dy;
00487    double r_max = user_data->r_max;
00488    double a_min = user_data->min_angle;
00489    double a_max = user_data->max_angle;
00490    double r, a;
00491 
00492    r = sqrt( pow( (x - x_0)*dx , 2. ) + pow( (y - y_0)*dy , 2. ) );
00493 
00494    if ( r < r_max )
00495    {
00496       a_min = eh_reduce_angle( a_min );
00497       a_max = eh_reduce_angle( a_max );
00498 
00499       a = atan2( (y - y_0)*dy , (x - x_0)*dx );
00500       if ( a_min > a_max )
00501       {
00502          if ( a < a_max )
00503             a += 2.*M_PI;
00504          a_max += 2.*M_PI;
00505       }
00506       if ( a > a_min && a < a_max )
00507          return TRUE;
00508    }
00509    return FALSE;
00510 }
00511 

Generated on Fri Jan 4 18:04:15 2008 for sedflux by  doxygen 1.5.2