/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/sed/sed_cube.c

Go to the documentation of this file.
00001 //---
00002 //
00003 // This file is part of sedflux.
00004 //
00005 // sedflux is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // sedflux is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with sedflux; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //
00019 //---
00020 
00021 #include "utils/utils.h"
00022 #include "sed_cube.h"
00023 
00024 CLASS ( Sed_cube )
00025 {
00026    gchar* name; //< The name of the Sed_cube.
00027    double age; //< The age of the Sed_cube.
00028    double time_step; //< The time step.
00029    double storm_value; //< The magnitude of the current storm.
00030    double quake_value; //< The magnitude of the current earthquake.
00031    double tidal_range; //< The tidal range in meters.
00032    double tidal_period; //< The tidal period.
00033    double wave[3]; //< The wave height, period, and length respectively.
00034    GSList *storm_list;
00035 //   GList *in_suspension; //< Array of grids (one for each river) of cells with sediment that is suspended in the water.
00036    Sed_cell erode; //< Sediment that has been eroded.
00037    Sed_cell remove; //< Sediment to be removed from the river
00038    Sed_column **col; //< Array of poiters to columns making up the profile.
00039    int n_x; //< The number of Sed_columns in the x-direction.
00040    int n_y; //< The number of Sed_columns in the y-direction.
00041    double basinWidth; //< The width of the basin.
00042    double dx; //< The spacing of the columns in the x-direction
00043    double dy; //< The spacing of the columns in the y-direction
00044    double sea_level; //< The current height of sea level.
00045    GList *river; //< Information for each of the river mouths.
00046    GList *shore; //< A doubly liked list that defines the shore line.
00047    double cell_height; //< Height of a cell of sediment.
00048    Sed_constants constants; //< The physical constants for the profile (g, rho_w, etc)
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 //   s->in_suspension = NULL;
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       /* Scan the initialization file */
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             /* Scan Sed_cube parameters from key-file */
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       /* Scan in the sediment and set the environment. */
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       /* Scan the bathymetry file */
00222       if ( !tmp_err )
00223       {
00224          Eh_dbl_grid grid = NULL;
00225 
00226          /* Read the bathymetry.  The method depends if the profile is 1 or 2 D. */
00227          grid = sed_bathy_grid_scan( bathy_file , x_res , y_res , &tmp_err );
00228 
00229          if ( grid )
00230          {
00231             /* Create the cube and set positions and elevations. */
00232             gint       i, j;
00233             Sed_column this_col;
00234 
00235             /* Create the cube. */
00236             p = sed_cube_new( eh_grid_n_x(grid) , eh_grid_n_y(grid) );
00237 
00238             /* Set column positions and elevations. */
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             /* Set cube resolutions. */
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             /* Set cube name */
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       /* Free resources */
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 //   dest->in_suspension = src->in_suspension;
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       // in_suspension is twice as large in each dimension than the cube.  the
00375       // indices are adjusted so that (0,0) is the middle of the grid.  thus,
00376       // the grid runs from -n_x -> n_x-1.
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 gint sed_cmp_river_name( Sed_river *this_river , const char *name )
00789 {
00790    if ( this_river->river_name )
00791       return g_ascii_strcasecmp( this_river->river_name , name );
00792    else
00793       return -1;
00794 }
00795 */
00796 /*
00797 Sed_river *sed_cube_river( Sed_cube s , gssize n )
00798 {
00799    eh_return_val_if_fail( s!=NULL , NULL );
00800    return g_list_nth_data( s->river , n );
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 Sed_cell_grid
00818 sed_cube_in_suspension( Sed_cube s , gssize river_no )
00819 {
00820    eh_return_val_if_fail( s!=NULL , NULL );
00821    return g_list_nth_data( s->in_suspension , river_no );
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       // Search to the right
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 Sed_hydro sed_cube_river_data( Sed_cube s , GList *this_river )
01531 {
01532    return ((Sed_river*)(this_river->data))->data;
01533 }
01534 */
01535 /*
01536 Sed_cube sed_cube_set_river_data( Sed_cube s        ,
01537                                   GList *this_river ,
01538                                   Sed_hydro new_river_data )
01539 {
01540    Sed_hydro this_hydro_rec = sed_cube_river_data( s , this_river );
01541    sed_hydro_copy( this_hydro_rec , new_river_data );
01542    return s;
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       /* Split the longest branch of the river */
01563       sed_river_split( r );
01564 
01565       /* Create in_suspension grids for each new leaf */
01566       left_grid  = sed_cube_create_in_suspension(s);
01567       right_grid = sed_cube_create_in_suspension(s);
01568 
01569       /* Attach in_suspension grids to the new leaves */
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       /* If the river is a trunk, remove it from the list of trunks */
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 Sed_cube sed_cube_remove_river( Sed_cube s , gssize river_no )
01647 {
01648    Sed_cell_grid this_grid = g_list_nth_data( s->in_suspension , river_no );
01649 
01650    sed_cube_destroy_in_suspension( this_grid );
01651    s->in_suspension = g_list_delete_link( s->in_suspension ,
01652                                           g_list_nth( s->in_suspension ,
01653                                                       river_no ) );
01654 
01655    return s;
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 void sed_cube_set_nth_river_data( Sed_cube s , int n , Sed_hydro new_data )
01670 {
01671    Sed_river *nth = g_list_nth( s->river , n )->data;
01672    sed_hydro_copy( nth->data , new_data );
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 Sed_hydro sed_cube_nth_river_data( Sed_cube s , int n )
01789 {
01790    Sed_hydro hydro_data = NULL;
01791    eh_require( s )
01792    {
01793       Sed_river *nth = g_list_nth( s->river , n )->data;
01794       hydro_data = nth->data;
01795    }
01796    return hydro_data;
01797 }
01798 */
01799 /*
01800 Sed_cube sed_cube_add_river( Sed_cube s , Sed_river *river )
01801 {
01802    eh_require( s )
01803    {
01804       s->river = g_list_prepend( s->river , river );
01805    }
01806    return s;
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    // Look for the shoreline along the first and last rows, then along the
01825    // first and last columns.  If there are no shore cells along the boundaries
01826    // then look in the interior.
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       // If the column is below sea level, it isn't the shore.
01951       // Otherwise, if any of its neighbours is below sea level,
01952       // then it is a shore column.
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    // If this column is below sea level, then it is not a shore edge.
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    // Check if each of the sides of the cell is a shore edge.  That is,
01987    // which neighbour cells are below sea level.  Turn on the appropriate
01988    // edge bit for each shore edge.
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    // Facing this edge, turn to the right and see if this new edge is a shore
02019    // edge.  If it is, this is the continuation of the current shore edge.
02020    // The shore turns to the right.
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    // Move to the new cell and rotate to the left.  Check if this new edge is
02035    // a shore edge.  If it is, this is the continuation of the shore edge.
02036    // The shore continues in a straight line.
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    // Move to the next cell.  By elimination, this must the new shore cell.
02048    // Turn to the left to face the new shore edge.  We could double check that
02049    // this is a shore edge but if it weren't, the original shore edge would 
02050    // not have been a shore edge.  Here, the shore has taken a left turn.
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    // Begin in the center of the first cell.
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    // If the first column satisies the stop criterion, return a NULL list.
02153    // Otherwise, add this column to the first of the list.
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    // Trace the path while within the domain while the stop criterion is not
02162    // satisfied.  Also, watch for flow from one cell, to another, and then
02163    // back the the first cell.  Stop the search once this occurs.
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       // Get the new path direction.
02170       angle = angle_func( s , i , j , NULL );
02171 
02172       // Using this direction, find the exit point of the cell.
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       // From the exit position, get the index shift to move to the next cell.
02179       // Also, find the position within the new cell.
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       // The indices of the new cell.
02187       i += shift.i;
02188       j += shift.j;
02189 
02190       // If this new cell is within the domain, add the column to the list of
02191       // columns.  To avoid a infinite loop, stop the search if this cell is
02192       // already in the list.
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 eh_watch_dbl( exit_pos.x );
02417 eh_watch_dbl( exit_pos.y );
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    if ( fabs(exit_pos.x) < 1e-5 )
02438       entrance_pos.x = dx;
02439    else if ( fabs(exit_pos.x-dx) < 1e-5 )
02440       entrance_pos.x = 0;
02441 
02442    if ( fabs(exit_pos.y) < 1e-5 )
02443       entrance_pos.y = dy;
02444    else if ( fabs(exit_pos.y-dy) < 1e-5 )
02445       entrance_pos.y = 0;
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    if ( fabs(exit_pos.x) < 1e-5 )
02467       shift.i = -1;
02468    else if ( fabs(exit_pos.x-dx) < 1e-5 )
02469       shift.i = 1;
02470 
02471    if ( fabs(exit_pos.y) < 1e-5 )
02472       shift.j = -1;
02473    else if ( fabs(exit_pos.y-dy) < 1e-5 )
02474       shift.j = 1;
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 Sed_river *sed_create_river( int n_grains , Eh_ind_2 *pos )
02614 {
02615    Sed_river *river = eh_new( Sed_river , 1 );
02616 
02617    river->data = sed_hydro_new( n_grains );
02618    river->hinge = eh_new( Sed_hinge_pt , 1 );
02619    river->hinge->min_angle = 0;
02620    river->hinge->max_angle = M_PI;
02621 
02622    if ( pos )
02623    {
02624       river->x_ind = pos->i;
02625       river->y_ind = pos->j;
02626    }
02627    else
02628    {
02629       river->x_ind = 0;
02630       river->y_ind = 0;
02631    }
02632 
02633    return river;
02634 }
02635 */
02636 /*
02637 Sed_river *sed_copy_river( Sed_river *dest , Sed_river *source )
02638 {
02639    if ( !dest )
02640       dest = eh_new( Sed_river , 1 );
02641 
02642    memcpy( dest , source , sizeof( Sed_river ) );
02643 
02644    dest->data  = sed_hydro_dup( source->data );
02645    dest->hinge = eh_new( Sed_hinge_pt , 1 );
02646 
02647    memcpy( dest->hinge , source->hinge , sizeof( Sed_hinge_pt ) );
02648 
02649    return dest;
02650 }
02651 */
02652 /*
02653 Sed_river *sed_dup_river( Sed_river *source )
02654 {
02655    return sed_copy_river( NULL , source );
02656 }
02657 */
02658 /*
02659 void sed_dump_river( FILE *fp , Sed_river *river )
02660 {
02661    int len = strlen( river->river_name );
02662 
02663    sed_hydro_write( fp , river->data );
02664 
02665    fwrite( river->hinge      , sizeof(Sed_hinge_pt) , 1   , fp );
02666    fwrite( &(river->x_ind)   , sizeof(int)          , 1   , fp );
02667    fwrite( &(river->y_ind)   , sizeof(int)          , 1   , fp );
02668    fwrite( &len              , sizeof(int)          , 1   , fp );
02669    fwrite( river->river_name , sizeof(char)         , len , fp );
02670 }
02671 */
02672 /*
02673 Sed_river *sed_load_river( FILE *fp )
02674 {
02675    int len;
02676    Sed_river *river = eh_new( Sed_river , 1 );
02677 
02678    river->data = sed_hydro_read( fp );
02679    fread( &(river->x_ind)   , sizeof(int)          , 1   , fp );
02680    fread( &(river->y_ind)   , sizeof(int)          , 1   , fp );
02681    fread( &len              , sizeof(int)          , 1   , fp );
02682    fread( river->river_name , sizeof(char)         , len , fp );
02683 
02684    return river;
02685 }
02686 */
02687 /*
02688 void sed_destroy_river( Sed_river *river )
02689 {
02690    if ( river )
02691    {
02692       eh_free( river->hinge );
02693       sed_hydro_destroy( river->data );
02694       eh_free( river );
02695    }
02696 }
02697 */
02698 /*
02699 double sed_get_river_angle( Sed_river *river )
02700 {
02701    return river->hinge->angle;
02702 }
02703 */
02704 /*
02705 double sed_cube_river_angle( Sed_cube c , GList *river )
02706 {
02707    return sed_get_river_angle( (Sed_river*)(river->data) );
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       /* Read the time keys */
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       /* and make sure they're monotonically increasing */
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          /* Make sure there are only two columns of data in the file */
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          /* and that there are at least two data points */
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       /* Read the data for each record of the sequence */
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    // Open the sequence file.
02960    //---
02961    fp = eh_fopen_error( file , "rb" , &tmp_err );
02962 
02963    if ( !tmp_err )
02964    {
02965 
02966       //---
02967       // The number of columns and rows are listed first as an int (32).
02968       //---
02969       fread( &n_y , sizeof(gint32) , 1 , fp );
02970       fread( &n_x , sizeof(gint32) , 1 , fp );
02971 
02972       //---
02973       // A simple check for the wrong byte order
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       // Calculate the number of rows in the file based on the number of columns
02998       // and the file size.  If this is not a whole number, something is wrong.
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       // Read the sequence of grids.  A frame of a sequence consists of a key
03021       // followed by a square grid.  Each key is a double and each grid is a
03022       // series of doubles.  All grids are the same size that is given by the
03023       // first to elements in the file as two (32 bit) ints.
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       // Ensure that the sequence is monotonically increasing.
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    // Open the bathymetry file.
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       // The number of columns is listed first as an int (32).
03168       //---
03169       fread( &n_y , sizeof(gint32) , 1 , fp );
03170 
03171       //---
03172       // Calculate the number of rows in the file based on the number of columns
03173       // and the file size.  If this is not a whole number, something is wrong.
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          // Read the grid data.
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    // Scan the data file.  The should only be one record.  If there
03228    // are more, we'll just ignore them.
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          // The cross-shore positions will be the first row, and the depths the
03271          // second row (in the file they are listed in columns).
03272          // They should both be the same length.  We don't bother checking.
03273          //---
03274          y = data[0];
03275          z = data[1];
03276          n = n_cols;
03277 
03278          //---
03279          // Interpolate the data from the file to an equally spaced grid.
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 void sed_avulse_river( Sed_river *river , Sed_cube c )
03304 {
03305    double last_angle, angle;
03306    double min_angle, max_angle;
03307    double std_dev;
03308    static long int iseed[1];
03309 
03310    last_angle = river->hinge->angle;
03311    min_angle  = river->hinge->min_angle;
03312    max_angle  = river->hinge->max_angle;
03313    std_dev    = river->hinge->std_dev;
03314 
03315    do
03316    {
03317       angle = last_angle + eh_gasdev( iseed )*std_dev;
03318       if ( angle<min_angle )
03319          angle = min_angle+(min_angle-angle);
03320       if ( angle>max_angle )
03321          angle = max_angle-(angle-max_angle);
03322    }
03323    while ( angle < min_angle || angle > max_angle );
03324 
03325    river->hinge->angle = angle;
03326 
03327    river = sed_cube_find_river_mouth( c , river );
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 void avulse_river_helper( Sed_river *this_river , Sed_cube c );
03340 
03341 Sed_cube sed_cube_avulse_all_rivers( Sed_cube c )
03342 {
03343    g_list_foreach( c->river , (GFunc)&avulse_river_helper , c );
03344    return c;
03345 }
03346 
03347 void avulse_river_helper( Sed_river *this_river , Sed_cube c )
03348 {
03349    sed_avulse_river( this_river , c );
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       /* Write all of the scalar data */
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       // Now write all of the pointer data.
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       // Dump all rivers and suspension grids.
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       // Load in the scalar information into the Sed_cube.
03456       //---
03457       NEW_OBJECT( Sed_cube , p );
03458       fread( p , sizeof(*p) , 1 , fp );
03459 
03460       //---
03461       // Allocate memory, and load in the vector information into the Sed_cube.
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       // read the river data.
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       // Create an array of y's to pass to sed_get_floor
03599       //---
03600       for ( i=0 ; i<len ; i++ )
03601          g_array_append_val( y_array , y[i] );
03602 
03603       //---
03604       // Get the depths as an array
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          // Copy the array values to the input locations
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    // Scan the data file.
03655    // The should only be one record.  If there is more, we'll just ignore them.
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       // The cross-shore positions will be the first row, and the depths the
03684       // second row (in the file they are listed in columns).
03685       // They should both be the same length.  We don't bother checking.
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       // Make sure the cross-shore distances are monotonically increasing.
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       // Interpolate the data from the file to an equally spaced grid.
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 }

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