00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <math.h>
00023 #include <glib.h>
00024 #include <utils/utils.h>
00025 #include <sed/sed_sedflux.h>
00026 #include "avulsion.h"
00027
00028 static double init_angle = 90.;
00029 static double min_angle = 0.;
00030 static double max_angle = 180.;
00031 static double std_dev = 1.;
00032 static gint seed = 0;
00033 static gint n_times = 100;
00034 static gint verbose = 0;
00035 static gboolean version = FALSE;
00036 static gboolean header = FALSE;
00037
00038 static gboolean lite = FALSE;
00039
00040 static double eps = 5.;
00041 static double alpha = 45.;
00042 static gint n_i = 100;
00043 static gint n_j = 100;
00044 static gint n_rivers = 1;
00045 static gchar* in_file = NULL;
00046 static gchar* out_type_s = NULL;
00047
00048 static GOptionEntry entries[] =
00049 {
00050 { "n-times" , 'n' , 0 , G_OPTION_ARG_INT , &n_times , "Number of iterations" , "N" } ,
00051 { "std-dev" , 's' , 0 , G_OPTION_ARG_DOUBLE , &std_dev , "Standard deviation (degs)" , "SIGMA" } ,
00052 { "min" , 'l' , 0 , G_OPTION_ARG_DOUBLE , &min_angle , "Minimum angle (degs)" , "MIN" } ,
00053 { "max" , 'h' , 0 , G_OPTION_ARG_DOUBLE , &max_angle , "Maximum angle (degs)" , "MAX" } ,
00054 { "start" , 'i' , 0 , G_OPTION_ARG_DOUBLE , &init_angle , "Starting angle (degs)" , "ANGLE" } ,
00055 { "seed" , 'd' , 0 , G_OPTION_ARG_INT , &seed , "Seed for RNG" , "SEED" } ,
00056 { "verbose" , 'V' , 0 , G_OPTION_ARG_INT , &verbose , "Verbosity level" , "N" } ,
00057 { "version" , 'v' , 0 , G_OPTION_ARG_NONE , &version , "Version number" , NULL } ,
00058 { "header" , 'H' , 0 , G_OPTION_ARG_NONE , &header , "Print a header" , NULL } ,
00059
00060 { "lite" , 'L' , 0 , G_OPTION_ARG_NONE , &lite , "Run the lite version" , NULL } ,
00061
00062 { "eps" , 'e' , 0 , G_OPTION_ARG_DOUBLE , &eps , "River join angle (degs)" , "ANGLE" } ,
00063 { "alpha" , 'a' , 0 , G_OPTION_ARG_DOUBLE , &alpha , "River split angle (degs)" , "ANGLE" } ,
00064 { "nx" , 'x' , 0 , G_OPTION_ARG_INT , &n_i , "Number of rows" , "N" } ,
00065 { "ny" , 'y' , 0 , G_OPTION_ARG_INT , &n_j , "Number of columns" , "N" } ,
00066 { "n-rivers", 'r' , 0 , G_OPTION_ARG_INT , &n_rivers , "Number of rivers" , "N" } ,
00067 { "river-file", 'f' , 0 , G_OPTION_ARG_FILENAME , &in_file , "River file" , "<file>" } ,
00068 { "out-type", 't' , 0 , G_OPTION_ARG_STRING , &out_type_s , "Type of output file" , "<out-key>" } ,
00069
00070 { NULL }
00071 };
00072
00073 int avulsion_lite( void );
00074 int avulsion_full( void );
00075
00076 typedef enum
00077 {
00078 AVULSION_OUTPUT_ANGLES,
00079 AVULSION_OUTPUT_DEPTHS
00080 }
00081 Avulsion_out_type;
00082
00083 Avulsion_out_type output_type;
00084
00085 int main( int argc , char *argv[] )
00086 {
00087 GError* error = NULL;
00088 GOptionContext* context = g_option_context_new( "Run random walk avulsion model" );
00089 gchar** command_line = eh_new0( gchar* , argc );
00090 gint i;
00091
00092 for ( i=1 ; i<argc ; i++ )
00093 command_line[i-1] = g_strdup( argv[i] );
00094
00095 g_thread_init(NULL);
00096
00097 g_option_context_add_main_entries( context , entries , NULL );
00098
00099 if ( !g_option_context_parse( context , &argc , &argv , &error ) )
00100 eh_error( "Error parsing command line arguments: %s" , error->message );
00101
00102 if ( version )
00103 {
00104 eh_fprint_version_info( stdout ,
00105 AVULSION_PROGRAM_NAME ,
00106 AVULSION_MAJOR_VERSION ,
00107 AVULSION_MINOR_VERSION ,
00108 AVULSION_MICRO_VERSION );
00109 exit(0);
00110 }
00111
00112 eh_set_verbosity_level( verbose );
00113
00114 min_angle *= S_RADS_PER_DEGREE;
00115 max_angle *= S_RADS_PER_DEGREE;
00116 init_angle *= S_RADS_PER_DEGREE;
00117 std_dev *= S_RADS_PER_DEGREE;
00118 eps *= S_RADS_PER_DEGREE;
00119 alpha *= S_RADS_PER_DEGREE;
00120
00121 if ( out_type_s )
00122 {
00123 if ( g_ascii_strcasecmp(out_type_s,"ANGLE")==0 )
00124 output_type = AVULSION_OUTPUT_ANGLES;
00125 else if ( g_ascii_strcasecmp(out_type_s,"DEPTH")==0 )
00126 output_type = AVULSION_OUTPUT_DEPTHS;
00127 else
00128 eh_require_not_reached();
00129 }
00130 else
00131 output_type = AVULSION_OUTPUT_ANGLES;
00132
00133 if ( header )
00134 {
00135 fprintf( stdout , "# Minimum angle = %f\n" , min_angle/S_RADS_PER_DEGREE );
00136 fprintf( stdout , "# Maximum angle = %f\n" , max_angle/S_RADS_PER_DEGREE );
00137 fprintf( stdout , "# Standard deviation = %f\n" , std_dev/S_RADS_PER_DEGREE );
00138 fprintf( stdout , "# Command line = %s\n" , g_strjoinv( " " , command_line ) );
00139 }
00140
00141 if ( lite )
00142 avulsion_lite( );
00143 else
00144 avulsion_full( );
00145
00146 g_strfreev( command_line );
00147
00148 return 0;
00149 }
00150
00151 int
00152 avulsion_lite( void )
00153 {
00154 {
00155 gint n;
00156 double angle = init_angle;
00157 GRand* rand = (seed==0)?g_rand_new():g_rand_new_with_seed(seed);
00158 double m;
00159
00160 m = 2.*G_PI/(max_angle-min_angle);
00161
00162 std_dev *= m;
00163
00164 for ( n=0 ; n<n_times ; n++ )
00165 {
00166 angle = avulsion( rand , angle , std_dev );
00167 fprintf( stdout , "%f\n" , (angle/m+.5*(min_angle+max_angle))*S_DEGREES_PER_RAD );
00168 }
00169
00170 g_rand_free( rand );
00171 }
00172
00173 return 0;
00174 }
00175
00176 typedef struct
00177 {
00178 double angle;
00179 double stddev;
00180 double size;
00181 int id;
00182 }
00183 stream_st;
00184
00185 GList *avulse_streams( GList *streams );
00186 GList *create_streams( GList *streams , double alpha );
00187 GList *merge_streams( GList *streams , double eps );
00188 GList *print_streams( GList *streams );
00189 GList *print_streams_as_table( GList *streams );
00190 void avulse_stream( stream_st *stream , gpointer data );
00191 int sort_streams_by_angle( stream_st *s1 , stream_st *s2 );
00192 int sort_streams_by_discharge( stream_st *s1 , stream_st *s2 );
00193 int sort_streams_by_id( stream_st *s1 , stream_st *s2 );
00194 void combine_rivers( Sed_riv r_1 , Sed_riv r_2 );
00195
00196 void sed_merge_all_rivers( Sed_cube c , double eps );
00197 GList *merge_rivers( GList *rivers , double eps );
00198 int sort_rivers_by_angle( Sed_riv r_1 , Sed_riv r_2 );
00199 int sort_rivers_by_discharge( Sed_riv r_1 , Sed_riv r_2 );
00200 void combine_river_discharge( Sed_riv r_1 , Sed_riv r_2 );
00201 Sed_riv split_river_discharge( Sed_riv r_1 , Sed_riv r_2 );
00202 void sed_split_all_rivers( Sed_cube c , double alpha );
00203 GList *create_rivers( GList *rivers , double alpha );
00204 void deposit_sediment_at_river_mouth( Sed_cube c );
00205
00206 int avulsion_full( )
00207 {
00208 Sed_cube cube;
00209
00210 {
00211 GError* error = NULL;
00212 Sed_sediment sediment_type = sed_sediment_scan( SED_SEDIMENT_TEST_FILE , &error );
00213
00214 if ( !sediment_type )
00215 eh_error( "%s: Unable to read sediment file: %s" , SED_SEDIMENT_TEST_FILE , error->message);
00216
00217 sed_sediment_set_env( sediment_type );
00218
00219 sed_sediment_destroy( sediment_type );
00220 }
00221
00222 {
00223 Eh_dbl_grid bathy_grid = sed_get_floor_3_default( 1 , n_i , n_j );
00224
00225 cube = sed_cube_new( eh_grid_n_x(bathy_grid) ,
00226 eh_grid_n_y(bathy_grid) );
00227 sed_cube_set_dz ( cube , 1. );
00228 sed_cube_set_bathy( cube , bathy_grid );
00229
00230 eh_grid_destroy( bathy_grid , TRUE );
00231 }
00232
00233 {
00234 gint i;
00235 Avulsion_st* data;
00236 Sed_riv new_river;
00237 Sed_hydro* hydro_data = sed_hydro_scan( NULL , NULL );
00238 double** river_data = NULL;
00239
00240 if ( in_file )
00241 {
00242 gint n_rows, n_cols;
00243
00244 river_data = eh_dlm_read( in_file , ",;" , &n_rows , &n_cols , NULL );
00245
00246 eh_require( n_cols==3 );
00247 n_rivers = n_rows;
00248 }
00249 else
00250 {
00251 river_data = eh_new_2( double , n_rivers , 3 );
00252 for ( i=0 ; i<n_rivers ; i++ )
00253 {
00254 river_data[i][0] = 0.;
00255 river_data[i][1] = 180.;
00256 river_data[i][2] = std_dev*S_DEGREES_PER_RAD;
00257 }
00258 }
00259
00260 for ( i=0 ; i<n_rivers ; i++ )
00261 {
00262 min_angle = river_data[i][0]*S_RADS_PER_DEGREE;
00263 max_angle = river_data[i][1]*S_RADS_PER_DEGREE;
00264 std_dev = river_data[i][2]*S_RADS_PER_DEGREE;
00265
00266 data = avulsion_new( (seed==0)?g_rand_new():g_rand_new_with_seed(seed) , std_dev );
00267
00268 new_river = sed_river_new ( NULL );
00269
00270 sed_river_set_angle ( new_river , .5*(min_angle+max_angle) );
00271 sed_river_set_angle_limit ( new_river , min_angle , max_angle );
00272 sed_river_set_hinge ( new_river , sed_cube_n_x(cube)/2 , 0 );
00273 sed_river_set_hydro ( new_river , hydro_data[0] );
00274 sed_river_set_avulsion_data( new_river , data );
00275 sed_cube_add_trunk ( cube , new_river );
00276 }
00277
00278 eh_free_2( river_data );
00279 }
00280
00281 {
00282 gint i, n;
00283 double t=0, t_end=n_times;
00284 Eh_status_bar* sb = eh_status_bar_new( &t , &t_end );
00285
00286 for ( n=0 ; n<n_times ; n++,t++ )
00287 {
00288 sed_cube_avulse_all_rivers( cube );
00289
00290
00291
00292
00293 if ( output_type==AVULSION_OUTPUT_ANGLES )
00294 {
00295 for ( i=0 ; i<n_rivers ; i++ )
00296 fprintf( stdout , "%f " , sed_river_angle( sed_cube_nth_river( cube,i ) )*S_DEGREES_PER_RAD );
00297 fprintf( stdout , "\n" );
00298 }
00299
00300 deposit_sediment_at_river_mouth( cube );
00301 }
00302
00303 eh_status_bar_destroy(sb);
00304 }
00305
00306 if ( output_type==AVULSION_OUTPUT_DEPTHS )
00307 {
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 gint i,j;
00318 gint top_i = sed_cube_n_x(cube);
00319 gint top_j = sed_cube_n_y(cube)-1;
00320
00321 for ( i=0 ; i<top_i ; i++ )
00322 {
00323 for ( j=0 ; j<top_j ; j++ )
00324 fprintf( stdout , "%f " , sed_cube_water_depth(cube,i,j) );
00325 fprintf( stdout , "%f\n" , sed_cube_water_depth(cube,i,j) );
00326 }
00327 }
00328
00329 sed_sediment_unset_env();
00330
00331 return 0;
00332 }
00333
00334 void deposit_sediment_helper( Sed_riv this_river , Sed_cube c );
00335
00336 void deposit_sediment_at_river_mouth( Sed_cube c )
00337 {
00338 g_list_foreach( sed_cube_river_list(c) , (GFunc)&deposit_sediment_helper , c );
00339 }
00340
00341 void deposit_sediment_helper( Sed_riv this_river , Sed_cube c )
00342 {
00343 Eh_ind_2 mouth_pos;
00344 Sed_cell deposit_cell;
00345
00346 {
00347 gssize n;
00348 gssize len = sed_sediment_env_n_types();
00349 double* f = eh_new( double , len );
00350
00351 f[0] = eh_get_fuzzy_dbl( 0 , 1 );
00352 for ( n=1 ; n<len ; n++ )
00353 f[n] = ( 1.-f[0] ) / ( (double)len - 1. );
00354
00355 deposit_cell = sed_cell_new_sized( len , 1. , f );
00356
00357 eh_free( f );
00358 }
00359
00360 this_river = sed_cube_find_river_mouth( c , this_river );
00361
00362 mouth_pos = sed_river_mouth( this_river );
00363
00364 if ( sed_cube_is_in_domain( c , mouth_pos.i , mouth_pos.j ) )
00365 {
00366 double depth = sed_column_water_depth(sed_cube_col_ij(c,mouth_pos.i,mouth_pos.j));
00367
00368 if ( depth<sed_cell_size(deposit_cell) )
00369 sed_cell_resize( deposit_cell , depth );
00370 sed_column_add_cell( sed_cube_col_ij(c,mouth_pos.i,mouth_pos.j) , deposit_cell );
00371 }
00372
00373 sed_cell_destroy( deposit_cell );
00374 }
00375
00376 void
00377 sed_merge_all_rivers( Sed_cube c , double eps )
00378 {
00379 sed_cube_set_river_list( c , merge_rivers( sed_cube_river_list(c) , eps ) );
00380 }
00381
00382 GList
00383 *merge_rivers( GList *rivers , double eps )
00384 {
00385 double d_theta;
00386 Sed_riv this_river, last_river;
00387 GList *this_link, *last_link;
00388
00389 rivers = g_list_sort( rivers , (GCompareFunc)&sort_rivers_by_angle );
00390
00391 for ( this_link=rivers->next ; this_link ; this_link=this_link->next )
00392 {
00393 last_link = this_link->prev;
00394
00395 this_river = this_link->data;
00396 last_river = last_link->data;
00397
00398 d_theta = sed_river_angle(this_river)
00399 - sed_river_angle(last_river);
00400 if ( d_theta < eps )
00401 {
00402 if ( sort_rivers_by_discharge( this_river , last_river ) > 0 )
00403 {
00404 combine_river_discharge( this_river , last_river );
00405 rivers = g_list_remove_link( rivers , last_link );
00406 }
00407 else
00408 {
00409 combine_river_discharge( last_river , this_river );
00410 rivers = g_list_remove_link( rivers , this_link );
00411 }
00412 }
00413 }
00414
00415 return rivers;
00416 }
00417
00418 int sort_rivers_by_angle( Sed_riv r_1 , Sed_riv r_2 )
00419 {
00420 if ( sed_river_angle(r_1) > sed_river_angle(r_2) )
00421 return 1;
00422 else if ( sed_river_angle(r_1) < sed_river_angle(r_2) )
00423 return -1;
00424 else
00425 return 0;
00426 }
00427
00428 int sort_rivers_by_discharge( Sed_riv r_1 , Sed_riv r_2 )
00429 {
00430 double q_1 = sed_river_water_flux(r_1);
00431 double q_2 = sed_river_water_flux(r_2);
00432
00433 if ( q_1 > q_2 )
00434 return 1;
00435 else if ( q_1 < q_2 )
00436 return -1;
00437 else
00438 return 0;
00439 }
00440
00441 int sort_streams_by_id( stream_st *s1 , stream_st *s2 )
00442 {
00443 if ( s1->id > s2->id )
00444 return 1;
00445 else if ( s1->id < s2->id )
00446 return -1;
00447 else
00448 return 0;
00449 }
00450
00451 void combine_river_discharge( Sed_riv r_1 , Sed_riv r_2 )
00452 {
00453 double total_q;
00454
00455 eh_require( r_1!=NULL );
00456 eh_require( r_2!=NULL );
00457
00458 total_q = sed_river_water_flux( r_1 )
00459 + sed_river_water_flux( r_2 );
00460
00461 sed_river_set_width( r_1 , total_q
00462 / ( sed_river_velocity(r_1)*sed_river_depth(r_1) ) );
00463
00464 }
00465
00466 Sed_riv split_river_discharge( Sed_riv r_1 , Sed_riv r_2 )
00467 {
00468 double q_1, q_2;
00469 double f=.25;
00470 Sed_riv new_river;
00471
00472 eh_require( r_1!=NULL );
00473 eh_require( r_2!=NULL );
00474
00475 q_1 = sed_river_water_flux( r_1 );
00476 q_2 = sed_river_water_flux( r_2 );
00477
00478 new_river = sed_river_dup( r_1 );
00479
00480 sed_river_set_angle ( new_river , .5*( sed_river_angle (r_1) + sed_river_angle (r_2) ) );
00481 sed_river_set_velocity( new_river , .5*( sed_river_velocity(r_1) + sed_river_velocity(r_2) ) );
00482 sed_river_set_depth ( new_river , .5*( sed_river_depth (r_1) + sed_river_depth (r_2) ) );
00483 sed_river_set_bedload ( new_river , .5*( sed_river_bedload (r_1) + sed_river_bedload (r_2) ) );
00484 sed_river_set_width ( new_river , f*( q_1+q_2 )
00485 / ( sed_river_velocity( new_river )
00486 * sed_river_depth ( new_river ) ) );
00487
00488 sed_river_set_width( r_1 , sed_river_width(r_1)*(1.-f) );
00489 sed_river_set_width( r_2 , sed_river_width(r_2)*(1.-f) );
00490
00491 return new_river;
00492 }
00493
00494 void sed_split_all_rivers( Sed_cube c , double alpha )
00495 {
00496 sed_cube_set_river_list( c , create_rivers( sed_cube_river_list(c) , alpha ) );
00497 }
00498
00499 GList *create_rivers( GList *rivers , double alpha )
00500 {
00501 double d_theta;
00502 GList *this_link, *last_link;
00503 Sed_riv left_wall, right_wall;
00504 Sed_riv this_river, last_river, new_river;
00505
00506 rivers = g_list_sort( rivers , (GCompareFunc)&sort_rivers_by_angle );
00507
00508 left_wall = sed_river_dup( g_list_first( rivers )->data );
00509 sed_river_set_angle( left_wall , G_PI );
00510 sed_river_set_width( left_wall , 0. );
00511
00512 right_wall = sed_river_dup( g_list_last( rivers )->data );
00513 sed_river_set_angle( right_wall , 0. );
00514 sed_river_set_width( right_wall , 0. );
00515
00516 rivers = g_list_insert_sorted( rivers ,
00517 left_wall ,
00518 (GCompareFunc)&sort_rivers_by_angle );
00519 rivers = g_list_insert_sorted( rivers ,
00520 right_wall ,
00521 (GCompareFunc)&sort_rivers_by_angle );
00522
00523 for ( this_link=rivers->next ; this_link ; this_link=this_link->next )
00524 {
00525 last_link = this_link->prev;
00526
00527 this_river = this_link->data;
00528 last_river = last_link->data;
00529
00530 d_theta = sed_river_angle(this_river) - sed_river_angle(last_river);
00531
00532 if ( d_theta > alpha )
00533 {
00534
00535 new_river = split_river_discharge( this_river , last_river );
00536
00537 rivers = g_list_insert_sorted( rivers ,
00538 new_river ,
00539 (GCompareFunc)&sort_rivers_by_angle );
00540 }
00541 }
00542
00543 rivers = g_list_remove( rivers , left_wall );
00544 rivers = g_list_remove( rivers , right_wall );
00545
00546 sed_river_destroy( left_wall );
00547 sed_river_destroy( right_wall );
00548
00549 return rivers;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599