00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "utils/utils.h"
00022 #include "sed_cube.h"
00023
00024 CLASS ( Sed_cube )
00025 {
00026 gchar* name;
00027 double age;
00028 double time_step;
00029 double storm_value;
00030 double quake_value;
00031 double tidal_range;
00032 double tidal_period;
00033 double wave[3];
00034 GSList *storm_list;
00035
00036 Sed_cell erode;
00037 Sed_cell remove;
00038 Sed_column **col;
00039 int n_x;
00040 int n_y;
00041 double basinWidth;
00042 double dx;
00043 double dy;
00044 double sea_level;
00045 GList *river;
00046 GList *shore;
00047 double cell_height;
00048 Sed_constants constants;
00049 };
00050
00051 GQuark
00052 sed_cube_susp_grid_quark( void )
00053 {
00054 return g_quark_from_static_string( "sed-cube-susp-grid-quark" );
00055 }
00056
00057 GQuark
00058 sed_cube_error_quark( void )
00059 {
00060 return g_quark_from_static_string( "sed-cube-error-quark" );
00061 }
00062
00063 static Sedflux_mode __sedflux_mode = SEDFLUX_MODE_NOT_SET;
00064
00065 void
00066 sed_mode_set( Sedflux_mode mode )
00067 {
00068 if ( __sedflux_mode == SEDFLUX_MODE_NOT_SET
00069 && mode != SEDFLUX_MODE_NOT_SET )
00070 __sedflux_mode = mode;
00071 }
00072
00073 gboolean
00074 sed_mode_is( Sedflux_mode mode )
00075 {
00076 return __sedflux_mode==mode;
00077 }
00078
00079 gboolean
00080 sed_mode_is_2d( void )
00081 {
00082 return __sedflux_mode==SEDFLUX_MODE_2D;
00083 }
00084
00085 gboolean
00086 sed_mode_is_3d( void )
00087 {
00088 return __sedflux_mode==SEDFLUX_MODE_3D;
00089 }
00090
00091 #define DEFAULT_BINS (16)
00092
00093 Sed_cube sed_cube_new( gssize n_x , gssize n_y )
00094 {
00095 Sed_cube s;
00096
00097 s = sed_cube_new_empty( n_x , n_y );
00098
00099 if ( s )
00100 {
00101 gint i, j;
00102
00103 for (i=0;i<n_x;i++)
00104 for (j=0;j<n_y;j++)
00105 {
00106 s->col[i][j] = sed_column_new( DEFAULT_BINS );
00107 sed_column_set_x_position( s->col[i][j] , i );
00108 sed_column_set_y_position( s->col[i][j] , j );
00109 }
00110 }
00111
00112 return s;
00113 }
00114
00115 Sed_cube
00116 sed_cube_new_empty( gssize n_x , gssize n_y )
00117 {
00118 Sed_cube s;
00119
00120 eh_return_val_if_fail( n_x>=0 , NULL );
00121 eh_return_val_if_fail( n_y>=0 , NULL );
00122
00123 NEW_OBJECT( Sed_cube , s );
00124
00125 if ( n_x*n_y>0 )
00126 {
00127 gint i;
00128 s->col = eh_new( Sed_column* , n_x );
00129 s->col[0] = eh_new( Sed_column , n_x*n_y );
00130 for ( i=1 ; i<n_x ; i++ )
00131 s->col[i] = s->col[i-1]+n_y;
00132 }
00133 else
00134 s->col = NULL;
00135
00136
00137
00138 s->erode = sed_cell_new_env( );
00139 s->remove = sed_cell_new_env( );
00140
00141 s->name = g_strdup( "( null )" );
00142
00143 s->age = 0.;
00144 s->time_step = 0.;
00145 s->sea_level = 0.;
00146 s->storm_value = 1.;
00147 s->quake_value = 0.;
00148 s->tidal_range = 0.;
00149 s->tidal_period = G_MAXFLOAT;
00150 s->wave[0] = 1.;
00151 s->wave[1] = 1.;
00152 s->wave[2] = 1.;
00153 s->storm_list = NULL;
00154 s->dx = 1.;
00155 s->dy = 1.;
00156 s->n_x = n_x;
00157 s->n_y = n_y;
00158 s->river = NULL;
00159 s->shore = NULL;
00160 eh_message( "DONE" );
00161
00162 return s;
00163 }
00164
00165 #define SED_KEY_MARGIN_NAME "margin name"
00166 #define SED_KEY_V_RES "vertical resolution"
00167 #define SED_KEY_X_RES "x resolution"
00168 #define SED_KEY_Y_RES "y resolution"
00169 #define SED_KEY_H_RES "horizontal resolution"
00170 #define SED_KEY_LENGTH "basin length"
00171 #define SED_KEY_WIDTH "basin width"
00172 #define SED_KEY_BATHY_FILE "bathymetry file"
00173 #define SED_KEY_SEDIMENT_FILE "sediment file"
00174
00175 Sed_cube
00176 sed_cube_new_from_file( const gchar* file , GError** error )
00177 {
00178 Sed_cube p = NULL;
00179
00180 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00181
00182 if ( file )
00183 {
00184 GError* tmp_err = NULL;
00185 gchar* name;
00186 gchar* bathy_file;
00187 gchar* sediment_file;
00188 double x_res, y_res, z_res;
00189
00190
00191 if ( !tmp_err )
00192 {
00193 Eh_key_file key_file = eh_key_file_scan( file , &tmp_err );
00194
00195 if ( key_file )
00196 {
00197
00198 name = eh_key_file_get_value ( key_file , "global" , SED_KEY_MARGIN_NAME );
00199 z_res = eh_key_file_get_dbl_value( key_file , "global" , SED_KEY_V_RES );
00200 x_res = eh_key_file_get_dbl_value( key_file , "global" , SED_KEY_X_RES );
00201 y_res = eh_key_file_get_dbl_value( key_file , "global" , SED_KEY_Y_RES );
00202 bathy_file = eh_key_file_get_value ( key_file , "global" , SED_KEY_BATHY_FILE );
00203 sediment_file = eh_key_file_get_value ( key_file , "global" , SED_KEY_SEDIMENT_FILE );
00204 }
00205
00206 eh_key_file_destroy ( key_file );
00207 }
00208
00209
00210 if ( !tmp_err )
00211 {
00212 Sed_sediment sediment_type = sed_sediment_scan( sediment_file , &tmp_err );
00213
00214 if ( sediment_type )
00215 {
00216 sed_sediment_set_env( sediment_type );
00217 sed_sediment_destroy( sediment_type );
00218 }
00219 }
00220
00221
00222 if ( !tmp_err )
00223 {
00224 Eh_dbl_grid grid = NULL;
00225
00226
00227 grid = sed_bathy_grid_scan( bathy_file , x_res , y_res , &tmp_err );
00228
00229 if ( grid )
00230 {
00231
00232 gint i, j;
00233 Sed_column this_col;
00234
00235
00236 p = sed_cube_new( eh_grid_n_x(grid) , eh_grid_n_y(grid) );
00237
00238
00239 for ( i=0 ; i<sed_cube_n_x(p) ; i++ )
00240 for ( j=0 ; j<sed_cube_n_y(p) ; j++ )
00241 {
00242 this_col = sed_cube_col_ij(p,i,j);
00243
00244 sed_column_set_x_position ( this_col , eh_grid_x(grid)[i] );
00245 sed_column_set_y_position ( this_col , eh_grid_y(grid)[j] );
00246
00247 sed_column_set_base_height( this_col , eh_dbl_grid_val(grid,i,j) );
00248 }
00249
00250
00251 sed_cube_set_x_res( p , x_res );
00252 sed_cube_set_y_res( p , y_res );
00253 sed_cube_set_z_res( p , z_res );
00254
00255
00256 sed_cube_set_name( p , name );
00257 }
00258
00259 eh_grid_destroy ( grid , TRUE );
00260 }
00261
00262 if ( tmp_err )
00263 g_propagate_error( error , tmp_err );
00264
00265
00266 eh_free ( name );
00267 eh_free ( bathy_file );
00268 eh_free ( sediment_file );
00269 }
00270
00271 return p;
00272 }
00273
00274 Sed_cube
00275 sed_cube_free( Sed_cube s , gboolean free_data )
00276 {
00277 if ( s )
00278 {
00279 if ( free_data )
00280 {
00281 gssize i, n_nodes = sed_cube_size(s);
00282 for ( i=0 ; i<n_nodes ; i++ )
00283 sed_column_destroy( s->col[0][i] );
00284 }
00285
00286 eh_free( s->col[0] );
00287 eh_free( s->col );
00288
00289 sed_cube_remove_all_trunks( s );
00290
00291 sed_cell_destroy( s->erode );
00292 sed_cell_destroy( s->remove );
00293
00294 sed_cube_destroy_storm_list( s );
00295
00296 g_list_free( s->shore );
00297
00298 eh_free( s->name );
00299 eh_free( s );
00300 }
00301
00302 return NULL;
00303 }
00304
00305 Sed_cube sed_cube_free_river( Sed_cube p )
00306 {
00307 if ( p )
00308 {
00309 GList *list;
00310
00311 for ( list=p->river ; list ; list=list->next )
00312 sed_river_destroy( list->data );
00313 p->river = NULL;
00314 }
00315 return p;
00316 }
00317
00318 Sed_cube sed_cube_destroy( Sed_cube s )
00319 {
00320 sed_cube_free( s , TRUE );
00321 return NULL;
00322 }
00323
00324 Sed_cube sed_cube_copy_scalar_data( Sed_cube dest , const Sed_cube src )
00325 {
00326 if ( !dest )
00327 dest = sed_cube_new( src->n_x , dest->n_y );
00328
00329 eh_free( dest->name );
00330 dest->name = g_strdup( src->name );
00331
00332 dest->age = src->age;
00333 dest->time_step = src->time_step;
00334 dest->storm_value = src->storm_value;
00335 dest->quake_value = src->quake_value;
00336 dest->tidal_range = src->tidal_range;
00337 dest->tidal_period = src->tidal_period;
00338 dest->wave[0] = src->wave[0];
00339 dest->wave[1] = src->wave[1];
00340 dest->wave[2] = src->wave[2];
00341 dest->sea_level = src->sea_level;
00342 dest->cell_height = src->cell_height;
00343 dest->dx = src->dx;
00344 dest->dy = src->dy;
00345
00346 return dest;
00347 }
00348
00349 Sed_cube sed_cube_copy_pointer_data( Sed_cube dest , const Sed_cube src )
00350 {
00351 if ( !dest )
00352 dest = sed_cube_new( src->n_x , dest->n_y );
00353
00354
00355 dest->erode = src->erode;
00356 dest->remove = src->remove;
00357 dest->storm_list = g_slist_copy( src->storm_list );
00358
00359 return dest;
00360 }
00361
00362 Sed_cell_grid
00363 sed_cube_create_in_suspension( Sed_cube s )
00364 {
00365 Sed_cell_grid in_suspension;
00366
00367 if ( s )
00368 {
00369 in_suspension = sed_cell_grid_new( 2*s->n_x , 2*s->n_y );
00370
00371 sed_cell_grid_init( in_suspension , sed_sediment_env_n_types() );
00372
00373
00374
00375
00376
00377
00378 eh_grid_reindex( in_suspension , -s->n_x , -s->n_y );
00379 }
00380
00381 return in_suspension;
00382 }
00383
00384 Sed_cell_grid
00385 sed_cube_destroy_in_suspension( Sed_cell_grid g )
00386 {
00387 if ( g )
00388 {
00389 sed_cell_grid_free( g );
00390 eh_grid_destroy( g , TRUE );
00391 }
00392 return NULL;
00393 }
00394
00395 GSList* sed_cube_storm_list( Sed_cube c )
00396 {
00397 eh_return_val_if_fail( c!=NULL , NULL );
00398 return c->storm_list;
00399 }
00400
00401 Sed_cube sed_cube_set_storm_list( Sed_cube c , GSList *storms )
00402 {
00403 sed_cube_destroy_storm_list( c );
00404 c->storm_list = storms;
00405 return c;
00406 }
00407
00408 void __free_slist_ocean_storm_data( Sed_ocean_storm s , gpointer user_data )
00409 {
00410 sed_ocean_storm_destroy( s );
00411 }
00412
00413 Sed_cube sed_cube_destroy_storm_list( Sed_cube c )
00414 {
00415 eh_return_val_if_fail( c!=NULL , NULL );
00416
00417 g_slist_foreach( c->storm_list ,
00418 (GFunc)&__free_slist_ocean_storm_data ,
00419 NULL );
00420
00421 g_slist_free( c->storm_list );
00422
00423 return c;
00424 }
00425
00426 Sed_cube sed_cube_set_bathy( Sed_cube c , Eh_dbl_grid g )
00427 {
00428 eh_return_val_if_fail( g!=NULL , c );
00429
00430 if ( !c )
00431 c = sed_cube_new( eh_grid_n_x(g) , eh_grid_n_y(g) );
00432
00433 eh_require( eh_grid_n_x(g)==c->n_x );
00434 eh_require( eh_grid_n_y(g)==c->n_y );
00435
00436 if ( g )
00437 {
00438 gssize i, j;
00439 for ( i=0 ; i<c->n_x ; i++ )
00440 for ( j=0 ; j<c->n_y ; j++ )
00441 sed_column_set_base_height( c->col[i][j] , eh_dbl_grid_val(g,i,j) );
00442 }
00443
00444 return c;
00445 }
00446
00447 Sed_cube sed_cube_set_dz( Sed_cube p , double new_dz )
00448 {
00449 eh_return_val_if_fail( p!=NULL , NULL );
00450
00451 {
00452 gssize i, len = sed_cube_size(p);
00453 p->cell_height = new_dz;
00454 for ( i=0 ; i<len ; i++ )
00455 sed_column_set_z_res( sed_cube_col( p , i ) , new_dz );
00456 }
00457
00458 return p;
00459 }
00460
00461 char* sed_cube_name( const Sed_cube s )
00462 {
00463 eh_return_val_if_fail( s!=NULL , NULL );
00464 return g_strdup( s->name );
00465 }
00466
00467 gssize sed_cube_size( const Sed_cube s )
00468 {
00469 eh_return_val_if_fail( s!=NULL , 0 );
00470 return s->n_x*s->n_y;
00471 }
00472
00473 gssize sed_cube_n_x( const Sed_cube s )
00474 {
00475 eh_return_val_if_fail( s!=NULL , 0 );
00476 return s->n_x;
00477 }
00478
00479 gssize sed_cube_n_y( const Sed_cube s )
00480 {
00481 eh_return_val_if_fail( s!=NULL , 0 );
00482 return s->n_y;
00483 }
00484
00485 Sed_column
00486 sed_cube_col( const Sed_cube s , gssize ind )
00487 {
00488 eh_return_val_if_fail( s!=NULL , NULL );
00489
00490 eh_require( ind>=0 );
00491 eh_require( ind<sed_cube_size(s) );
00492
00493 return s->col[0][ind];
00494 }
00495
00496 Sed_column
00497 sed_cube_col_ij( const Sed_cube s , gssize i , gssize j )
00498 {
00499 eh_return_val_if_fail( s!=NULL , NULL );
00500
00501 eh_require( i>=0 );
00502 eh_require( j>=0 );
00503 eh_require( i<sed_cube_n_x(s) );
00504 eh_require( sed_cube_id(s,i,j)<sed_cube_size(s) );
00505
00506 return s->col[i][j];
00507 }
00508
00509 Sed_column
00510 sed_cube_col_pos( const Sed_cube s , double x , double y )
00511 {
00512 Sed_column c = NULL;
00513
00514 if ( s )
00515 {
00516 gint id = sed_cube_column_id( s , x , y );
00517
00518 if ( id>=0 ) c = sed_cube_col( s , id );
00519 }
00520
00521 return c;
00522 }
00523
00524 double sed_cube_sea_level( const Sed_cube s )
00525 {
00526 eh_return_val_if_fail( s!=NULL , 0. );
00527 return s->sea_level;
00528 }
00529
00530 double* sed_cube_x( const Sed_cube s , gssize *id )
00531 {
00532 double *x;
00533
00534 eh_return_val_if_fail( s!=NULL , NULL );
00535
00536 {
00537 gssize i, n_x;
00538
00539 if ( !id )
00540 {
00541 x = eh_new( double , s->n_x );
00542 for ( i=0 ; i<s->n_x ; i++ )
00543 x[i] = sed_column_x_position( sed_cube_col(s,i*s->n_y) );
00544 }
00545 else
00546 {
00547 for ( n_x=0 ; id[n_x]>=0 ; n_x++ );
00548 x = eh_new( double , n_x );
00549 for ( i=0 ; i<n_x ; i++ )
00550 x[i] = sed_column_x_position( sed_cube_col(s,id[i]) );
00551 }
00552 }
00553
00554 return x;
00555 }
00556
00557 double* sed_cube_y( const Sed_cube s , gssize *id )
00558 {
00559 double *y;
00560
00561 eh_return_val_if_fail( s!=NULL , NULL );
00562
00563 {
00564 gssize i, n_y;
00565
00566 if ( !id )
00567 {
00568 y = eh_new( double , s->n_y );
00569 for ( i=0 ; i<s->n_y ; i++ )
00570 y[i] = sed_column_y_position( sed_cube_col(s,i) );
00571 }
00572 else
00573 {
00574 for ( n_y=0 ; id[n_y]>=0 ; n_y++ );
00575 y = eh_new( double , n_y );
00576 for ( i=0 ; i<n_y ; i++ )
00577 y[i] = sed_column_y_position( sed_cube_col(s,id[i]) );
00578 }
00579 }
00580
00581 return y;
00582 }
00583
00584 double sed_cube_col_x( const Sed_cube s , gssize id )
00585 {
00586 eh_require( id >= 0 );
00587 eh_require( id < sed_cube_size(s) );
00588
00589 return sed_column_x_position( sed_cube_col(s,id) );
00590 }
00591
00592 double sed_cube_col_x_ij( const Sed_cube s , gssize i , gssize j )
00593 {
00594 return sed_column_x_position( sed_cube_col_ij(s,i,j) );
00595 }
00596
00597 double sed_cube_col_y( const Sed_cube s , gssize id )
00598 {
00599 eh_require( id >= 0 );
00600 eh_require( id < sed_cube_size(s) );
00601
00602 return sed_column_y_position( sed_cube_col(s,id) );
00603 }
00604
00605 double sed_cube_col_y_ij( const Sed_cube s , gssize i , gssize j )
00606 {
00607 return sed_column_y_position( sed_cube_col_ij(s,i,j) );
00608 }
00609
00610 double sed_cube_x_slope( const Sed_cube s , gssize i , gssize j )
00611 {
00612 double slope;
00613
00614 eh_require( s );
00615 eh_require( eh_is_in_domain( s->n_x , s->n_y , i , j ) );
00616
00617 if ( s->n_x < 2 )
00618 return 0;
00619
00620 if ( i==s->n_x-1 )
00621 slope = ( sed_cube_water_depth( s , i , j )
00622 - sed_cube_water_depth( s , i-1 , j ) )
00623 / sed_cube_x_res( s );
00624 else
00625 slope = ( sed_cube_water_depth( s , i+1 , j )
00626 - sed_cube_water_depth( s , i , j ) )
00627 / sed_cube_x_res( s );
00628
00629 return slope;
00630 }
00631
00632 double sed_cube_y_slope( const Sed_cube s , gssize i , gssize j )
00633 {
00634 double slope;
00635
00636 eh_require( s );
00637 eh_require( eh_is_in_domain( s->n_x , s->n_y , i , j ) );
00638
00639 if ( s->n_y < 2 )
00640 return 0;
00641
00642 if ( j==s->n_y-1 )
00643 slope = ( sed_cube_water_depth( s , i , j )
00644 - sed_cube_water_depth( s , i , j-1 ) )
00645 / sed_cube_y_res( s );
00646 else
00647 slope = ( sed_cube_water_depth( s , i , j+1 )
00648 - sed_cube_water_depth( s , i , j ) )
00649 / sed_cube_y_res( s );
00650
00651 return slope;
00652 }
00653
00654 double sed_cube_y_slope_fast( const Sed_cube s , gssize i , gssize j )
00655 {
00656 eh_require( s );
00657 eh_require( eh_is_in_domain( s->n_x , s->n_y , i , j ) );
00658
00659 return ( sed_cube_water_depth( s , i , j+1 )
00660 - sed_cube_water_depth( s , i , j ) )
00661 / sed_cube_y_res( s );
00662 }
00663
00664 double sed_cube_slope( const Sed_cube s , gssize i , gssize j )
00665 {
00666 double dx, dy;
00667
00668 dx = sed_cube_x_slope( s , i , j );
00669 dy = sed_cube_y_slope( s , i , j );
00670
00671 return sqrt( dx*dx + dy*dy );
00672 }
00673
00674 double sed_cube_slope_dir( const Sed_cube s , gssize i , gssize j )
00675 {
00676 double dx, dy;
00677
00678 dx = sed_cube_x_slope( s , i , j );
00679 dy = sed_cube_y_slope( s , i , j );
00680
00681 return atan2( dy , dx );
00682 }
00683
00684 Eh_pt_2 sed_cube_slope_vector( const Sed_cube s , gssize i , gssize j )
00685 {
00686 Eh_pt_2 u;
00687
00688 eh_require( s );
00689
00690 u.x = sed_cube_x_slope( s , i , j );
00691 u.y = sed_cube_y_slope( s , i , j );
00692
00693 return u;
00694 }
00695
00696 double sed_cube_top_height(const Sed_cube p , gssize i , gssize j )
00697 {
00698 return sed_column_top_height( sed_cube_col_ij( p , i , j ) );
00699 }
00700
00701 Eh_ind_2 sed_ind2sub( gssize ind , gssize n_y )
00702 {
00703 Eh_ind_2 sub;
00704
00705 sub.i = floor( ind / n_y );
00706 sub.j = fmod ( ind , n_y );
00707
00708 return sub;
00709 }
00710
00711 Eh_dbl_grid sed_cube_grid( const Sed_cube s ,
00712 Sed_grid_func func ,
00713 gssize *index )
00714 {
00715 Eh_dbl_grid g;
00716
00717 eh_require( s );
00718
00719 {
00720 gssize i, j;
00721
00722 g = eh_grid_new( double , s->n_x , s->n_y );
00723
00724 if ( index )
00725 {
00726 for ( i=0 ; index[i]>=0 ; i++ )
00727 eh_dbl_grid_set_val( g , 0 , index[i] , (*func)( s , 0 , index[i] ) );
00728 }
00729 else
00730 {
00731 for ( i=0 ; i<eh_grid_n_x(g) ; i++ )
00732 for ( j=0 ; j<eh_grid_n_y(g) ; j++ )
00733 eh_dbl_grid_set_val( g , i , j , (*func)( s , i , j ) );
00734 }
00735 }
00736
00737 return g;
00738 }
00739
00740 Eh_dbl_grid sed_cube_slope_dir_grid( const Sed_cube s , gssize *index )
00741 {
00742 return sed_cube_grid( s , S_SLOPE_DIR_FUNC , index );
00743 }
00744
00745 Eh_dbl_grid sed_cube_x_slope_grid( const Sed_cube s , gssize *index )
00746 {
00747 return sed_cube_grid( s , S_X_SLOPE_FUNC , index );
00748 }
00749
00750 Eh_dbl_grid sed_cube_y_slope_grid( const Sed_cube s , gssize *index )
00751 {
00752 return sed_cube_grid( s , S_Y_SLOPE_FUNC , index );
00753 }
00754
00755 Eh_dbl_grid sed_cube_water_depth_grid( const Sed_cube s , gssize *index )
00756 {
00757 return sed_cube_grid( s , S_WATER_DEPTH_FUNC , index );
00758 }
00759
00760 Eh_dbl_grid sed_cube_thickness_grid( const Sed_cube s , gssize *index )
00761 {
00762 return sed_cube_grid( s , S_THICKNESS_FUNC , index );
00763 }
00764
00765 Eh_dbl_grid sed_cube_load_grid( const Sed_cube s , gssize *index )
00766 {
00767 return sed_cube_grid( s , S_LOAD_FUNC , index );
00768 }
00769
00770 Sed_riv
00771 sed_cube_river_by_name( Sed_cube s , const char *name )
00772 {
00773 Sed_riv the_river = NULL;
00774
00775 if ( s )
00776 {
00777 GList *found;
00778 found = g_list_find_custom( s->river ,
00779 name ,
00780 (GCompareFunc)&sed_river_name_cmp );
00781 if ( found )
00782 the_river = (Sed_riv)(found->data);
00783 }
00784
00785 return the_river;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 gssize
00805 sed_cube_river_id( Sed_cube s , Sed_riv river )
00806 {
00807 return g_list_index( s->river , river );
00808 }
00809
00810 Sed_cell_grid
00811 sed_cube_in_suspension( Sed_cube s , Sed_riv river )
00812 {
00813 eh_return_val_if_fail( s!=NULL , NULL );
00814 return sed_river_get_susp_grid( river );
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824 GList*
00825 sed_cube_river_list( Sed_cube s )
00826 {
00827 return s->river;
00828 }
00829
00830 Sed_riv*
00831 sed_cube_all_trunks( Sed_cube s )
00832 {
00833 Sed_riv* all = NULL;
00834
00835 if ( s )
00836 {
00837 GList* r_list = sed_cube_river_list( s );
00838 GList* l;
00839
00840 for ( l=r_list ; l ; l=l->next )
00841 eh_strv_append( (gchar***)&all , l->data );
00842 }
00843
00844 return all;
00845 }
00846
00847 Sed_riv*
00848 sed_cube_all_branches( Sed_cube s )
00849 {
00850 Sed_riv* all = NULL;
00851
00852 if ( s )
00853 {
00854 GList* r_list = sed_cube_river_list( s );
00855 GList* l;
00856 Sed_riv* branches;
00857
00858 for ( l=r_list ; l ; l=l->next )
00859 {
00860 branches = sed_river_branches( l->data );
00861 eh_strv_concat( (gchar***)&all , (gchar**)branches );
00862
00863 eh_free( branches );
00864 }
00865
00866 }
00867
00868 return all;
00869 }
00870
00871 Sed_riv*
00872 sed_cube_all_leaves( Sed_cube s )
00873 {
00874 Sed_riv* all = NULL;
00875
00876 if ( s )
00877 {
00878 GList* r_list = sed_cube_river_list( s );
00879 GList* l;
00880 Sed_riv* leaves;
00881
00882 for ( l=r_list ; l ; l=l->next )
00883 {
00884 leaves = sed_river_leaves( l->data );
00885 eh_strv_concat( (gchar***)&all , (gchar**)leaves );
00886
00887 eh_free( leaves );
00888 }
00889
00890 }
00891
00892 return all;
00893 }
00894
00895 Sed_riv*
00896 sed_cube_all_rivers( Sed_cube s )
00897 {
00898 Sed_riv* all = NULL;
00899
00900 if ( s )
00901 {
00902 GList* r_list = sed_cube_river_list( s );
00903 GList* l;
00904
00905 for ( l=r_list ; l ; l=l->next )
00906 eh_strv_append( (gchar***)&all , l->data );
00907 }
00908
00909 return all;
00910 }
00911
00912 gint
00913 sed_cube_n_branches( Sed_cube s )
00914 {
00915 gint n = 0;
00916 eh_return_val_if_fail( s!=NULL , 0 );
00917 if ( s )
00918 {
00919 gint i;
00920 gint n_rivers = sed_cube_n_rivers(s);
00921 for ( i=0 ; i<n_rivers ; i++ )
00922 n += sed_river_n_branches( g_list_nth_data(s->river,i) );
00923 }
00924 return n;
00925 }
00926
00927 gint
00928 sed_cube_n_rivers( Sed_cube s )
00929 {
00930 eh_return_val_if_fail( s!=NULL , 0 );
00931 return g_list_length( s->river );
00932 }
00933
00934 gssize sed_cube_number_of_rivers( Sed_cube s )
00935 {
00936 eh_return_val_if_fail( s!=NULL , 0 );
00937 return g_list_length( s->river );
00938 }
00939
00940 double sed_cube_time_step( const Sed_cube s )
00941 {
00942 eh_require( s );
00943 return s->time_step;
00944 }
00945
00946 double sed_cube_time_step_in_years( const Sed_cube s )
00947 {
00948 eh_require( s );
00949 return s->time_step;
00950 }
00951
00952 double sed_cube_time_step_in_seconds( const Sed_cube s )
00953 {
00954 eh_require( s );
00955 return s->time_step*S_SECONDS_PER_YEAR;
00956 }
00957
00958 double sed_cube_time_step_in_days( const Sed_cube s )
00959 {
00960 eh_require( s );
00961 return s->time_step*S_DAYS_PER_YEAR;
00962 }
00963
00964 Sed_constants sed_cube_constants( const Sed_cube s )
00965 {
00966 eh_require( s );
00967 return s->constants;
00968 }
00969
00970 double sed_cube_x_res( const Sed_cube s )
00971 {
00972 eh_require( s );
00973 return s->dx;
00974 }
00975
00976 double sed_cube_y_res( const Sed_cube s )
00977 {
00978 eh_require( s );
00979 return s->dy;
00980 }
00981
00982 double sed_cube_z_res( const Sed_cube s )
00983 {
00984 eh_require( s );
00985 return s->cell_height;
00986 }
00987
00988 Sed_cell sed_cube_to_remove( const Sed_cube s )
00989 {
00990 eh_require( s );
00991 return s->remove;
00992 }
00993
00994 Sed_cell sed_cube_to_add( const Sed_cube s )
00995 {
00996 eh_require( s );
00997 return s->erode;
00998 }
00999
01000 gssize sed_column_x_index( const Sed_cube c , double x )
01001 {
01002 gssize i;
01003
01004 eh_require( c );
01005
01006 if ( x<=sed_cube_col_x( c,0 ) )
01007 i = 0;
01008 else if ( x>=sed_cube_col_x( c , (c->n_y-1)*c->n_x ) )
01009 i = c->n_x-1;
01010 else
01011 {
01012 for ( i=0 ; i<c->n_x && sed_column_x_position( c->col[i][0] ) <= x ; i++ );
01013 i = i-1;
01014 }
01015
01016 return i;
01017 }
01018
01019 gssize sed_column_y_index( const Sed_cube c , double y )
01020 {
01021 gssize j;
01022
01023 eh_require( c );
01024
01025 if ( y<=sed_cube_col_y( c,0 ) )
01026 j = 0;
01027 else if ( y>=sed_cube_col_y( c , c->n_y-1 ) )
01028 j = c->n_y-1;
01029 else
01030 {
01031 for ( j=0 ; j<c->n_y && sed_column_y_position( c->col[0][j] ) <= y ; j++ );
01032 j = j-1;
01033 }
01034
01035 return j;
01036 }
01037
01038 double sed_cube_wave_height( const Sed_cube s )
01039 {
01040 return s->wave[0];
01041 }
01042
01043 double sed_cube_wave_period( const Sed_cube s )
01044 {
01045 return s->wave[1];
01046 }
01047
01048 double sed_cube_wave_length( const Sed_cube s )
01049 {
01050 return s->wave[2];
01051 }
01052
01053 double sed_cube_storm( const Sed_cube s )
01054 {
01055 return s->storm_value;
01056 }
01057
01058 double sed_cube_quake( const Sed_cube s )
01059 {
01060 return s->quake_value;
01061 }
01062
01063 double sed_cube_age( const Sed_cube s )
01064 {
01065 return s->age;
01066 }
01067
01068 double sed_cube_age_in_years( const Sed_cube s )
01069 {
01070 return s->age;
01071 }
01072
01073 double sed_cube_tidal_period( const Sed_cube s )
01074 {
01075 return s->tidal_period;
01076 }
01077
01078 Sed_cube sed_cube_set_tidal_period( Sed_cube s , double new_val )
01079 {
01080 s->tidal_period = new_val;
01081 return s;
01082 }
01083
01084 double sed_cube_tidal_range( const Sed_cube s )
01085 {
01086 return s->tidal_range;
01087 }
01088
01089 Sed_cube sed_cube_set_tidal_range( Sed_cube s , double new_val )
01090 {
01091 s->tidal_range = new_val;
01092 return s;
01093 }
01094
01095 double sed_cube_water_depth( const Sed_cube p , gssize i , gssize j )
01096 {
01097 double depth;
01098
01099 eh_require( p );
01100
01101 depth = sed_column_water_depth( sed_cube_col_ij(p,i,j) );
01102
01103 return depth;
01104 }
01105
01106 double sed_cube_water_pressure( const Sed_cube p , gssize i , gssize j )
01107 {
01108 double press = 0.;
01109
01110 eh_require( p );
01111
01112 {
01113 double water_depth = sed_cube_water_depth(p,i,j);
01114
01115 if ( water_depth > 0 )
01116 press = water_depth*sed_rho_sea_water()*sed_gravity();
01117 }
01118
01119 return press;
01120 }
01121
01122 double sed_cube_load( const Sed_cube p , gssize i , gssize j )
01123 {
01124 double load;
01125
01126 eh_require( p );
01127
01128 {
01129 double sediment_load = sed_column_load_at( sed_cube_col_ij(p,i,j) , 0 );
01130 double water_load = sed_cube_water_pressure( p , i , j );
01131
01132 load = water_load + sediment_load;
01133 }
01134
01135 return load;
01136 }
01137
01138 double sed_cube_thickness( const Sed_cube p , gssize i , gssize j )
01139 {
01140 return sed_column_thickness( p->col[i][j] );
01141 }
01142
01143 gboolean
01144 sed_cube_col_is_empty( const Sed_cube p , gssize i , gssize j )
01145 {
01146 return sed_column_is_empty( p->col[i][j] );
01147 }
01148
01149 double sed_cube_base_height( const Sed_cube p , gssize i , gssize j )
01150 {
01151 return sed_column_base_height( sed_cube_col_ij(p,i,j) );
01152 }
01153
01162 Sed_cube sed_cube_dup( Sed_cube c )
01163 {
01164 return sed_cube_copy( NULL , c );
01165 }
01166
01176 Sed_cube sed_cube_copy( Sed_cube dest , const Sed_cube src )
01177 {
01178 eh_require( src );
01179
01180 if ( dest==NULL )
01181 dest = sed_cube_new( src->n_x , src->n_y );
01182
01183 eh_require( dest->n_x==src->n_x && dest->n_y==src->n_y );
01184
01185 sed_cube_copy_scalar_data ( dest , src );
01186 sed_cube_copy_pointer_data( dest , src );
01187
01188 return dest;
01189 }
01190
01205 Sed_cube sed_cube_copy_cols( const Sed_cube src , gssize* x , gssize* y , double* z , gssize len )
01206 {
01207 Sed_cube new_cube = NULL;
01208
01209 eh_require( src );
01210 eh_require( x );
01211 eh_require( y );
01212 eh_require( z );
01213 eh_require( len>0 );
01214
01215 new_cube = sed_cube_new( 1 , len );
01216
01217 {
01218 gssize i;
01219
01220 sed_cube_copy_scalar_data( new_cube , src );
01221
01222 for (i=0;i<len;i++)
01223 new_cube->col[0][i] = sed_column_height_copy( src->col[x[i]][y[i]] ,
01224 z[i] ,
01225 NULL );
01226 }
01227
01228 return new_cube;
01229 }
01230
01245 Sed_cube sed_cube_copy_line( const Sed_cube src , double *x , double *y , double *z , gssize len )
01246 {
01247 Sed_cube new_cube = NULL;
01248
01249 eh_require( src );
01250 eh_require( x );
01251 eh_require( y );
01252 eh_require( z );
01253 eh_require( len>0 );
01254
01255 {
01256 gssize i;
01257 gssize *id = eh_new( gssize , len );
01258
01259 for ( i=0 ; i<len ; i++ )
01260 id[i] = sed_cube_column_id( src , x[i] , y[i] );
01261
01262 new_cube = sed_cube_new( 1 , len );
01263
01264 sed_cube_copy_scalar_data( new_cube , src );
01265
01266 for (i=0;i<len;i++)
01267 new_cube->col[0][i] = sed_column_height_copy( src->col[0][id[i]] ,
01268 z[i] ,
01269 NULL );
01270 eh_free( id );
01271 }
01272
01273 return new_cube;
01274 }
01275
01276 Sed_cube
01277 sed_cube_cols( Sed_cube src , gssize *path )
01278 {
01279 Sed_cube new_cube = NULL;
01280
01281 eh_require( src!=NULL );
01282
01283 {
01284 gssize j;
01285 gssize len;
01286
01287 if ( path )
01288 for ( len=0 ; path[len]>=0 ; len++ );
01289 else
01290 len = sed_cube_size( src );
01291
01292 new_cube = sed_cube_new_empty( 1 , len );
01293 sed_cube_copy_scalar_data( new_cube , src );
01294
01295 if ( path )
01296 for ( j=0 ; j<len ; j++ )
01297 new_cube->col[0][j] = src->col[0][path[j]];
01298 else
01299 for ( j=0 ; j<len ; j++ )
01300 new_cube->col[0][j] = src->col[0][j];
01301 }
01302
01303 return new_cube;
01304 }
01305
01306 gssize sed_cube_river_mouth_1d( Sed_cube c )
01307 {
01308 gssize i_river = 0;
01309
01310 eh_require( c );
01311 eh_require( c->n_x==1 );
01312
01313 {
01314 double river_depth = 1e-5;
01315
01316
01317
01318
01319 for ( i_river=0 ;
01320 i_river<c->n_y && sed_cube_water_depth(c,0,i_river) <= river_depth ;
01321 i_river++ );
01322
01323 if ( i_river >= c->n_y )
01324 eh_warning( "The river mouth is at the right boundary" );
01325 else if ( i_river <= 0 )
01326 eh_warning( "The river mouth is at the left boundary" );
01327
01328 eh_clamp( i_river , 0 , c->n_y-1 );
01329 }
01330
01331 return i_river;
01332 }
01333
01334 Sed_cube sed_cube_remove( Sed_cube dest , Sed_cube src )
01335 {
01336 gssize i;
01337 gssize dest_size = sed_cube_size(dest);
01338 gssize *src_id = eh_new( gssize , dest_size );
01339
01340 for ( i=0 ; i<dest_size ; i++ )
01341 src_id[i] = sed_cube_column_id( src ,
01342 sed_column_x_position( dest->col[0][i] ) ,
01343 sed_column_y_position( dest->col[0][i] ) );
01344
01345 for ( i=0 ; i<dest_size ; i++ )
01346 if ( src_id[i]>=0 )
01347 sed_column_remove( dest->col[0][i] ,
01348 src->col[0][src_id[i]] );
01349
01350 eh_free( src_id );
01351
01352 return dest;
01353 }
01354
01355 Sed_cube sed_cube_add( Sed_cube dest , const Sed_cube src )
01356 {
01357 gssize i;
01358 gssize src_size = sed_cube_size(src);
01359 gssize *dest_id = eh_new( gssize , src_size );
01360
01361 for ( i=0 ; i<src_size ; i++ )
01362 dest_id[i] = sed_cube_column_id( dest ,
01363 sed_column_x_position( src->col[0][i] ) ,
01364 sed_column_y_position( src->col[0][i] ) );
01365
01366 for ( i=0 ; i<src_size ; i++ )
01367 if ( dest_id[i]>=0 )
01368 sed_column_add( dest->col[0][dest_id[i]] ,
01369 src->col[0][i] );
01370
01371 eh_free( dest_id );
01372
01373 return dest;
01374 }
01375
01376 double sed_cube_mass( const Sed_cube p )
01377 {
01378 double mass = 0;
01379
01380 if ( p )
01381 {
01382 gssize i;
01383 gssize len = sed_cube_size(p);
01384
01385 for ( i=0 ; i<len ; i++ )
01386 mass += sed_column_mass( sed_cube_col(p,i) );
01387 mass *= sed_cube_x_res(p)*sed_cube_y_res(p);
01388 }
01389
01390 return mass;
01391 }
01392
01393 double
01394 sed_cube_sediment_mass(const Sed_cube p )
01395 {
01396 double mass = 0;
01397
01398 eh_require( p );
01399 {
01400 gint i;
01401 gint len = sed_cube_size(p);
01402
01403 for ( i=0 ; i<len ; i++ )
01404 mass += sed_column_sediment_mass( sed_cube_col(p,i) );
01405 mass *= sed_cube_x_res(p)*sed_cube_y_res(p);
01406 }
01407
01408 return mass;
01409 }
01410
01411 double
01412 sed_cube_mass_in_suspension( const Sed_cube p )
01413 {
01414 double mass = 0.;
01415
01416 if ( p )
01417 {
01418 Sed_riv* all_rivers = sed_cube_all_branches(p);
01419 Sed_riv* r;
01420 Sed_cell_grid in_susp;
01421
01422 if ( all_rivers )
01423 {
01424 for ( r=all_rivers ; *r ; r++ )
01425 {
01426 in_susp = g_dataset_id_get_data( *r , SED_CUBE_SUSP_GRID );
01427 mass += sed_cell_grid_mass( in_susp );
01428 }
01429
01430 eh_free( all_rivers );
01431 }
01432
01433 mass *= sed_cube_x_res(p)*sed_cube_y_res(p);
01434 }
01435
01436 return mass;
01437 }
01438
01439 Sed_cube
01440 sed_cube_set_sea_level( Sed_cube s , double new_sea_level )
01441 {
01442 if ( s )
01443 {
01444 gssize i, len = sed_cube_size(s);
01445 s->sea_level = new_sea_level;
01446 for ( i=0 ; i<len ; i++ )
01447 sed_column_set_sea_level( sed_cube_col(s,i) , new_sea_level );
01448 }
01449
01450 return s;
01451 }
01452
01453 Sed_cube sed_cube_adjust_sea_level( Sed_cube s , double dz )
01454 {
01455 return sed_cube_set_sea_level( s , s->sea_level + dz );
01456 }
01457
01458 Sed_cube sed_cube_set_base_height( Sed_cube s , gssize i , gssize j , double height )
01459 {
01460 sed_column_set_base_height( sed_cube_col_ij(s,i,j) , height );
01461 return s;
01462 }
01463
01464 Sed_cube sed_cube_adjust_base_height( Sed_cube s , gssize i , gssize j , double dz )
01465 {
01466 Sed_column this_col = sed_cube_col_ij(s,i,j);
01467 sed_column_set_base_height( this_col ,
01468 sed_column_base_height( this_col ) + dz );
01469 return s;
01470 }
01471
01472 Sed_cube
01473 sed_cube_set_nth_river( Sed_cube s , gssize n , Sed_riv new_river )
01474 {
01475 eh_require( s );
01476
01477 if ( s )
01478 {
01479 GList* node = g_list_nth( s->river , n );
01480
01481 eh_require( node );
01482
01483 sed_river_copy( node->data , new_river );
01484 }
01485 return s;
01486 }
01487
01488 Eh_pt_2*
01489 sed_cube_river_mouth_position( Sed_cube s ,
01490 Sed_riv this_river )
01491 {
01492 Eh_pt_2 *river_mouth_pos;
01493
01494 eh_require( s );
01495 eh_require( this_river );
01496
01497 {
01498 Eh_ind_2 mouth_pos = sed_river_mouth( this_river );
01499 Eh_ind_2 hinge_pos = sed_river_hinge( this_river );
01500 Eh_polygon_2 shore_cell = eh_get_rectangle_polygon(
01501 eh_create_pt_2(
01502 (mouth_pos.i+.5)*sed_cube_x_res( s ) ,
01503 (mouth_pos.j+.5)*sed_cube_y_res( s ) ) ,
01504 sed_cube_x_res( s ) ,
01505 sed_cube_y_res( s ) );
01506 GList *river_end = eh_find_polygon_crossings(
01507 eh_create_pt_2(
01508 (hinge_pos.i+.5)*sed_cube_x_res( s ) ,
01509 (hinge_pos.j+.5)*sed_cube_y_res( s ) ) ,
01510 sed_river_angle(this_river) ,
01511 shore_cell ,
01512 POLYGON_IN_CROSSINGS );
01513
01514 if ( river_end && (g_list_length( river_end ) == 1) )
01515 river_mouth_pos = (Eh_pt_2*)(river_end->data);
01516 else
01517 {
01518 river_mouth_pos = NULL;
01519 eh_require_not_reached( );
01520 }
01521
01522 eh_destroy_polygon( shore_cell );
01523 g_list_free( river_end );
01524 }
01525
01526 return river_mouth_pos;
01527 }
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 Sed_cube sed_cube_set_river_list( Sed_cube s , GList* river_list )
01547 {
01548 s->river = river_list;
01549 return s;
01550 }
01551
01552 Sed_cube
01553 sed_cube_split_river( Sed_cube s , const gchar* name )
01554 {
01555 if ( s )
01556 {
01557 Sed_cell_grid left_grid;
01558 Sed_cell_grid right_grid;
01559 Sed_riv trunk = sed_cube_river_by_name( s , name );
01560 Sed_riv r = sed_river_longest_branch( trunk );
01561
01562
01563 sed_river_split( r );
01564
01565
01566 left_grid = sed_cube_create_in_suspension(s);
01567 right_grid = sed_cube_create_in_suspension(s);
01568
01569
01570 sed_river_attach_susp_grid( sed_river_left(r) , left_grid );
01571 sed_river_attach_susp_grid( sed_river_right(r) , right_grid );
01572 }
01573 return s;
01574 }
01575
01576 void
01577 sed_river_attach_susp_grid( Sed_riv r , Sed_cell_grid g )
01578 {
01579 eh_require( r );
01580 g_dataset_id_set_data_full( r , SED_CUBE_SUSP_GRID , g , (GDestroyNotify)sed_cube_destroy_in_suspension );
01581 }
01582
01583 Sed_cell_grid
01584 sed_river_get_susp_grid( Sed_riv r )
01585 {
01586 return g_dataset_id_get_data( r , SED_CUBE_SUSP_GRID );
01587 }
01588
01589 void
01590 sed_river_detach_susp_grid( Sed_riv r )
01591 {
01592 g_dataset_id_remove_data( r , SED_CUBE_SUSP_GRID );
01593 }
01594
01595 Sed_cube
01596 sed_cube_add_trunk( Sed_cube s , Sed_riv new_trunk )
01597 {
01598 Sed_cell_grid new_grid = sed_cube_create_in_suspension( s );
01599
01600 s->river = g_list_prepend( s->river , new_trunk );
01601
01602 sed_river_attach_susp_grid( new_trunk , new_grid );
01603
01604 return s;
01605 }
01606
01607 Sed_cube
01608 sed_cube_remove_river( Sed_cube s , Sed_riv r )
01609 {
01610 if ( r )
01611 {
01612 sed_river_detach_susp_grid( r );
01613
01614 if ( sed_river_left (r) ) sed_cube_remove_river( s , sed_river_left(r) );
01615 if ( sed_river_right(r) ) sed_cube_remove_river( s , sed_river_right(r) );
01616
01617
01618 s->river = g_list_remove( s->river , r );
01619
01620 sed_river_destroy( r );
01621 }
01622 return s;
01623 }
01624
01625 Sed_cube
01626 sed_cube_remove_all_trunks( Sed_cube s )
01627 {
01628 if ( s && s->river )
01629 {
01630 Sed_riv* all = sed_cube_all_trunks( s );
01631 Sed_riv* r;
01632
01633 if ( all )
01634 {
01635 for ( r=all ; *r ; r++ )
01636 sed_cube_remove_river( s , *r );
01637
01638 eh_free( all );
01639 }
01640
01641 eh_require( s->river == NULL );
01642 }
01643 return s;
01644 }
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658 Sed_riv
01659 sed_cube_nth_river( Sed_cube s , gint n )
01660 {
01661 Sed_riv r = NULL;
01662
01663 if ( s ) r = g_list_nth_data( s->river , n );
01664
01665 return r;
01666 }
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676 Sed_cube sed_cube_set_name( Sed_cube s , char *name )
01677 {
01678 eh_require( s )
01679 {
01680 eh_free( s->name );
01681 s->name = g_strdup( name );
01682 }
01683 return s;
01684 }
01685
01686 Sed_cube sed_cube_set_time_step( Sed_cube s , double time_step_in_years )
01687 {
01688 eh_require( s )
01689 {
01690 s->time_step = time_step_in_years;
01691 }
01692 return s;
01693 }
01694
01695 Sed_cube set_cube_set_constants( Sed_cube s , Sed_constants new_c )
01696 {
01697 eh_require( s )
01698 {
01699 s->constants = new_c;
01700 }
01701 return s;
01702 }
01703
01704 Sed_cube sed_cube_set_x_res( Sed_cube s , double new_x_res )
01705 {
01706 eh_require( s )
01707 {
01708 s->dx = new_x_res;
01709 }
01710 return s;
01711 }
01712
01713 Sed_cube sed_cube_set_y_res( Sed_cube s , double new_y_res )
01714 {
01715 eh_require( s )
01716 {
01717 s->dy = new_y_res;
01718 }
01719 return s;
01720 }
01721
01722 Sed_cube sed_cube_set_z_res( Sed_cube s , double new_z_res )
01723 {
01724 eh_require( s )
01725 {
01726 gssize i, len = sed_cube_size(s);
01727 for ( i=0 ; i<len ; i++ )
01728 sed_column_set_z_res( sed_cube_col(s,i) , new_z_res );
01729 s->cell_height = new_z_res;
01730 }
01731
01732 return s;
01733 }
01734
01735 Sed_cube sed_cube_set_wave_height( Sed_cube s , double new_wave_height )
01736 {
01737 s->wave[0] = new_wave_height;
01738 return s;
01739 }
01740
01741 Sed_cube sed_cube_set_wave_period( Sed_cube s , double new_wave_period )
01742 {
01743 s->wave[1] = new_wave_period;
01744 return s;
01745 }
01746
01747 Sed_cube sed_cube_set_wave_length( Sed_cube s , double new_wave_length )
01748 {
01749 s->wave[2] = new_wave_length;
01750 return s;
01751 }
01752
01753 Sed_cube sed_cube_set_storm( Sed_cube s , double new_storm_value )
01754 {
01755 s->storm_value = new_storm_value;
01756 return s;
01757 }
01758
01759 Sed_cube sed_cube_set_quake( Sed_cube s , double new_quake_value )
01760 {
01761 eh_require( s )
01762 {
01763 s->quake_value = new_quake_value;
01764 }
01765 return s;
01766 }
01767
01768 Sed_cube sed_cube_set_age( Sed_cube s , double new_age )
01769 {
01770 eh_require( s )
01771 {
01772 s->age = new_age;
01773 }
01774 return s;
01775 }
01776
01777 Sed_cube sed_cube_adjust_age( Sed_cube s , double dt )
01778 {
01779 return sed_cube_set_age( s , s->age + dt );
01780 }
01781
01782 Sed_cube sed_cube_increment_age( Sed_cube s )
01783 {
01784 return sed_cube_adjust_age( s , sed_cube_time_step(s) );
01785 }
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810 #define VARY_COLS (0)
01811 #define VARY_ROWS (1)
01812
01813 void sed_cube_set_shore( Sed_cube s )
01814 {
01815 int i;
01816 Eh_ind_2 *pos;
01817 GList *shore_list=NULL;
01818 GList *list;
01819
01820 g_list_free( s->shore );
01821 s->shore = NULL;
01822
01823
01824
01825
01826
01827
01828 if ( (pos=sed_cube_find_shore( s , 0 , VARY_COLS ))
01829 || (pos=sed_cube_find_shore( s , s->n_x-1 , VARY_COLS ))
01830 || (pos=sed_cube_find_shore( s , 0 , VARY_ROWS ))
01831 || (pos=sed_cube_find_shore( s , s->n_y-1 , VARY_ROWS )) )
01832 shore_list = sed_cube_find_shore_line( s , pos );
01833 else
01834 {
01835 for ( i=1 ; pos==NULL && i<s->n_x-1 ; i++ )
01836 pos = sed_cube_find_shore( s , i , VARY_COLS );
01837 if ( !pos )
01838 eh_message( "There are no shore cells in the domain" );
01839 else
01840 shore_list = sed_cube_find_shore_line( s , pos );
01841 }
01842
01843 for ( list=shore_list ; list ; list=list->next )
01844 {
01845 fprintf( stderr , "shore : %d , %d\n" ,
01846 ((Eh_ind_2*)(list->data))->i ,
01847 ((Eh_ind_2*)(list->data))->j );
01848 }
01849
01850 s->shore = shore_list;
01851 }
01852
01853 GList *sed_cube_find_shore_line( Sed_cube s , Eh_ind_2 *pos )
01854 {
01855 return sed_find_next_shore( NULL , s , pos , g_list_prepend( NULL , pos ) );
01856 }
01857
01858 int eh_compare_ind_2( Eh_ind_2 *a , Eh_ind_2 *b );
01859
01860 GList *sed_find_next_shore( GList *shore_list ,
01861 Sed_cube s ,
01862 Eh_ind_2 *pos ,
01863 GList *ignore_list )
01864 {
01865 int i;
01866 Eh_ind_2 shift[8] = { {-1,-1} , {0,-1} , {1,-1} ,
01867 {-1, 0} , {1, 0} ,
01868 {-1, 1} , {0, 1} , {1, 1} };
01869 GList *child_list = NULL;
01870 GList *list;
01871 Eh_ind_2 shift_pos;
01872 Eh_ind_2 *next_pos;
01873
01874 for ( i=0 ; i<8 ; i++ )
01875 {
01876 shift_pos = eh_ind_2_create( pos->i+shift[i].i , pos->j+shift[i].j );
01877 if ( g_list_find_custom( ignore_list ,
01878 &shift_pos ,
01879 (GCompareFunc)&eh_compare_ind_2 )
01880 == NULL
01881 && is_shore_cell( s , shift_pos.i , shift_pos.j ) )
01882 {
01883 next_pos = eh_ind_2_dup( &shift_pos , NULL );
01884 child_list = g_list_prepend( child_list , next_pos );
01885 }
01886 }
01887
01888
01889 if ( child_list )
01890 {
01891 for ( list=child_list ; list ; list=list->next )
01892 ignore_list = g_list_prepend( ignore_list ,
01893 eh_ind_2_dup( list->data , NULL ) );
01894
01895 for ( list=child_list ; list ; list=list->next )
01896 shore_list = sed_find_next_shore( shore_list ,
01897 s ,
01898 list->data ,
01899 ignore_list );
01900 shore_list = g_list_prepend( shore_list , pos );
01901 }
01902 else
01903 return g_list_prepend( shore_list , pos );
01904
01905 return shore_list;
01906 }
01907
01908 int eh_compare_ind_2( Eh_ind_2 *a , Eh_ind_2 *b )
01909 {
01910 if ( a->i==b->i && a->j==b->j )
01911 return 0;
01912 else if ( a->i < b->i )
01913 return -1;
01914 else if ( a->i > b->i )
01915 return 1;
01916 else if ( a->j < b->j )
01917 return -1;
01918 else
01919 return 1;
01920 }
01921
01930 gboolean is_shore_cell( Sed_cube s , gssize x , gssize y )
01931 {
01932 gboolean is_shore = FALSE;
01933
01934 eh_require( s!=NULL );
01935
01936 if ( x<0 || x>=s->n_x || y<0 || y>=s->n_y )
01937 {
01938 int west = y-1;
01939 int east = y+1;
01940 int north = x-1;
01941 int south = x+1;
01942
01943
01944 eh_clamp( west , 0 , s->n_y-1 );
01945 eh_clamp( east , 0 , s->n_y-1 );
01946 eh_clamp( north , 0 , s->n_x-1 );
01947 eh_clamp( south , 0 , s->n_x-1 );
01948
01949
01950
01951
01952
01953
01954 if ( sed_column_is_below( s->col[x][y] , s->sea_level ) )
01955 is_shore = FALSE;
01956 else if ( sed_column_is_below( s->col[x][west] , s->sea_level )
01957 || sed_column_is_below( s->col[x][east] , s->sea_level )
01958 || sed_column_is_below( s->col[north][y] , s->sea_level )
01959 || sed_column_is_below( s->col[south][y] , s->sea_level ) )
01960 is_shore = TRUE;
01961 else
01962 is_shore = FALSE;
01963 }
01964
01965 return is_shore;
01966 }
01967
01968 int sed_cube_find_shore_edge( Sed_cube s , gssize i , gssize j )
01969 {
01970 int shore_edge = 0;
01971 int west = j-1;
01972 int east = j+1;
01973 int north = i-1;
01974 int south = i+1;
01975
01976 eh_require( s!=NULL );
01977
01978
01979
01980
01981 if ( !eh_is_in_domain( s->n_x , s->n_y , i , j )
01982 || sed_column_is_below( s->col[i][j] , s->sea_level ) )
01983 return shore_edge;
01984
01985
01986
01987
01988
01989
01990 if ( eh_is_in_domain( s->n_x , s->n_y , i , west )
01991 && sed_column_is_below( s->col[i][west] , s->sea_level ) )
01992 shore_edge |= S_WEST_EDGE;
01993
01994 if ( eh_is_in_domain( s->n_x , s->n_y , i , east )
01995 && sed_column_is_below( s->col[i][east] , s->sea_level ) )
01996 shore_edge |= S_EAST_EDGE;
01997
01998 if ( eh_is_in_domain( s->n_x , s->n_y , i , north )
01999 && sed_column_is_below( s->col[north][j] , s->sea_level ) )
02000 shore_edge |= S_NORTH_EDGE;
02001
02002 if ( eh_is_in_domain( s->n_x , s->n_y , i , south )
02003 && sed_column_is_below( s->col[south][j] , s->sea_level ) )
02004 shore_edge |= S_SOUTH_EDGE;
02005
02006 return shore_edge;
02007 }
02008
02009 Eh_ind_2 *sed_cube_find_adjacent_shore_edge( Sed_cube s ,
02010 gssize i ,
02011 gssize j ,
02012 int edge )
02013 {
02014 Eh_ind_2 this_index;
02015 int new_edge;
02016
02017
02018
02019
02020
02021
02022 new_edge = sed_rotate_direction( edge , -1 );
02023
02024 this_index.i = i;
02025 this_index.j = j;
02026
02027 if ( sed_cube_is_shore_edge( s , this_index.i , this_index.j , new_edge ) )
02028 return eh_ind_2_dup( &this_index , NULL );
02029
02030 if ( !eh_is_in_domain( s->n_x , s->n_y , this_index.i , this_index.j ) )
02031 return NULL;
02032
02033
02034
02035
02036
02037
02038 this_index = sed_shift_index_over_edge( this_index.i ,
02039 this_index.j ,
02040 new_edge );
02041 new_edge = sed_rotate_direction( edge , +1 );
02042
02043 if ( sed_cube_is_shore_edge( s , this_index.i , this_index.j , new_edge ) )
02044 return eh_ind_2_dup( &this_index , NULL );
02045
02046
02047
02048
02049
02050
02051
02052 this_index = sed_shift_index_over_edge( this_index.i ,
02053 this_index.j ,
02054 new_edge );
02055
02056 return eh_ind_2_dup( &this_index , NULL );
02057 }
02058
02069 int sed_rotate_direction( int dir , int angle )
02070 {
02071 return dir << (angle%4);
02072 }
02073
02088 gboolean sed_cube_is_shore_edge( Sed_cube s , gssize i , gssize j , int edge )
02089 {
02090 Eh_ind_2 shift = sed_shift_index_over_edge( i , j , edge );
02091
02092 if ( !eh_is_in_domain( s->n_x , s->n_y , shift.i , shift.j ) )
02093 return FALSE;
02094
02095 if ( sed_column_is_below( s->col[i][j] , s->sea_level )
02096 ^ sed_column_is_below( s->col[shift.i][shift.j] , s->sea_level ) )
02097 return TRUE;
02098 else
02099 return FALSE;
02100 }
02101
02110 Eh_ind_2 sed_shift_index_over_edge( gssize i , gssize j , int edge )
02111 {
02112 Eh_ind_2 shift[4] = { {-1, 0} , { 0,+1} , {+1, 0} , { 0,-1} };
02113 Eh_ind_2 new_index, this_shift;
02114
02115 if ( edge|S_NORTH_EDGE )
02116 this_shift = shift[0];
02117 else if ( edge|S_EAST_EDGE )
02118 this_shift = shift[1];
02119 else if ( edge|S_SOUTH_EDGE )
02120 this_shift = shift[2];
02121 else if ( edge|S_WEST_EDGE )
02122 this_shift = shift[3];
02123
02124 new_index.i = i+this_shift.i;
02125 new_index.j = j+this_shift.j;
02126
02127 return new_index;
02128 }
02129
02130 GList *sed_cube_find_columns_custom( Sed_cube s ,
02131 gssize i ,
02132 gssize j ,
02133 gpointer data ,
02134 Sed_cube_func stop_func ,
02135 Sed_cube_func angle_func )
02136 {
02137 double angle;
02138 GList *column_list=NULL;
02139 Eh_ind_2 shift;
02140 Eh_pt_2 pos_in_cell;
02141
02142
02143
02144
02145 pos_in_cell.x = .5*s->dx;
02146 pos_in_cell.y = .5*s->dy;
02147
02148 eh_require( s );
02149 eh_require( eh_is_in_domain( s->n_x , s->n_y , i , j ) );
02150
02151
02152
02153
02154
02155 if ( (*stop_func)( s , i , j , data ) )
02156 return column_list;
02157
02158 column_list = g_list_prepend( column_list , s->col[i][j] );
02159
02160
02161
02162
02163
02164
02165 while ( eh_is_in_domain( s->n_x , s->n_y , i , j )
02166 && !stop_func( s , i , j , data ) )
02167 {
02168
02169
02170 angle = angle_func( s , i , j , NULL );
02171
02172
02173 pos_in_cell = get_path_exit_pos( pos_in_cell , angle , s->dx , s->dy );
02174
02175 eh_clamp( pos_in_cell.y , .01*s->dy , .99*s->dy );
02176 eh_clamp( pos_in_cell.x , .01*s->dx , .99*s->dx );
02177
02178
02179
02180 shift = get_shift_from_exit_pos( pos_in_cell , s->dx , s->dy );
02181 pos_in_cell = get_path_entrance_pos( pos_in_cell , s->dx , s->dy );
02182
02183 eh_clamp( pos_in_cell.y , .01*s->dy , .99*s->dy );
02184 eh_clamp( pos_in_cell.x , .01*s->dx , .99*s->dx );
02185
02186
02187 i += shift.i;
02188 j += shift.j;
02189
02190
02191
02192
02193 if ( eh_is_in_domain( s->n_x , s->n_y , i , j ) )
02194 {
02195 if ( column_list->data != s->col[i][j] )
02196 column_list = g_list_prepend( column_list , s->col[i][j] );
02197 else
02198 break;
02199 }
02200
02201 }
02202
02203 return column_list;
02204 }
02205
02206 GList *sed_cube_find_cross_shore_columns( Sed_cube s , gssize i , gssize j )
02207 {
02208 Eh_pt_2 u;
02209 GList *column_list = NULL;
02210 int shift_i, shift_j;
02211 double max_depth = 20;
02212
02213 if ( sed_cube_water_depth( s , i , j ) > max_depth )
02214 return g_list_prepend( column_list , s->col[i][j] );
02215
02216 u = sed_cube_slope_vector( s , i , j );
02217
02218 shift_i = eh_sign( u.x );
02219 shift_j = eh_sign( u.y );
02220
02221 if ( shift_i != 0 )
02222 column_list = sed_cube_find_cross_shore_columns( s , i+shift_i , j );
02223
02224 if ( shift_j != 0 )
02225 column_list = sed_cube_find_cross_shore_columns( s , i , j+shift_j );
02226
02227 column_list = g_list_prepend( column_list , s->col[i][j] );
02228
02229 return column_list;
02230 }
02231
02240 Eh_ind_2 *sed_cube_find_shore( Sed_cube s , int n , int vary_dim )
02241 {
02242 int i, j;
02243 int row, col;
02244 Eh_ind_2 *pos=NULL;
02245
02246 if ( vary_dim==VARY_COLS )
02247 {
02248 row = n;
02249 for ( j=0 ; j<s->n_y-1 && !pos ; j++ )
02250 if ( sed_column_is_below( s->col[row][j] , s->sea_level )
02251 ^ sed_column_is_below( s->col[row][j+1] , s->sea_level ) )
02252 {
02253 pos = eh_new( Eh_ind_2 , 1 );
02254 if ( sed_column_is_below( s->col[row][j] , s->sea_level ) )
02255 pos->j = j+1;
02256 else
02257 pos->j = j;
02258 pos->i = row;
02259 }
02260 }
02261 else
02262 {
02263 col = n;
02264 for ( i=0 ; i<s->n_x-1 && !pos ; i++ )
02265 if ( sed_column_is_below( s->col[i][col] , s->sea_level )
02266 ^ sed_column_is_below( s->col[i+1][col] , s->sea_level ) )
02267 {
02268 pos = eh_new( Eh_ind_2 , 1 );
02269 if ( sed_column_is_below( s->col[i][col] , s->sea_level ) )
02270 pos->i = i+1;
02271 else
02272 pos->i = i;
02273 pos->j = col;
02274 }
02275 }
02276
02277 return pos;
02278 }
02279
02280 GTree *sed_create_shore_tree( GList *shore )
02281 {
02282 GTree *tree = g_tree_new( (GCompareFunc)&eh_compare_ind_2 );
02283 while ( shore )
02284 {
02285 g_tree_insert( tree , shore->data , shore->data );
02286 shore = shore->next;
02287 }
02288 return tree;
02289 }
02290
02291 Sed_riv
02292 sed_cube_find_river_mouth( Sed_cube c , Sed_riv this_river )
02293 {
02294 Eh_ind_2 hinge_pos;
02295 Eh_ind_2 *new_pos;
02296 double hinge_angle;
02297
02298 hinge_pos = sed_river_hinge( this_river );
02299 hinge_angle = sed_river_angle( this_river );
02300
02301 new_pos = sed_find_river_mouth( c , &hinge_pos , hinge_angle );
02302
02303 sed_river_set_mouth( this_river , new_pos->i , new_pos->j );
02304
02305 eh_free( new_pos );
02306
02307 return this_river;
02308 }
02309
02310 GList*
02311 sed_cube_find_river_path( Sed_cube c ,
02312 Eh_ind_2 *hinge_pos ,
02313 double angle )
02314 {
02315 GList *river = sed_cube_find_line_path( c , hinge_pos , angle );
02316 return river;
02317 }
02318
02319 Eh_ind_2*
02320 sed_find_river_mouth( Sed_cube c ,
02321 Eh_ind_2 *hinge_pos ,
02322 double angle )
02323 {
02324 GList *this_link;
02325 Eh_ind_2 *ans;
02326 GList *river = sed_cube_find_river_path( c , hinge_pos , angle );
02327
02328 ans = eh_ind_2_dup( river->data , NULL );
02329
02330 for ( this_link=river ; this_link ; this_link=this_link->next )
02331 eh_free( this_link->data );
02332
02333 g_list_free( river );
02334
02335 return ans;
02336 }
02337
02338 Eh_ind_2 get_offset_from_angle( double angle , double aspect )
02339 {
02340 double shift_x, shift_y;
02341 double angle_diag = atan( aspect );
02342
02343 eh_require( aspect>0 );
02344
02345 if ( fabs(sin( angle )) - fabs(sin( angle_diag )) > -1e-5 )
02346 shift_y = (sin(angle)>0)?1:-1;
02347 else
02348 shift_y = 0;
02349
02350 if ( fabs(cos( angle )) - fabs(cos( angle_diag )) > -1e-5 )
02351 shift_x = (cos(angle)>0)?1:-1;
02352 else
02353 shift_x = 0;
02354
02355 eh_require( shift_x || shift_y );
02356
02357 return eh_ind_2_create( shift_x , shift_y );
02358 }
02359
02360 int get_path_exit_side( Eh_pt_2 pos_in_box , double angle , double dx , double dy )
02361 {
02362 int i;
02363 Eh_pt_2 corner_pos[4] = { {0,0} , {1,0} , {1,1} , {0,1} };
02364 double angle_to_corner=-M_PI;
02365 double rise, run;
02366
02367 eh_require( angle>=-M_PI );
02368 eh_require( angle<= M_PI );
02369
02370 for ( i=0 ; i<4 && angle_to_corner<angle ; i++ )
02371 {
02372 rise = corner_pos[i].y*dy - pos_in_box.y;
02373 run = corner_pos[i].x*dx - pos_in_box.x;
02374
02375 if ( rise==0 && run<0 )
02376 angle_to_corner = (i==0)?-M_PI:M_PI;
02377 else
02378 angle_to_corner = atan2( rise , run );
02379 }
02380
02381 if ( angle_to_corner<angle )
02382 i = 0;
02383 else
02384 i--;
02385
02386 return i;
02387 }
02388
02389 Eh_pt_2 get_path_exit_pos( Eh_pt_2 pos_in_box ,
02390 double angle ,
02391 double dx ,
02392 double dy )
02393 {
02394 int side;
02395 Eh_pt_2 exit_pos;
02396
02397 side = get_path_exit_side( pos_in_box , angle , dx , dy );
02398
02399 if ( side == 0 || side == 2 )
02400 {
02401 exit_pos.x = (side==0)?0:dx;
02402 if ( side==0 )
02403 exit_pos.y = -tan( angle )*pos_in_box.x+pos_in_box.y;
02404 else
02405 exit_pos.y = tan( angle )*(dx-pos_in_box.x)+pos_in_box.y;
02406 }
02407 else
02408 {
02409 if ( side==1 )
02410 exit_pos.x = -pos_in_box.y/tan( angle )+pos_in_box.x;
02411 else
02412 exit_pos.x = (dy-pos_in_box.y)/tan( angle )+pos_in_box.x;
02413 exit_pos.y = (side==1)?0:dy;
02414 }
02415
02416
02417
02418
02419
02420 return exit_pos;
02421 }
02422
02423 Eh_pt_2 get_path_entrance_pos( Eh_pt_2 exit_pos , double dx , double dy )
02424 {
02425 Eh_pt_2 entrance_pos = exit_pos;
02426
02427 if ( eh_compare_dbl( exit_pos.x , 0. , 1e-12 ) )
02428 entrance_pos.x = dx;
02429 else if ( eh_compare_dbl( exit_pos.x , dx , 1e-12 ) )
02430 entrance_pos.x = 0;
02431
02432 if ( eh_compare_dbl( exit_pos.y , 0. , 1e-12 ) )
02433 entrance_pos.y = dy;
02434 else if ( eh_compare_dbl( exit_pos.y , dy , 1e-12 ) )
02435 entrance_pos.y = 0;
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448 return entrance_pos;
02449 }
02450
02451 Eh_ind_2 get_shift_from_exit_pos( Eh_pt_2 exit_pos , double dx , double dy )
02452 {
02453 Eh_ind_2 shift = { 0 , 0 };
02454
02455 if ( eh_compare_dbl( exit_pos.x , 0. , 1e-12 ) )
02456 shift.i = -1;
02457 else if ( eh_compare_dbl( exit_pos.x , dx , 1e-12 ) )
02458 shift.i = 1;
02459
02460 if ( eh_compare_dbl( exit_pos.y , 0. , 1e-12 ) )
02461 shift.j = -1;
02462 else if ( eh_compare_dbl( exit_pos.y , dy , 1e-12 ) )
02463 shift.j = 1;
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476 return shift;
02477 }
02478
02479 gssize*
02480 sed_cube_river_path_id( Sed_cube c ,
02481 Sed_riv river ,
02482 gboolean down_stream )
02483 {
02484 gssize *path_id = NULL;
02485
02486 eh_require( c );
02487 eh_require( river );
02488
02489 if ( c && river )
02490 {
02491 Eh_ind_2 hinge = sed_river_hinge( river );
02492 double angle = sed_river_angle( river );
02493 GList* path;
02494
02495 path = sed_cube_find_line_path( c , &hinge , angle );
02496
02497 eh_require( path );
02498
02499 if ( path )
02500 {
02501 gint i;
02502 gint n_y = g_list_length( path );
02503 GList* this_link;
02504
02505 path_id = eh_new( gssize , n_y+1 );
02506
02507 if ( down_stream ) path = g_list_reverse( path );
02508
02509 for ( i=0,this_link=path ; this_link ; this_link=this_link->next,i++ )
02510 {
02511 path_id[i] = eh_grid_sub_to_id( c->n_y ,
02512 ((Eh_ind_2*)(this_link->data))->i ,
02513 ((Eh_ind_2*)(this_link->data))->j );
02514 eh_free( this_link->data );
02515 }
02516 path_id[n_y] = -1;
02517
02518 g_list_free( path );
02519 }
02520 }
02521
02522 return path_id;
02523 }
02524
02525 GList*
02526 sed_cube_river_path( Sed_cube c , Sed_riv river )
02527 {
02528 Eh_ind_2 hinge = sed_river_hinge( river );
02529 double angle = sed_river_angle( river );
02530
02531 return sed_cube_find_line_path( c , &hinge , angle );
02532 }
02533
02534 GList*
02535 sed_cube_find_line_path( Sed_cube c ,
02536 Eh_ind_2 *hinge_pos ,
02537 double angle )
02538 {
02539 GList *river_path=NULL;
02540 int n, i, j;
02541 int max_iter;
02542 Eh_ind_2 river_pos;
02543 Eh_ind_2 shift;
02544 Eh_pt_2 pos_in_cell;
02545
02546 angle = eh_reduce_angle( angle );
02547
02548 pos_in_cell.x = .5*c->dx;
02549 pos_in_cell.y = .5*c->dy;
02550
02551 eh_require( c );
02552 eh_require( hinge_pos );
02553 eh_require( eh_is_in_domain( c->n_x , c->n_y , hinge_pos->i , hinge_pos->j ) );
02554
02555 i = hinge_pos->i;
02556 j = hinge_pos->j;
02557
02558 river_path = g_list_prepend( river_path , eh_ind_2_dup( hinge_pos , NULL ) );
02559
02560 if ( sed_column_is_below( c->col[i][j] , c->sea_level ) )
02561 return river_path;
02562
02563 max_iter = c->n_x*c->n_y+1;
02564
02565 for ( n=0 ;
02566 eh_is_in_domain( c->n_x , c->n_y , i , j )
02567 && sed_column_is_above( c->col[i][j] , c->sea_level-1e-3 )
02568 && n<max_iter ;
02569 n++ )
02570 {
02571 pos_in_cell = get_path_exit_pos ( pos_in_cell , angle , c->dx , c->dy );
02572
02573 shift = get_shift_from_exit_pos( pos_in_cell , c->dx , c->dy );
02574 pos_in_cell = get_path_entrance_pos ( pos_in_cell , c->dx , c->dy );
02575
02576 i += shift.i;
02577 j += shift.j;
02578
02579 if ( eh_is_in_domain( c->n_x , c->n_y , i , j ) )
02580 {
02581 river_pos = eh_ind_2_create( i , j );
02582
02583 river_path = g_list_prepend( river_path ,
02584 eh_ind_2_dup( &river_pos , NULL ) );
02585 }
02586 }
02587
02588 if ( n==max_iter )
02589 eh_require_not_reached();
02590
02591 return river_path;
02592 }
02593
02594 int is_river_mouth( Eh_ind_2 *shore_pos , Sed_hinge_pt* dir )
02595 {
02596 int river_x, river_y;
02597 double hinge_ang = dir->angle;
02598 int hinge_x = dir->x;
02599 int hinge_y = dir->y;
02600
02601 river_y = shore_pos->j;
02602
02603 river_x = hinge_x + (river_y - hinge_y) / tan( hinge_ang );
02604
02605 if ( river_x<shore_pos->i )
02606 return -1;
02607 else if ( river_x>shore_pos->i )
02608 return 1;
02609 else
02610 return 0;
02611 }
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711 Eh_dbl_grid
02712 sed_get_floor_3_default( int floor_type , int n_x , int n_y )
02713 {
02714 int i, j;
02715 int dy = 100;
02716 double m = .02;
02717 Eh_dbl_grid grid;
02718
02719 if ( n_x <= 0 )
02720 n_x = 100;
02721 if ( n_y <= 0 )
02722 n_y = 100;
02723
02724 grid = eh_grid_new( double , n_x , n_y );
02725
02726 switch ( floor_type )
02727 {
02728 case 1:
02729 for ( i=0 ; i<n_x ; i++ )
02730 for ( j=0 ; j<n_y ; j++ )
02731 eh_dbl_grid_set_val( grid , i , j , -m*j*dy );
02732 break;
02733 case 2:
02734 for ( i=0 ; i<n_x ; i++ )
02735 for ( j=0 ; j<n_y ; j++ )
02736 if ( j<n_y/2 )
02737 eh_dbl_grid_set_val( grid , i , j , -m*j*dy );
02738 else
02739 eh_dbl_grid_set_val( grid , i , j , -2*m*j*dy );
02740 break;
02741 default:
02742 for ( i=0 ; i<n_x ; i++ )
02743 for ( j=0 ; j<n_y ; j++ )
02744 eh_dbl_grid_set_val( grid , i , j , -1 );
02745 break;
02746 }
02747
02748 return grid;
02749 }
02750
02751 double**
02752 sed_scan_sea_level_curve( const char* file , gint* len , GError** err )
02753 {
02754 double** data = NULL;
02755
02756 eh_return_val_if_fail( file , NULL );
02757 eh_return_val_if_fail( len , NULL );
02758
02759 eh_return_val_if_fail( err==NULL || *err==NULL , NULL );
02760
02761 eh_debug( "Scan the sea-level file" );
02762 {
02763 GError* tmp_err = NULL;
02764 gint n_rows;
02765
02766 data = eh_dlm_read_swap( file , ";," , &n_rows , len , &tmp_err );
02767
02768 if ( tmp_err )
02769 g_propagate_error( err , tmp_err );
02770 else if ( n_rows!=2 )
02771 g_set_error( &tmp_err ,
02772 SED_CUBE_ERROR ,
02773 SED_CUBE_ERROR_NOT_TWO_COLUMNS ,
02774 "%s: Sea-level curve does not contain 2 columns (found %d)\n" ,
02775 file , n_rows );
02776 else if ( *len<2 )
02777 g_set_error( &tmp_err ,
02778 SED_CUBE_ERROR ,
02779 SED_CUBE_ERROR_INSUFFICIENT_DATA ,
02780 "%s: Sea-level curve contains only one data point\n" ,
02781 file );
02782 else if ( !eh_dbl_array_is_monotonic_up( data[0] , *len ) )
02783 g_set_error( &tmp_err ,
02784 SED_CUBE_ERROR ,
02785 SED_CUBE_ERROR_TIME_NOT_MONOTONIC ,
02786 "%s: The time data must be monotonically increasing.\n" ,
02787 file );
02788 else if ( data[0][0]>0 )
02789 g_set_error( &tmp_err ,
02790 SED_CUBE_ERROR ,
02791 SED_CUBE_ERROR_DATA_BAD_RANGE ,
02792 "%s: Insufficient range in time data.\n" ,
02793 file );
02794
02795 if ( tmp_err!=NULL )
02796 {
02797 g_propagate_error( err , tmp_err );
02798
02799 eh_free_2( data );
02800 data = NULL;
02801 }
02802
02803 }
02804
02805 return data;
02806 }
02807
02808 #define S_KEY_SUBSIDENCE_TIME "time"
02809
02810 Eh_sequence *sed_get_floor_sequence_2( const char *file ,
02811 double *y_i ,
02812 gssize n_yi ,
02813 GError** error )
02814 {
02815 Eh_sequence* grid_seq = NULL;
02816 gint* n_rows = NULL;
02817 gint* n_cols = NULL;
02818 gchar** data = NULL;
02819 GError* err = NULL;
02820 double*** all_records;
02821
02822 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
02823
02824 all_records = eh_dlm_read_full_swap( file , "," , &n_rows , &n_cols ,
02825 &data , -1 , &err );
02826
02827 if ( all_records )
02828 {
02829 gint i;
02830 Eh_symbol_table tab;
02831 gint n_recs = g_strv_length( (gchar**)all_records );
02832 double* t = eh_new( double , n_recs );
02833
02834
02835 for ( i=0 ; i<n_recs && err==NULL ; i++ )
02836 {
02837 tab = eh_str_parse_key_value( data[i] , ":" , "\n" );
02838
02839 if ( tab && eh_symbol_table_has_label( tab , S_KEY_SUBSIDENCE_TIME ) )
02840 t[i] = eh_symbol_table_dbl_value( tab , S_KEY_SUBSIDENCE_TIME );
02841 else
02842 {
02843 g_set_error( &err ,
02844 SED_CUBE_ERROR ,
02845 SED_CUBE_ERROR_NO_TIME_LABEL ,
02846 "Time label not found "
02847 "for record %d in %s" , i+1 , file );
02848 }
02849
02850 tab = eh_symbol_table_destroy( tab );
02851 }
02852
02853
02854 if ( err==NULL && !eh_dbl_array_is_monotonic_up(t,n_recs ) )
02855 {
02856 g_set_error( &err ,
02857 SED_CUBE_ERROR ,
02858 SED_CUBE_ERROR_TIME_NOT_MONOTONIC ,
02859 "%s: The grid sequence must be monotonically increasing.\n" ,
02860 file );
02861 }
02862
02863 for ( i=0 ; i<n_recs && err==NULL ; i++ )
02864 {
02865
02866 if ( n_rows[i]!=2 )
02867 {
02868 g_set_error( &err ,
02869 SED_CUBE_ERROR ,
02870 SED_CUBE_ERROR_NOT_TWO_COLUMNS ,
02871 "%s: Record number %d does not contain 2 columns (found %d)\n" ,
02872 file , i+1 , n_rows[i] );
02873 }
02874
02875 else if ( n_cols[i]<2 )
02876 {
02877 g_set_error( &err ,
02878 SED_CUBE_ERROR ,
02879 SED_CUBE_ERROR_INSUFFICIENT_DATA ,
02880 "%s: Record number %d contains only one data point\n" ,
02881 file , i+1 );
02882 }
02883 }
02884
02885
02886 if ( err==NULL )
02887 {
02888 Eh_dbl_grid this_grid;
02889 double* y;
02890 double* z;
02891
02892 grid_seq = eh_create_sequence( );
02893
02894 for ( i=0 ; i<n_recs && err==NULL ; i++ )
02895 {
02896 y = (all_records[i])[0];
02897 z = (all_records[i])[1];
02898
02899 if ( !eh_dbl_array_is_monotonic_up(y,n_cols[i] ) )
02900 g_set_error( &err ,
02901 SED_CUBE_ERROR ,
02902 SED_CUBE_ERROR_DATA_NOT_MONOTONIC ,
02903 "%s (record %d): Position data not monotonically increasing.\n" ,
02904 file , i+1 );
02905 else if ( y[0]>y_i[0] || y[n_cols[i]-1]<y_i[n_yi-1] )
02906 g_set_error( &err ,
02907 SED_CUBE_ERROR ,
02908 SED_CUBE_ERROR_DATA_BAD_RANGE ,
02909 "%s (record %d): Insufficient range in position data.\n" ,
02910 file , i+1 );
02911 else
02912 {
02913 this_grid = eh_grid_new( double , 1 , n_yi );
02914 g_memmove( eh_grid_y(this_grid) , y_i , n_yi*sizeof(double) );
02915
02916 interpolate( y , z , n_cols[i] ,
02917 eh_grid_y(this_grid) , eh_grid_data_start(this_grid) , eh_grid_n_y(this_grid) );
02918
02919 eh_add_to_sequence( grid_seq , t[i] , this_grid );
02920 }
02921 }
02922 }
02923
02924 eh_free( t );
02925
02926 for ( i=0 ; i<n_recs ; i++ )
02927 eh_free_2( all_records[i] );
02928 }
02929
02930 if ( err!=NULL )
02931 g_propagate_error( error , err );
02932
02933 g_strfreev( data );
02934 eh_free( n_rows );
02935 eh_free( n_cols );
02936 eh_free( all_records );
02937
02938 return grid_seq;
02939 }
02940
02941 Eh_sequence *sed_get_floor_sequence_3( const char *file ,
02942 double dx ,
02943 double dy ,
02944 GError** error )
02945 {
02946 Eh_dbl_grid grid = NULL;
02947 Eh_sequence* grid_seq = NULL;
02948 FILE *fp;
02949 int i, n, n_elem;
02950 size_t start, end;
02951 gint n_x, n_y, n_t;
02952 double t;
02953 GError* tmp_err = NULL;
02954 gboolean is_wrong_byte_order = FALSE;
02955
02956 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
02957
02958
02959
02960
02961 fp = eh_fopen_error( file , "rb" , &tmp_err );
02962
02963 if ( !tmp_err )
02964 {
02965
02966
02967
02968
02969 fread( &n_y , sizeof(gint32) , 1 , fp );
02970 fread( &n_x , sizeof(gint32) , 1 , fp );
02971
02972
02973
02974
02975 if ( n_x<=0 || n_y<=0 || n_x>10000000 || n_y>10000000 )
02976 {
02977 rewind( fp );
02978
02979 eh_fread_int32_swap( &n_y , sizeof(gint32) , 1 , fp );
02980 eh_fread_int32_swap( &n_x , sizeof(gint32) , 1 , fp );
02981
02982 is_wrong_byte_order = TRUE;
02983 }
02984
02985 if ( n_x<=0 || n_y<=0 )
02986 {
02987 g_set_error( &tmp_err ,
02988 SED_CUBE_ERROR ,
02989 SED_CUBE_ERROR_BAD_GRID_DIMENSION ,
02990 "Bad grid dimension (n_x=%d, n_y=%d)" , n_x , n_y );
02991 }
02992 }
02993
02994 if ( !tmp_err )
02995 {
02996
02997
02998
02999
03000 start = ftell( fp );
03001 fseek( fp , 0 , SEEK_END );
03002 end = ftell( fp );
03003 fseek( fp , start , SEEK_SET );
03004
03005 n_elem = (end-start)/sizeof(double);
03006 n_t = n_elem/(n_x*n_y+1);
03007
03008 if ( (n_x*n_y+1)*n_t != n_elem )
03009 {
03010 g_set_error( &tmp_err ,
03011 SED_CUBE_ERROR ,
03012 SED_CUBE_ERROR_TRUNCATED_FILE ,
03013 "Sequence file is truncated (%d complete records found)", n_t );
03014 }
03015 }
03016
03017 if ( !tmp_err )
03018 {
03019
03020
03021
03022
03023
03024
03025 grid_seq = eh_create_sequence( );
03026
03027 for ( n=0 ; n<n_t ; n++ )
03028 {
03029 if ( is_wrong_byte_order ) eh_fread_dbl_swap( &t , sizeof(double) , 1 , fp );
03030 else fread ( &t , sizeof(double) , 1 , fp );
03031
03032 grid = eh_grid_new( double , n_x , n_y );
03033
03034 if ( is_wrong_byte_order ) eh_fread_dbl_swap( eh_grid_data_start(grid) , sizeof(double) , n_x*n_y , fp );
03035 else fread ( eh_grid_data_start(grid) , sizeof(double) , n_x*n_y , fp );
03036
03037 for ( i=0 ; i<n_x ; i++ )
03038 eh_grid_x(grid)[i] = i*dx;
03039
03040 for ( i=0 ; i<n_y ; i++ )
03041 eh_grid_y(grid)[i] = i*dy;
03042
03043 eh_add_to_sequence( grid_seq , t , grid );
03044 }
03045
03046
03047
03048
03049 for ( n=1 ; n<grid_seq->len && !tmp_err ; n++ )
03050 {
03051 if ( !(grid_seq->t[n-1] < grid_seq->t[n]) )
03052 {
03053 g_set_error( &tmp_err ,
03054 SED_CUBE_ERROR ,
03055 SED_CUBE_ERROR_TIME_NOT_MONOTONIC ,
03056 "Grid sequence not monotonically increasing (t[%d]=%f, t[%d]=%f)\n" ,
03057 n-1 , grid_seq->t[n-1], n , grid_seq->t[n] );
03058 }
03059 }
03060 }
03061
03062 if ( tmp_err )
03063 {
03064 if ( grid_seq )
03065 {
03066 for ( i=0 ; i<grid_seq->len ; i++ )
03067 eh_grid_destroy( grid_seq->data[i] , TRUE );
03068 eh_destroy_sequence( grid_seq , FALSE );
03069 grid_seq = NULL;
03070 }
03071 g_propagate_error( error , tmp_err );
03072 }
03073
03074 fclose( fp );
03075
03076 return grid_seq;
03077 }
03078
03079 Eh_dbl_grid
03080 sed_bathy_grid_scan( const char* file , double dx , double dy , GError** error )
03081 {
03082 Eh_dbl_grid g = NULL;
03083
03084 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
03085
03086 if ( sed_mode_is_2d() )
03087 g = sed_bathy_grid_scan_1d_ascii( file , dx , dy , error );
03088 else if ( sed_mode_is_3d() )
03089 g = sed_bathy_grid_scan_2d_ascii( file , dx , dy , error );
03090 else
03091 eh_require_not_reached();
03092
03093 return g;
03094 }
03095
03096 Eh_dbl_grid
03097 sed_bathy_grid_scan_2d_ascii( const char *file , double dx , double dy , GError** error )
03098 {
03099 gint n_rows = 0;
03100 gint n_cols = 0;
03101 double** z = NULL;
03102 GError* tmp_err = NULL;
03103 Eh_dbl_grid grid = NULL;
03104
03105 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
03106
03107 z = eh_dlm_read( file , ",;" , &n_rows , &n_cols , &tmp_err );
03108
03109 if ( z )
03110 {
03111
03112 if ( n_rows<2 )
03113 g_set_error( &tmp_err ,
03114 SED_CUBE_ERROR ,
03115 SED_CUBE_ERROR_TOO_FEW_ROWS ,
03116 "%s: sedflux-3d bathymetry needs more than 1 row\n" ,
03117 file );
03118 else if ( n_cols<3 )
03119 g_set_error( &tmp_err ,
03120 SED_CUBE_ERROR ,
03121 SED_CUBE_ERROR_TOO_FEW_COLUMNS ,
03122 "%s: sedflux-3d bathymetry needs more than 2 columns\n" ,
03123 file );
03124 else
03125 {
03126 gint i;
03127
03128 grid = eh_dbl_grid_new_set( n_rows , n_cols , z );
03129
03130 for ( i=0 ; i<n_rows ; i++ )
03131 eh_grid_x(grid)[i] = i*dx;
03132 for ( i=0 ; i<n_cols ; i++ )
03133 eh_grid_y(grid)[i] = i*dy;
03134 }
03135 }
03136
03137 if ( tmp_err )
03138 {
03139 grid = eh_grid_destroy( grid , TRUE );
03140 g_propagate_error( error , tmp_err );
03141 }
03142
03143 return grid;
03144 }
03145
03146 Eh_dbl_grid
03147 sed_bathy_grid_scan_2d_binary( const char *file , double dx , double dy , GError** error )
03148 {
03149 Eh_dbl_grid grid = NULL;
03150 GError* tmp_err = NULL;
03151 FILE* fp;
03152
03153 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
03154
03155
03156
03157
03158 fp = eh_fopen_error( file , "rb" , &tmp_err );
03159
03160 if ( fp )
03161 {
03162 gint32 n_x, n_y;
03163 gint n_elem;
03164 size_t start, end;
03165
03166
03167
03168
03169 fread( &n_y , sizeof(gint32) , 1 , fp );
03170
03171
03172
03173
03174
03175 start = ftell( fp );
03176 fseek( fp , 0 , SEEK_END );
03177 end = ftell( fp );
03178 fseek( fp , start , SEEK_SET );
03179
03180 n_elem = (end-start)/sizeof(double);
03181 n_x = n_elem/n_y;
03182
03183 if ( n_x*n_y != n_elem )
03184 {
03185 g_set_error( &tmp_err ,
03186 SED_CUBE_ERROR ,
03187 SED_CUBE_ERROR_TRUNCATED_FILE ,
03188 "Bathymetry file is truncated: found %d values but expeced %d values (%d*%d)" ,
03189 n_elem , n_x*n_y , n_x , n_y );
03190 }
03191 else
03192 {
03193 gint i;
03194
03195
03196
03197 grid = eh_grid_new( double , n_x , n_y );
03198
03199 fread( eh_grid_data_start(grid) , sizeof(double) , n_x*n_y , fp );
03200
03201 for ( i=0 ; i<n_x ; i++ )
03202 eh_grid_x(grid)[i] = i*dx;
03203
03204 for ( i=0 ; i<n_y ; i++ )
03205 eh_grid_y(grid)[i] = i*dy;
03206 }
03207
03208 fclose( fp );
03209 }
03210
03211 if ( tmp_err )
03212 g_propagate_error( error , tmp_err );
03213
03214
03215
03216 return grid;
03217 }
03218
03219 Eh_dbl_grid
03220 sed_bathy_grid_scan_1d_ascii( const char *file , double dx , double dy , GError** error )
03221 {
03222 Eh_dbl_grid grid = NULL;
03223
03224 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
03225
03226
03227
03228
03229
03230 eh_debug( "Scan the bathymetry file" );
03231 {
03232 double** data;
03233 GError* tmp_err = NULL;
03234 gint n_rows, n_cols;
03235
03236 data = eh_dlm_read_swap( file , ";," , &n_rows , &n_cols , &tmp_err );
03237
03238 if ( tmp_err )
03239 g_propagate_error( error , tmp_err );
03240 else if ( n_rows!=2 )
03241 g_set_error( &tmp_err ,
03242 SED_CUBE_ERROR ,
03243 SED_CUBE_ERROR_NOT_TWO_COLUMNS ,
03244 "%s: Bathymetry file does not contain 2 columns (found %d)\n" ,
03245 file , n_rows );
03246 else if ( n_cols<2 )
03247 g_set_error( &tmp_err ,
03248 SED_CUBE_ERROR ,
03249 SED_CUBE_ERROR_INSUFFICIENT_DATA ,
03250 "%s: Bathymetry file contains only one data point\n" ,
03251 file );
03252 else if ( !eh_dbl_array_is_monotonic_up( data[0] , n_cols ) )
03253 g_set_error( &tmp_err ,
03254 SED_CUBE_ERROR ,
03255 SED_CUBE_ERROR_TIME_NOT_MONOTONIC ,
03256 "%s: The position data must be monotonically increasing.\n" ,
03257 file );
03258 else if ( data[0][0]>0 )
03259 g_set_error( &tmp_err ,
03260 SED_CUBE_ERROR ,
03261 SED_CUBE_ERROR_DATA_BAD_RANGE ,
03262 "%s: Insufficient range in position data.\n" ,
03263 file );
03264 else
03265 {
03266 double *y, *z;
03267 gint n;
03268
03269
03270
03271
03272
03273
03274 y = data[0];
03275 z = data[1];
03276 n = n_cols;
03277
03278
03279
03280
03281 eh_debug( "Interpolate to a uniform grid" );
03282 {
03283 gssize n_y = (y[n-1]-y[0]) / dy;
03284 grid = eh_grid_new( double , 1 , n_y );
03285
03286 eh_grid_set_y_lin( grid , y[0] , dy );
03287
03288 interpolate( y , z , n , eh_grid_y(grid) , eh_grid_data_start(grid) , n_y );
03289 }
03290
03291 }
03292
03293 eh_free_2( data );
03294
03295 if ( tmp_err!=NULL )
03296 g_propagate_error( error , tmp_err );
03297 }
03298
03299 return grid;
03300 }
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331 Sed_cube
03332 sed_cube_foreach_river( Sed_cube c , GFunc func , gpointer user_data )
03333 {
03334 g_list_foreach( c->river , func , user_data );
03335 return c;
03336 }
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353 void find_river_mouth_helper( Sed_riv this_river , Sed_cube c );
03354
03355 Sed_cube sed_cube_find_all_river_mouths( Sed_cube c )
03356 {
03357 g_list_foreach( c->river , (GFunc)&find_river_mouth_helper , c );
03358 return c;
03359 }
03360
03361 void find_river_mouth_helper( Sed_riv this_river , Sed_cube c )
03362 {
03363 sed_cube_find_river_mouth( c , this_river );
03364 }
03365
03374 gssize sed_cube_write( FILE *fp , const Sed_cube p )
03375 {
03376 gssize n = 0;
03377
03378 if ( p && fp )
03379 {
03380 gssize i;
03381 gssize len = sed_cube_size(p);
03382
03383
03384 n += fwrite( &(p->age) , sizeof(double) , 1 , fp );
03385 n += fwrite( &(p->time_step) , sizeof(double) , 1 , fp );
03386 n += fwrite( &(p->storm_value) , sizeof(double) , 1 , fp );
03387 n += fwrite( &(p->quake_value) , sizeof(double) , 1 , fp );
03388 n += fwrite( &(p->tidal_range) , sizeof(double) , 1 , fp );
03389 n += fwrite( &(p->tidal_period) , sizeof(double) , 1 , fp );
03390 n += fwrite( &(p->n_x) , sizeof(gint) , 1 , fp );
03391 n += fwrite( &(p->n_y) , sizeof(gint) , 1 , fp );
03392 n += fwrite( &(p->basinWidth) , sizeof(double) , 1 , fp );
03393 n += fwrite( &(p->dx) , sizeof(double) , 1 , fp );
03394 n += fwrite( &(p->dy) , sizeof(double) , 1 , fp );
03395 n += fwrite( &(p->sea_level) , sizeof(double) , 1 , fp );
03396 n += fwrite( &(p->cell_height) , sizeof(double) , 1 , fp );
03397
03398
03399
03400
03401 len = strlen( p->name );
03402 n += fwrite( &len , sizeof(gssize) , 1 , fp );
03403 n += fwrite( p->name , sizeof(char) , len , fp );
03404 n += fwrite( p->wave , sizeof(double) , 3 , fp );
03405
03406 for ( i=0 ; i<len ; i++ )
03407 n += sed_column_write( fp , p->col[0][i] );
03408
03409 n += sed_cell_write( fp , p->erode );
03410 n += sed_cell_write( fp , p->remove );
03411
03412 len = sed_cube_n_branches( p );
03413 n += fwrite( &len , sizeof(gssize) , 1 , fp );
03414
03415
03416 {
03417 Sed_riv* all = sed_cube_all_branches( p );
03418 Sed_riv* r;
03419
03420 if ( all )
03421 {
03422 for ( r=all ; *r ; r++ )
03423 {
03424 sed_river_fwrite( fp , *r );
03425 eh_grid_dump ( fp , sed_river_get_susp_grid(*r) );
03426 }
03427
03428 eh_free( all );
03429 }
03430
03431 }
03432 }
03433
03434 return n;
03435 }
03436
03443 Sed_cube sed_cube_read( FILE *fp )
03444 {
03445 Sed_cube p = NULL;
03446
03447 eh_require( fp )
03448 {
03449 gint i, j;
03450 gint len;
03451 Sed_riv r;
03452 Eh_grid g;
03453
03454
03455
03456
03457 NEW_OBJECT( Sed_cube , p );
03458 fread( p , sizeof(*p) , 1 , fp );
03459
03460
03461
03462
03463 fread( &len , sizeof(gssize) , 1 , fp );
03464 fread( p->name , sizeof(char) , len , fp );
03465 fread( p->wave , sizeof(double) , 3 , fp );
03466
03467 p->col = eh_new( Sed_column* , p->n_x );
03468 p->col[0] = eh_new( Sed_column , p->n_x*p->n_y );
03469 for ( i=1 ; i<p->n_x ; i++ )
03470 p->col[i] = p->col[i-1]+p->n_y;
03471 for ( i=0 ; i<p->n_x ; i++ )
03472 for ( j=0 ; j<p->n_y ; j++ )
03473 p->col[i][j] = sed_column_read( fp );
03474
03475 p->erode = sed_cell_read( fp );
03476 p->remove = sed_cell_read( fp );
03477
03478
03479 fread( &len , sizeof(int) , 1 , fp );
03480 for ( i=0 ; i<len ; i++ )
03481 {
03482 r = sed_river_new( NULL );
03483 sed_river_fread( fp , r );
03484 sed_cube_add_trunk( p , r );
03485
03486 g = eh_grid_load( fp );
03487 eh_grid_copy( sed_river_get_susp_grid(r) , g );
03488 eh_grid_destroy( g , TRUE );
03489 }
03490
03491 sed_cube_set_shore( p );
03492 }
03493
03494 return p;
03495 }
03496
03497 gssize
03498 sed_cube_column_id( const Sed_cube c , double x , double y )
03499 {
03500 gssize id = -1;
03501
03502 eh_require( c );
03503
03504 if ( c && sed_cube_is_in_domain_pos(c,x,y) )
03505 {
03506 gint i, j;
03507 gint row_ind = 0;
03508 gint col_ind = 0;
03509
03510 for ( j=0 ; j<c->n_y && sed_column_y_position( c->col[0][j] ) <= y ; j++ );
03511 col_ind = (j==0)?0:j-1;
03512
03513 if ( !sed_cube_is_1d(c) )
03514 {
03515 for ( i=0 ; i<c->n_x && sed_column_x_position( c->col[i][col_ind] ) <= x ; i++ );
03516 row_ind = (i==0)?0:i-1;
03517 }
03518
03519 id = eh_grid_sub_to_id( c->n_y , row_ind , col_ind );
03520 }
03521
03522 return id;
03523 }
03524
03525 gssize *sed_cube_find_column_below( Sed_cube c , double z )
03526 {
03527 gssize i, j, n;
03528 gssize *col_id;
03529
03530 col_id = NULL;
03531 for ( i=0,n=0 ; i<c->n_x ; i++ )
03532 for ( j=0 ; j<c->n_y ; j++ )
03533 if ( sed_column_top_height(c->col[i][j]) < z )
03534 {
03535 col_id = g_renew( gssize , col_id , ++n );
03536 col_id[n-1] = eh_grid_sub_to_id(c->n_y,i,j);
03537 }
03538 col_id = g_renew( gssize , col_id , ++n );
03539 col_id[n-1] = -1;
03540
03541 return col_id;
03542 }
03543
03544 gssize *sed_cube_find_column_above( Sed_cube c , double z )
03545 {
03546 gssize i, j, n;
03547 gssize *col_id;
03548
03549 col_id = NULL;
03550 for ( i=0,n=0 ; i<c->n_x ; i++ )
03551 for ( j=0 ; j<c->n_y ; j++ )
03552 {
03553 if ( sed_column_top_height(c->col[i][j]) > z )
03554 {
03555 col_id = g_renew( gssize , col_id , ++n );
03556 col_id[n-1] = eh_grid_sub_to_id(c->n_y,i,j);
03557 }
03558 }
03559 col_id = g_renew( gssize , col_id , ++n );
03560 col_id[n-1] = -1;
03561
03562 return col_id;
03563 }
03579 int
03580 sed_get_floor_vec(char *filename, double *y, int len, double *z , GError** error )
03581 {
03582 gssize new_len = 0;
03583
03584 eh_return_val_if_fail( error==NULL || *error==NULL , 0 );
03585
03586 eh_require( filename );
03587 eh_require( y );
03588 eh_require( z );
03589 eh_require( len>0 );
03590
03591 {
03592 GError* tmp_err = NULL;
03593 gssize i;
03594 GArray *y_array = g_array_new( FALSE , FALSE , sizeof(double) );
03595 GArray *z_array;
03596
03597
03598
03599
03600 for ( i=0 ; i<len ; i++ )
03601 g_array_append_val( y_array , y[i] );
03602
03603
03604
03605
03606 z_array = sed_get_floor( filename , y_array , &tmp_err );
03607
03608 if ( z_array )
03609 {
03610 new_len = z_array->len;
03611
03612
03613
03614
03615 for ( i=0 ; i<new_len ; i++ )
03616 {
03617 z[i] = g_array_index( z_array , double , i );
03618 y[i] = g_array_index( y_array , double , i );
03619 }
03620 }
03621 else
03622 g_propagate_error( error , tmp_err );
03623
03624 g_array_free( y_array , TRUE );
03625 g_array_free( z_array , TRUE );
03626 }
03627
03628 return new_len;
03629 }
03630
03645 GArray*
03646 sed_get_floor( char *file , GArray *y_array , GError** error )
03647 {
03648 GArray* z_array = NULL;
03649 Eh_data_record floor_data = NULL;
03650
03651 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
03652
03653
03654
03655
03656
03657 {
03658 gssize i;
03659 Eh_data_record* all_data = NULL;
03660 GError* tmp_err = NULL;
03661
03662 all_data = eh_data_record_scan_file( file , "," , EH_FAST_DIM_COL , FALSE , &tmp_err );
03663
03664 if ( all_data )
03665 {
03666 floor_data = all_data[0];
03667 for ( i=1 ; all_data[i] ; i++ )
03668 eh_data_record_destroy( all_data[i] );
03669 eh_free( all_data );
03670 }
03671 else
03672 g_propagate_error( error , tmp_err );
03673 }
03674
03675 if ( floor_data )
03676 {
03677 double *y, *z;
03678 gssize n;
03679
03680 z_array = g_array_new(FALSE,TRUE,sizeof(double));
03681
03682
03683
03684
03685
03686
03687 y = eh_data_record_row ( floor_data , 0 );
03688 z = eh_data_record_row ( floor_data , 1 );
03689 n = eh_data_record_size( floor_data , 1 );
03690
03691
03692
03693
03694 if ( !eh_dbl_array_is_monotonic_up( y , n ) )
03695 eh_error( "The position data must be monotonically increasing." );
03696
03697
03698
03699
03700
03701 {
03702 gssize i;
03703 interpolate( y , z , n , (double*)y_array->data , (double*)z_array->data , y_array->len );
03704 for ( i=0 ; i<y_array->len ; i++ )
03705 {
03706 if ( eh_isnan(g_array_index(z_array,double,i)) )
03707 {
03708 g_array_remove_index( y_array , i );
03709 g_array_remove_index( z_array , i );
03710 }
03711 }
03712 }
03713
03714 eh_data_record_destroy( floor_data );
03715 }
03716
03717 return z_array;
03718 }
03719
03728 gssize sed_cube_id( Sed_cube p , gssize i , gssize j )
03729 {
03730 return eh_grid_sub_to_id( p->n_y , i , j );
03731 }
03732
03740 Eh_ind_2 sed_cube_sub( Sed_cube p , gssize id )
03741 {
03742 return eh_grid_id_to_sub( p->n_y , id );
03743 }
03744
03753 gboolean
03754 sed_cube_is_in_domain( Sed_cube p , gssize i , gssize j )
03755 {
03756 return eh_is_in_domain( p->n_x , p->n_y , i , j );
03757 }
03758
03766 gboolean
03767 sed_cube_is_in_domain_id( Sed_cube p , gssize id )
03768 {
03769 eh_return_val_if_fail( p!=NULL , FALSE );
03770 return id>=0 && id<sed_cube_size(p);
03771 }
03772
03773 gboolean
03774 sed_cube_is_in_domain_pos( Sed_cube c , double x , double y )
03775 {
03776 gboolean is_ok = TRUE;
03777
03778 eh_return_val_if_fail( c!=NULL , FALSE );
03779
03780 if ( y > sed_column_y_position( c->col[0][c->n_y-1] )
03781 || y < sed_column_y_position( c->col[0][0] ) )
03782 is_ok = FALSE;
03783 else if ( !sed_cube_is_1d(c) )
03784 {
03785 if ( x > sed_column_x_position( c->col[c->n_x-1][0] )
03786 || x < sed_column_x_position( c->col[0][0] ) )
03787 is_ok = FALSE;
03788 }
03789
03790 return is_ok;
03791 }
03792
03793 gboolean
03794 sed_cube_is_1d( Sed_cube p )
03795 {
03796 eh_return_val_if_fail( p!=NULL , FALSE );
03797 return p->n_x == 1;
03798 }
03799
03800 gssize
03801 sed_cube_fprint( FILE* fp , Sed_cube c )
03802 {
03803 gssize n = 0;
03804
03805 if ( c )
03806 {
03807 gssize i;
03808 double z;
03809 double min_z = G_MAXDOUBLE;
03810 double max_z = -G_MAXDOUBLE;
03811
03812 n += fprintf( fp , "[Cube Info]\n" );
03813
03814 n += fprintf( fp , "Name = %s\n" , sed_cube_name (c) );
03815
03816 n += fprintf( fp , "x resolution = %f\n" , sed_cube_x_res(c) );
03817 n += fprintf( fp , "y resolution = %f\n" , sed_cube_y_res(c) );
03818 n += fprintf( fp , "z resolution = %f\n" , sed_cube_z_res(c) );
03819
03820 for ( i=0 ; i<sed_cube_size(c) ; i++ )
03821 {
03822 z = sed_cube_base_height(c,0,i);
03823 if ( z < min_z ) min_z = z;
03824 if ( z > max_z ) max_z = z;
03825 }
03826
03827 n += fprintf( fp , "No. x-columns = %d\n" , (gint)sed_cube_n_x(c) );
03828 n += fprintf( fp , "No. y-columns = %d\n" , (gint)sed_cube_n_y(c) );
03829
03830 n += fprintf( fp , "Max elevation = %f\n" , max_z );
03831 n += fprintf( fp , "Min elevation = %f\n" , min_z );
03832
03833 n += fprintf( fp , "Start = %f\n" , sed_cube_col_y( c , 0 ) );
03834 n += fprintf( fp , "End = %f\n" , sed_cube_col_y( c , sed_cube_n_y(c)-1 ) );
03835
03836 }
03837
03838 return n;
03839 }
03840
03841 Sed_cell
03842 sed_cube_to_cell( Sed_cube c , Sed_cell d )
03843 {
03844
03845 if ( c )
03846 {
03847 gint i;
03848 gint len = sed_cube_size(c);
03849 Sed_cell top = sed_cell_new_env();
03850
03851 if ( !d )
03852 d = sed_cell_new_env();
03853
03854 sed_cell_clear( d );
03855
03856 for ( i=0 ; i<len ; i++ )
03857 {
03858 sed_column_top( sed_cube_col(c,i) , sed_cube_thickness(c,0,i) , top );
03859 sed_cell_add( d , top );
03860 }
03861
03862 sed_cell_destroy( top );
03863 }
03864
03865 return d;
03866 }
03867
03875 gint
03876 sed_cube_count_above( Sed_cube c , double h )
03877 {
03878 gint n = 0;
03879
03880 eh_require( c );
03881
03882 if ( c )
03883 {
03884 gint id;
03885 gint len = sed_cube_size(c);
03886 for ( id=0 ; id<len ; id++ )
03887 n += sed_column_is_above( c->col[0][id] , h );
03888 }
03889
03890 return n;
03891 }
03892
03900 double
03901 sed_cube_area_above( Sed_cube c , double h )
03902 {
03903 eh_require( c );
03904
03905 return sed_cube_count_above( c , h )
03906 * sed_cube_x_res(c)
03907 * sed_cube_y_res(c);
03908 }