/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/xshore/xshore.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 
00032 #include <stdio.h>
00033 #include <math.h>
00034 #include <string.h>
00035 #include <glib.h>
00036 #include <utils/utils.h>
00037 #include <sed/sed_sedflux.h>
00038 #include "xshore.h"
00039 
00040 double get_closure_depth( Sed_cube p , Sed_wave wave );
00041 double get_h_c( Sed_wave wave );
00042 gssize get_zone_indices( Sed_cube p , double z_0 , double z_1 , gssize i_0 , Sed_grid_func get_val , gssize* ind );
00043 
00044 typedef struct
00045 {
00046    double u_0;   
00047    Sed_wave w;   
00048    Sed_cube p; 
00049    gssize* ind;
00050    gssize ind_len;
00051 
00052    double x_0;   
00053    double x_b;   
00054    double h_b;   
00055    double dz_dx; 
00056    double *k;    
00057 }
00058 Bruun_data G_GNUC_INTERNAL;
00059 
00060 double get_total_flux( double z     ,
00061                        double dz_dx ,
00062                        Sed_wave w   ,
00063                        double u_0   ,
00064                        double w_s   ,
00065                        double breaker_depth ,
00066                        double h_b   ,
00067                        double x     ,
00068                        double x_b   ,
00069                        double max_qx ) G_GNUC_INTERNAL;
00070 Sed_cell   move_sediment                 ( Sed_cube p            ,
00071                                            double** du           ,
00072                                            double* erosion_limit ,
00073                                            double z_0            ,
00074                                            double dt             ,
00075                                            Bruun_data* data      ,
00076                                            Sed_cell lost         ,
00077                                            Sed_cell added        ,
00078                                            Sed_cell in_suspension ) G_GNUC_INTERNAL;
00079 
00080 void update_bruun_zone_data( Bruun_data* data )
00081 {
00082    if ( data && data->ind_len>2 )
00083    {
00084       gssize n;
00085       double *w_s, u_om, d_max;
00086       double q_left, q_right;
00087       Sed_cube p = data->p;
00088       double breaker_depth = get_breaking_wave_depth( data->w );
00089       double h_b_left, h_b_right, x_b_left;
00090       gssize i_0 = data->ind[0];
00091       gssize i_b = data->ind[data->ind_len-1];
00092       gssize n_grains = sed_sediment_env_n_types();
00093       Sed_wave this_wave;
00094 
00095       eh_require( i_0 >= 0 );
00096       eh_require( i_b >= 0 );
00097       eh_require( i_b-1 >= 0 );
00098 
00099       data->x_0   = sed_cube_col_y( p,i_0 );
00100       data->x_b   = sed_cube_col_y( p,i_b );
00101       //data->h_b   = get_h_c( data->w );
00102       data->h_b   = sed_cube_water_depth(p,0,i_b);
00103       data->dz_dx = sed_cube_y_slope( p , 0 , i_b );
00104       h_b_left  = sed_cube_water_depth( p,0,i_b-1 );
00105       h_b_right = sed_cube_water_depth( p,0,i_b+1 );
00106       x_b_left  = sed_cube_col_y( p,i_b-1 );
00107       this_wave = sed_gravity_wave_new( data->w , data->h_b , NULL );
00108 
00109       w_s = sed_sediment_property( NULL , &sed_type_settling_velocity );
00110 
00111       for ( n=0 ; n<n_grains ; n++ )
00112       {
00113          w_s[n] /= S_SECONDS_PER_DAY;
00114          u_om  = get_near_bed_velocity( data->h_b ,
00115                                         data->w   ,
00116                                         breaker_depth );
00117          d_max = get_grain_size_threshold( u_om , sed_wave_period( data->w ) );
00118 /*
00119       if ( sed_grain_size_in_meters(p->sed,n) > d_max )
00120 {
00121          data->k[n] = 0;
00122 eh_watch_int( n );
00123 }
00124       else
00125 */
00126          data->k[n] = get_diffusion_constant( data->h_b ,
00127                                               this_wave ,
00128                                               w_s[n] ,
00129                                               breaker_depth )
00130                     * ( h_b_right - data->h_b )/( data->h_b - h_b_left )
00131                     * pow( (data->x_b-data->x_0) / (x_b_left-data->x_0) , 1.-XSHORE_BRUUN_M );
00132 
00133 q_left = get_total_flux( h_b_left ,
00134                          sed_cube_y_slope(p,0,i_b-1) ,
00135                          this_wave ,
00136                          data->u_0 ,
00137                          w_s[n] ,
00138                          breaker_depth ,
00139                          data->h_b ,
00140                          x_b_left-data->x_0 ,
00141                          data->x_b-data->x_0 ,
00142                          data->k[n] );
00143 q_right = get_total_flux( data->h_b ,
00144                           data->dz_dx ,
00145                           this_wave ,
00146                           data->u_0 ,
00147                           w_s[n] ,
00148                           breaker_depth ,
00149                           data->h_b ,
00150                           data->x_b-data->x_0 ,
00151                           data->x_b-data->x_0 ,   
00152                           data->k[n] );
00153 
00154       }
00155 
00156       sed_wave_destroy( this_wave );
00157    }
00158 }
00159 
00160 void       diffuse_cols                  ( Sed_cube p              ,
00161                                            Sed_wave deep_wave      ,
00162                                            double u_0               ,
00163                                            double* erosion_limit    ,
00164                                            Sed_column* source_col    ,
00165                                            double* bruun_depth        ,
00166                                            Sed_cell along_shore_cell ,
00167                                            Bruun_data* data  ,
00168                                            double dt                ,
00169                                            double t_total           ,
00170                                            Sed_cell added          ,
00171                                            Sed_cell in             ,
00172                                            Sed_cell out  ) G_GNUC_INTERNAL;
00173 double**   get_sediment_flux             ( Sed_cube p ,
00174                                            Sed_wave deep_wave ,
00175                                            double u_0 ,
00176                                            Bruun_data *data ,
00177                                            Sed_cell in );
00178 double     get_time_step                 ( Sed_cube p              ,
00179                                            Sed_wave deep_wave      ,
00180                                            double u_0               ,
00181                                            Bruun_data* data ) G_GNUC_INTERNAL;
00182 
00196 Xshore_info xshore( Sed_cube p               ,
00197                     Sed_cell along_shore_cell ,
00198                     double xshore_current     ,
00199                     Sed_ocean_storm storm )
00200 {
00201    double      z_0;
00202    double*     zone_dt;
00203    double**    bruun_depth;
00204    double**    max_erode_depth;
00205    Sed_wave    deep_water_wave;
00206    Sed_cube*   shelf_zone;
00207    Sed_column* source_col;
00208    gssize      n_zones;
00209    Xshore_info info;
00210    Bruun_data  bruun_zone_data;
00211 
00212    info.added = NULL;
00213    info.lost  = NULL;
00214    info.dt    = NULL;
00215 
00216    eh_require( sed_cube_is_1d(p) );
00217    eh_require( along_shore_cell );
00218    eh_require( storm            );
00219 
00220    eh_return_val_if_fail( sed_cube_is_1d(p)   , info );
00221    eh_return_val_if_fail( sed_cube_n_y(p) > 3 , info );
00222 
00223    deep_water_wave = sed_wave_new( sed_ocean_storm_wave_height( storm ) ,
00224                                    sed_ocean_storm_wave_number( storm ) ,
00225                                    sed_ocean_storm_wave_freq  ( storm ) );
00226 
00227    eh_return_val_if_fail( !sed_wave_is_bad(deep_water_wave) , info );
00228 
00229    eh_debug( "Is there a Bruun zone?" );
00230    {
00231       gboolean error = FALSE;
00232       gssize i;
00233 //      gssize*   bruun_ind   = eh_new( gssize , sed_cube_n_y(p) );
00234       Sed_cube* bruun_zones = get_shelf_zones( p , get_h_c( deep_water_wave ) , NULL );
00235 /*
00236       gssize    ind_len     = get_zone_indices( p ,
00237                                                 0 ,
00238                                                 get_h_c(deep_water_wave) ,
00239                                                 0 ,
00240                                                 S_WATER_DEPTH_FUNC ,
00241                                                 bruun_ind );
00242 */
00243 
00244       if ( bruun_zones[0]==NULL || sed_cube_n_y(bruun_zones[0])<=3 )
00245       {
00246          // No bruun zone, exit
00247          error = TRUE;
00248          sed_wave_destroy( deep_water_wave );
00249       }
00250 
00251       for ( i=0 ; bruun_zones[i] ; i++ )
00252          sed_cube_free( bruun_zones[i] , FALSE );
00253 
00254       if ( error )
00255          return info;
00256    }
00257 
00258    eh_debug( "Calculate the water depth of the inner shelf" );
00259    {
00260       z_0 = get_closure_depth( p , deep_water_wave );   
00261       z_0 = 100.;
00262       info.z_0 = z_0;
00263    }
00264 
00265    eh_debug( "Divide the profile into smaller regions" );
00266    {
00267       shelf_zone = get_shelf_zones( p , z_0 , NULL );
00268       for ( n_zones=0 ; shelf_zone[n_zones] ; n_zones++ );
00269       info.n_zones = n_zones;
00270 
00271       eh_require( n_zones>0 );
00272    }
00273 
00274    eh_debug( "Calculate the Bruun profile" );
00275    if ( n_zones>0 )
00276    {
00277       gssize i;
00278       double* y;
00279 //      gssize*   bruun_ind   = eh_new( gssize , sed_cube_n_y(p) );
00280       gssize**  bruun_ind   = eh_new( gssize* , 2 );
00281       Sed_cube* bruun_zones = get_shelf_zones( p , get_h_c( deep_water_wave ) , bruun_ind );
00282 /*
00283       gssize    ind_len     = get_zone_indices( p ,
00284                                                 0 ,
00285                                                 get_h_c(deep_water_wave) ,
00286                                                 0 ,
00287                                                 S_WATER_DEPTH_FUNC ,
00288                                                 bruun_ind );
00289 */
00290 
00291       bruun_depth = eh_new0( double* , n_zones );
00292 
00293       if ( bruun_zones[0] && sed_cube_n_y(bruun_zones[0])>3 )
00294       {
00295          double bruun_m = XSHORE_BRUUN_M;
00296          double bruun_a = get_bruun_a  ( bruun_zones[0] , bruun_m );
00297          double y_0     = get_bruun_y_0( bruun_zones[0] );
00298          double y_b     = get_bruun_y_b( bruun_zones[0] );
00299 
00300          for ( i=0 ; i<1; i++ )
00301          {
00302             y = sed_cube_y( shelf_zone[i] , NULL );
00303          
00304             bruun_depth[i] = get_bruun_profile( y ,
00305                                                sed_cube_n_y(shelf_zone[i]) ,
00306                                                bruun_a ,
00307                                                bruun_m ,
00308                                                y_0 ,
00309                                                y_b );
00310 
00311             eh_free( y );
00312          }
00313 
00314          bruun_zone_data.p        = p;
00315          bruun_zone_data.ind_len  = sed_cube_n_y(bruun_zones[0]);
00316          bruun_zone_data.ind      = g_memdup( bruun_ind[0] , sizeof(gssize)*bruun_zone_data.ind_len );
00317          bruun_zone_data.w        = deep_water_wave;
00318          bruun_zone_data.u_0      = xshore_current;
00319          bruun_zone_data.k        = g_new( double , sed_sediment_env_n_types() );
00320 
00321          update_bruun_zone_data( &bruun_zone_data );
00322 
00323          info.bruun_a   = bruun_a;
00324          info.bruun_m   = bruun_m;
00325          info.bruun_y_0 = y_0;
00326          info.bruun_y_b = y_b;
00327          info.bruun_h_b = sed_cube_water_depth( bruun_zones[0] ,
00328                                                 0              ,
00329                                                 sed_cube_n_y(bruun_zones[0])-1 );
00330       }
00331 
00332       for ( i=0 ; i<n_zones ; i++ )
00333       {
00334          sed_cube_free( bruun_zones[i] , FALSE );
00335          eh_free( bruun_ind[i] );
00336       }
00337       eh_free( bruun_zones  );
00338       eh_free( bruun_ind );
00339 
00340    }
00341 
00342    eh_debug( "Find the column where suspended sediment is added" );
00343    {
00344       gssize i;
00345       Sed_cube* zone = get_shelf_zones( p , 30. , NULL );
00346 
00347       if ( zone[1] )
00348       {
00349          source_col    = g_new0( Sed_column , 2 );
00350          source_col[0] = sed_cube_col(zone[1],0);
00351       }
00352       else
00353          source_col = NULL;
00354 
00355       for ( i=0 ; zone[i] ; i++ )
00356          sed_cube_free( zone[i] , FALSE );
00357       eh_free( zone  );
00358    }
00359 
00360    eh_debug( "Calculate the maximum erosion depth for this storm" );
00361    if ( n_zones>0 )
00362    {
00363       gssize i;
00364 
00365       max_erode_depth = eh_new0( double* , n_zones );
00366       for ( i=0 ; i<1 ; i++ )
00367          max_erode_depth[i] = get_max_erosion_profile( shelf_zone[i] , deep_water_wave );
00368    }
00369 
00370    eh_debug( "Calculate the time step for each region" );
00371    if ( n_zones>0 )
00372    {
00373       gssize i;
00374       double t_total = sed_ocean_storm_duration(storm);
00375 
00376       zone_dt = eh_new( double , n_zones+1 );
00377       for ( i=0 ; i<1 ; i++ )
00378       {
00379          zone_dt[i] = get_time_step( shelf_zone[i]   ,
00380                                      deep_water_wave ,
00381                                      xshore_current  ,
00382                                      &bruun_zone_data );
00383          if ( zone_dt[i] > t_total )
00384             zone_dt[i] = t_total;
00385       }
00386       zone_dt[n_zones] = zone_dt[n_zones-1];
00387 
00388       info.dt = g_memdup( zone_dt , sizeof(double)*n_zones );
00389    }
00390 
00391 
00392    eh_debug( "Diffuse each region" );
00393    if ( n_zones>0 )
00394    {
00395       double m_0 = sed_cube_mass( p );
00396       double m_added, m_lost, m_1;
00397       gssize i;
00398       double t;
00399       double       t_total = sed_ocean_storm_duration(storm);
00400       gssize      n_grains = sed_sediment_env_n_types();
00401       Sed_cell  total_lost = sed_cell_new( n_grains );
00402       Sed_cell total_added = sed_cell_new( n_grains );
00403       Sed_cell          in = sed_cell_new( n_grains );
00404       Sed_cell         out = sed_cell_new( n_grains );
00405       Sed_cell       added = sed_cell_new( n_grains );
00406 
00407       eh_require( t_total>0 );
00408 
00409       for ( t=0 ; t<t_total ; )
00410       {
00411          sed_cell_resize( in  , 0. );
00412          for ( i=0 ; i<1 ; i++ )
00413          {
00414             diffuse_cols( shelf_zone[i]   ,
00415                           deep_water_wave , xshore_current ,
00416                           max_erode_depth[i] , source_col ,
00417                           bruun_depth[i]  , along_shore_cell ,
00418                           &bruun_zone_data ,
00419                           zone_dt[0] , t_total , added ,
00420                           NULL              , out );
00421          }
00422 
00423          t += t_total;
00424 
00425          sed_cell_add( total_lost , in );
00426       }
00427 m_1 = sed_cube_mass(p);
00428 
00429       sed_cell_add( total_added , out );
00430 
00431 m_added = sed_cell_mass(added)*sed_cube_x_res(p)*sed_cube_y_res(p);
00432 m_lost  = sed_cell_mass(out)*sed_cube_x_res(p)*sed_cube_y_res(p);
00433 if ( fabs((m_0+m_added-m_lost-m_1)/m_1) > .01 )
00434 {
00435    eh_watch_dbl( m_0 );
00436    eh_watch_dbl( m_1 );
00437    eh_watch_dbl( m_added );
00438    eh_watch_dbl( m_lost );
00439    exit(0);
00440 }
00441 
00442       sed_cell_destroy( in   );
00443       sed_cell_destroy( total_added );
00444       sed_cell_destroy( total_lost );
00445 
00446       info.lost  = out;
00447       info.added = added;
00448    }
00449 
00450    eh_debug( "Free memory" );
00451    {
00452       gssize i;
00453 
00454       eh_free( zone_dt );
00455       sed_wave_destroy( deep_water_wave );
00456       for ( i=0 ; i<n_zones ; i++ )
00457       {
00458          sed_cube_free( shelf_zone[i] , FALSE );
00459          eh_free( bruun_depth[i] );
00460          eh_free( max_erode_depth[i] );
00461       }
00462       eh_free( shelf_zone  );
00463       eh_free( bruun_depth );
00464       eh_free( max_erode_depth );
00465       eh_free( source_col );
00466 
00467       eh_free( bruun_zone_data.ind );
00468       eh_free( bruun_zone_data.k   );
00469    }
00470    eh_debug( "Done xshore" );
00471 
00472    return info;
00473 }
00474 
00475 //---
00476 // get the water depths at each point along the profile.
00477 // also calculate the breaking wave depth.  the wave will break if
00478 // its height is greater than .78 times the water depth.
00479 //---
00480 
00481 double wave_break_helper( double z , gpointer user_data ) G_GNUC_INTERNAL;
00482 
00483 double get_breaking_wave_depth( Sed_wave deep_water )
00484 {
00485    Sed_wave waves[2];
00486    Sed_wave this_wave = sed_wave_new( 0,0,0 );
00487    double min_h, max_h;
00488 
00489    eh_require( deep_water );
00490    eh_require( !sed_wave_is_bad(deep_water) );
00491 
00492    waves[0] = deep_water;
00493    waves[1] = this_wave;
00494 
00495    min_h = sed_wave_height( deep_water )/2.;
00496    max_h = sed_wave_height( deep_water )*2.;
00497 //   min_h = .01;
00498 //   max_h = 100.;
00499 
00500    return eh_bisection( &wave_break_helper , min_h , max_h , .1 , waves );
00501 }
00502 
00503 double wave_break_helper( double z , gpointer user_data )
00504 {
00505    double ans;
00506    Sed_wave deep_wave = ((Sed_wave*)(user_data))[0];
00507    Sed_wave this_wave = ((Sed_wave*)(user_data))[1];
00508    sed_gravity_wave_new( deep_wave , z , this_wave );
00509    ans = sed_wave_height(this_wave)/z - .78;
00510 
00511    return ans;
00512 }
00513       
00522 Sed_cube* get_shelf_zones( Sed_cube p , double z_0 , gssize** shelf_ind )
00523 {
00524    const gssize n_zones = 2;
00525    double boundary[3];
00526    Sed_cube* shelf_zones, *all_zones;
00527    gssize** zone_ind;
00528 
00529    eh_require( p );
00530 
00531    eh_clamp( z_0 , .1 , G_MAXDOUBLE );
00532 
00533    boundary[0] = .1;
00534    boundary[1] = z_0;
00535    boundary[2] = G_MAXDOUBLE;
00536 
00537    if ( shelf_ind )
00538       memset( shelf_ind , 0 , n_zones*sizeof(gssize*) );
00539 
00540    zone_ind  = eh_new( gssize* , n_zones );
00541    all_zones = get_zones( p , boundary , n_zones , S_WATER_DEPTH_FUNC , zone_ind );
00542 
00543    eh_debug( "Get rid of NULL zones" );
00544    {
00545       gssize i;
00546 //      gssize n = 0;
00547       shelf_zones = eh_new0( Sed_cube , n_zones+1 );
00548 /*
00549       for ( i=0 ; i<n_zones ; i++ )
00550          if ( all_zones[i] )
00551          {
00552             shelf_zones[n] = all_zones[i];
00553             shelf_ind[n]   = zone_ind[i];
00554             n = n+1;
00555          }
00556       shelf_zones[n] = NULL;
00557 */
00558       memcpy( shelf_zones , all_zones , sizeof(Sed_cube)*n_zones );
00559       shelf_zones[n_zones] = NULL;
00560 
00561       if ( shelf_ind )
00562          memcpy( shelf_ind , zone_ind , sizeof(gssize*)*n_zones );
00563       else
00564       {
00565          for ( i=0 ; i<n_zones ; i++ )
00566             eh_free( zone_ind[i] );
00567       }
00568    }
00569 
00570    eh_free( all_zones );
00571    eh_free( zone_ind  );
00572 
00573    return shelf_zones;
00574 }
00575 
00576 Sed_cube* get_bruun_zones( Sed_cube p , double y_0 )
00577 {
00578    Sed_cube* shelf_zones;
00579    Sed_cube* all_zones;
00580    const gssize n_zones = 2;
00581    gssize i_rm;
00582 
00583    eh_require( p );
00584 
00585    eh_debug( "Find the start of the Bruun profile" );
00586    {
00587       double sea_level = sed_cube_sea_level( p );
00588 
00589       sed_cube_set_sea_level( p , sea_level );
00590 
00591       i_rm = sed_cube_river_mouth_1d( p ) - 1;
00592       eh_lower_bound( i_rm , 0 );
00593 
00594       sed_cube_set_sea_level( p , sea_level );
00595    }
00596 
00597    eh_debug( "Get the zones of the Bruun profile" );
00598    {
00599       double boundary[3];
00600       double y_rm = sed_cube_col_y( p , i_rm );
00601 
00602       boundary[0] = 0   + y_rm;
00603       boundary[1] = y_0 + y_rm;
00604       boundary[2] = G_MAXDOUBLE;
00605 
00606       all_zones = get_zones( p , boundary , n_zones , S_Y_FUNC , NULL );
00607    }
00608 
00609    eh_debug( "Get rid of NULL zones" );
00610    {
00611       gssize i;
00612       gssize n = 0;
00613       shelf_zones = eh_new0( Sed_cube , n_zones+1 );
00614 
00615       for ( i=0 ; i<n_zones ; i++ )
00616          if ( all_zones[i] )
00617          {
00618             shelf_zones[n] = all_zones[i];
00619             n = n+1;
00620          }
00621       shelf_zones[n] = NULL;
00622    }
00623 
00624    eh_free( all_zones );
00625 
00626    return shelf_zones;
00627 }
00628 
00629 
00644 Sed_cube* get_zones( Sed_cube p , double* z , gssize n_zones , Sed_grid_func f , gssize** ind )
00645 {
00646    Sed_cube* sub_cube;
00647    gssize **zones;
00648    gssize n;
00649 
00650    eh_require( p                 );
00651    eh_require( z                 );
00652    eh_require( sed_cube_is_1d(p) );
00653    eh_require( n_zones>0         );
00654 
00655    eh_require( eh_dbl_array_is_monotonic( z , n_zones+1 ) );
00656 
00657    zones = eh_new( gssize* , n_zones );
00658    for ( n=0 ; n<n_zones ; n++ )
00659       zones[n] = eh_new( gssize , sed_cube_n_y(p) );
00660 
00661    eh_require( zones )
00662    {
00663       gssize len = get_zone_indices( p , z[0] , z[1] , 0 , f , zones[0] );
00664       for ( n=1 ; n<n_zones ; n++ )
00665          len = get_zone_indices( p , z[n] , z[n+1] , zones[n-1][len-1] , f , zones[n] );
00666    }
00667 
00668    sub_cube = eh_new0( Sed_cube , n_zones+1 );
00669    for ( n=0 ; n<n_zones ; n++ )
00670    {
00671       if ( zones[n][0]>0 )
00672          sub_cube[n] = sed_cube_cols( p , zones[n] );
00673       else
00674          sub_cube[n] = NULL;
00675    }
00676 
00677    if ( ind )
00678       memcpy( ind , zones , sizeof(gssize*)*n_zones );
00679    else
00680       for ( n=0 ; n<n_zones ; n++ )
00681          eh_free(zones[n]);
00682 
00683    eh_free( zones );
00684 
00685    return sub_cube;
00686 }
00687 
00688 gssize get_zone_indices( Sed_cube p ,
00689                          double z_0 ,
00690                          double z_1 ,
00691                          gssize i_0 ,
00692                          Sed_grid_func get_val ,
00693                          gssize* ind )
00694 {
00695    gssize max_i;
00696    gssize n = 0;
00697 
00698    eh_require( p       );
00699    eh_require( z_1>z_0 );
00700    eh_require( i_0>=0  );
00701    eh_require( ind     );
00702 
00703    max_i = sed_cube_n_y(p)-1;
00704 
00705    // Check if the right edge of the Sed_cube is in this zone.
00706    if ( get_val( p,0,max_i)>z_0 )
00707    {
00708       gssize i;
00709 
00710       // Find the index of right boundary
00711       for (  ; get_val(p,0,i_0)<z_0 ; i_0++ );
00712 
00713       // Check if the right boundary is within the profile.  If so, we
00714       // don't need to check for exceeding the array limits.
00715       if ( get_val(p,0,max_i)>z_1 )
00716          for ( i=i_0,n=0 ; get_val(p,0,i)<z_1 ; i++ )
00717          {
00718             ind[n] = i;
00719             n = n+1;
00720          }
00721       else
00722          for ( i=i_0,n=0 ; i<sed_cube_n_y(p) && get_val(p,0,i)<z_1 ; i++ )
00723          {
00724             ind[n] = i;
00725             n = n+1;
00726          }
00727       ind[n] = -1;
00728    }
00729    else
00730       ind[0] = -1;
00731 
00732    return n;
00733 }
00734 
00774 double get_time_step( Sed_cube p , Sed_wave deep_wave , double u_0 , Bruun_data* data )
00775 {
00776    double dt;
00777    double breaker_depth;
00778    double k_max = 0;
00779 
00780    eh_require( p                           );
00781    eh_require( deep_wave                   );
00782    eh_require( !sed_wave_is_bad(deep_wave) );
00783 
00784    breaker_depth = get_breaking_wave_depth( deep_wave );
00785 /*
00786    {
00787       double* w_s = sed_sediment_property( NULL , &sed_type_settling_velocity );
00788       Sed_wave this_wave = sed_gravity_wave_new( deep_wave , breaker_depth , NULL );
00789 
00790       k_max     = get_diffusion_constant( breaker_depth     ,
00791                                           this_wave ,
00792                                           w_s[2] ,
00793                                           breaker_depth )
00794                 * S_SECONDS_PER_DAY;
00795 
00796       eh_free( w_s );
00797       sed_wave_destroy( this_wave );
00798    }
00799 */
00800    {
00801       gssize n_grains = sed_sediment_env_n_types();
00802       double* w_s = sed_sediment_property( NULL , &sed_type_settling_velocity );
00803       Sed_wave this_wave = sed_gravity_wave_new( deep_wave , data->h_b , NULL );
00804 
00805       k_max     = get_diffusion_constant( data->h_b ,
00806                                           this_wave ,
00807                                           //w_s[4]    ,
00808                                           w_s[n_grains-1]    ,
00809                                           breaker_depth )
00810                 * S_SECONDS_PER_DAY;
00811 
00812       eh_free( w_s );
00813       sed_wave_destroy( this_wave );
00814    }
00815 
00816    eh_debug( "Find the time step necessary for stability" );
00817    {
00818       double dy  = sed_cube_y_res(p);
00819       double fos = .9;
00820 
00821       dt = fos*dy*dy/(2*k_max);
00822 
00823       if ( dt*u_0*S_SECONDS_PER_DAY > dy )
00824          dt = fos*dy/(u_0*S_SECONDS_PER_DAY);
00825    }
00826 
00827    return dt;
00828 }
00829 
00830 double get_constant( double z , Sed_wave w , double w_s , double h_b )
00831 {
00832    double rho    = sed_rho_sea_water();
00833    double rho_s  = sed_rho_quartz();
00834    double c_fs   = .01;
00835    double eps_ss = .01;
00836    double g      = sed_gravity();
00837    double u_om   = get_near_bed_velocity( z , w , h_b );
00838    double i_s    = 1.;
00839 
00840    return   16./(3*M_PI)
00841           * rho/(rho_s-rho)
00842           * c_fs*eps_ss/g
00843           * i_s*pow(u_om,3.)/w_s;
00844 }
00845 
00846 double get_diffusion_constant( double z   ,
00847                                Sed_wave w ,
00848                                double w_s ,
00849                                double h_b )
00850 {
00851    double u_om = get_near_bed_velocity( z , w , h_b );
00852    return   get_constant( z , w , w_s , h_b )
00853           * pow(u_om,2.)/(5.*w_s);
00854 }
00855 
00866 double get_diffusion_flux( double z     ,
00867                            double dz_dx ,
00868                            Sed_wave w   ,
00869                            double w_s   ,
00870                            double h_b )
00871 {
00872    return get_diffusion_constant( z , w , w_s , h_b )*dz_dx;
00873 }
00874 
00885 double get_advection_flux( double z   ,
00886                            Sed_wave w ,
00887                            double u_0 ,
00888                            double w_s ,
00889                            double h_b )
00890 {
00891    return get_constant( z , w , w_s , h_b ) * u_0;
00892 }
00893 
00916 double
00917 get_total_flux_outer_shelf( double z     ,
00918                             double dz_dx ,
00919                             Sed_wave w   ,
00920                             double u_0   ,
00921                             double w_s   ,
00922                             double h_b )
00923 {
00924    double u_om = get_near_bed_velocity( z , w , h_b );
00925    return   get_constant( z , w , w_s , h_b )
00926           * ( u_0 + pow(u_om,2.)/(5.*w_s)*dz_dx );
00927 }
00928 
00936 double
00937 get_total_flux_bruun_zone( double x , double dz_dx , double x_0 , double k_0 )
00938 {
00939    eh_require( x>=0   );
00940    eh_require( x_0>0  );
00941    eh_require( x<=x_0 );
00942    eh_require( k_0>=0 );
00943 
00944    return k_0*pow(x/x_0,1.-XSHORE_BRUUN_M)*dz_dx;
00945 }
00946 
00947 double get_total_flux( double z     ,
00948                        double dz_dx ,
00949                        Sed_wave w   ,
00950                        double u_0   ,
00951                        double w_s   ,
00952                        double breaker_depth ,
00953                        double h_b   ,
00954                        double x     ,
00955                        double x_b   ,
00956                        double max_k )
00957 {
00958       return get_total_flux_outer_shelf( z , dz_dx , w , u_0 , w_s , breaker_depth );
00959 }
00960 
00983 void diffuse_cols( Sed_cube p                ,
00984                    Sed_wave deep_wave        ,
00985                    double u_0                ,
00986                    double* erosion_limit     ,
00987                    Sed_column* source_col    ,
00988                    double* bruun_depth       ,
00989                    Sed_cell along_shore_cell ,
00990                    Bruun_data* data          ,
00991                    double dt                 ,
00992                    double t_total            ,
00993                    Sed_cell added            ,
00994                    Sed_cell in               ,
00995                    Sed_cell out  )
00996 {
00997    eh_require( p         );
00998    eh_require( deep_wave );
00999    eh_require( !sed_wave_is_bad(deep_wave) );
01000    eh_require( dt>0      );
01001    eh_require( t_total>0 );
01002 
01003    if ( dt>t_total )
01004       dt = t_total;
01005 
01006    if ( sed_cube_n_y(p)>1 )
01007    {
01008       double t, **qy;
01009       Sed_cell suspended_cell = sed_cell_new_env( );
01010       double z_0 = get_closure_depth( p , deep_wave );
01011       double m_0 = sed_cube_mass(p), m_1;
01012       double m_added, m_lost;
01013 
01014       // Diffuse the sediment.  Calculate the fluxes, remove the sediment,
01015       // and move it to the next column.
01016       for ( t=dt ; t<t_total ; t+=dt )
01017       {
01018          qy = get_sediment_flux( p , deep_wave , u_0 , data , in );
01019          move_sediment( p , qy , erosion_limit , z_0 , dt , data , out , added , suspended_cell );
01020 m_added = sed_cell_mass( added )*sed_cube_x_res(p)*sed_cube_y_res(p);
01021 m_lost = sed_cell_mass( out )*sed_cube_x_res(p)*sed_cube_y_res(p);
01022 m_1=sed_cube_mass( p );
01023 //eh_watch_dbl( m_0 );
01024 //eh_watch_dbl( m_added );
01025 //eh_watch_dbl( m_lost );
01026 //eh_watch_dbl( m_1 );
01027 if ( fabs((m_0+m_added-m_lost-m_1)/m_1) > .01 )
01028 {
01029    eh_watch_dbl( sed_cell_mass( added ) );
01030    eh_watch_dbl( dt );
01031    eh_watch_dbl( m_0 );
01032    eh_watch_dbl( m_1 );
01033    eh_watch_dbl( m_added );
01034    eh_watch_dbl( m_lost );
01035    exit(0);
01036 }
01037          update_bruun_zone_data( data );
01038          sed_cell_resize( suspended_cell , 0. );
01039          eh_free_2( qy );
01040       }
01041 
01042       // Do the last partial time step, if need be.
01043       if ( t>=t_total )
01044       {
01045          dt = t_total-(t-dt);
01046          qy = get_sediment_flux( p , deep_wave , u_0 , data , in );
01047          move_sediment( p , qy , erosion_limit , z_0 , dt , data , out , added , suspended_cell );
01048 m_added = sed_cell_mass( added )*sed_cube_x_res(p)*sed_cube_y_res(p);
01049 m_lost = sed_cell_mass( out )*sed_cube_x_res(p)*sed_cube_y_res(p);
01050 m_1=sed_cube_mass( p );
01051 //eh_watch_dbl( m_0 );
01052 //eh_watch_dbl( m_added );
01053 //eh_watch_dbl( m_lost );
01054 //eh_watch_dbl( m_1=sed_cube_mass( p ) );
01055 if ( fabs((m_0+m_added-m_lost-m_1)/m_1) > .01 )
01056 {
01057    eh_watch_dbl( sed_cell_mass( added ) );
01058    eh_watch_dbl( dt );
01059    eh_watch_dbl( m_0 );
01060    eh_watch_dbl( m_1 );
01061    eh_watch_dbl( m_added );
01062    eh_watch_dbl( m_lost );
01063    exit(0);
01064 }
01065          update_bruun_zone_data( data );
01066          sed_cell_resize( suspended_cell , 0. );
01067          eh_free_2( qy );
01068       }
01069 eh_debug( "DONE" );
01070 
01071       sed_cell_destroy( suspended_cell );
01072    }
01073 
01074    return;
01075 }
01076 
01077 double** get_sediment_flux( Sed_cube p , Sed_wave deep_wave , double u_0 , Bruun_data *data , Sed_cell in )
01078 {
01079    double** du;
01080 
01081    eh_require( p                  );
01082    eh_require( deep_wave          );
01083    eh_require( u_0>=0             );
01084 
01085    du = eh_new_2( double , sed_cube_n_y(p) , sed_sediment_env_n_types() );
01086 
01087    eh_require( du )
01088    {
01089       gssize i, n;
01090       double u_om, d_max, qy;
01091       gssize     n_grains  = sed_sediment_env_n_types();
01092       Sed_wave this_wave   = sed_wave_new( 0 , 0 , 0 );
01093       double  wave_period  = sed_wave_period( deep_wave );
01094       double breaker_depth = get_breaking_wave_depth( deep_wave );
01095       double            dy = sed_cube_y_res( p );
01096       Eh_dbl_grid   z_grid = sed_cube_water_depth_grid( p , NULL );
01097       Eh_dbl_grid dz_dy_grid = sed_cube_y_slope_grid( p , NULL );
01098       double*            z = eh_grid_data_start( z_grid );
01099       double*        dz_dy = eh_grid_data_start( dz_dy_grid );
01100       double depth, y_b, y, *k_b;
01101       double* gz  = sed_sediment_property( NULL , &sed_type_grain_size_in_meters );
01102       double* w_s = sed_sediment_property( NULL , &sed_type_settling_velocity );
01103 
01104       for ( n=0 ; n<n_grains ; n++ )
01105          w_s[n] /= S_SECONDS_PER_DAY;
01106 
01107       eh_dbl_array_set( du[0] , n_grains*sed_cube_n_y(p) , 0. );
01108 
01109       y_b = data->x_b - data->x_0;
01110       k_b = data->k;
01111 
01112       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01113       {
01114          if ( i!=sed_cube_n_y(p)-1 )
01115             depth = (z[i]+z[i+1])*.5;
01116          else
01117             depth = z[i];
01118 
01119          y = sed_cube_col_y( p , i ) - data->x_0;
01120 
01121          if ( depth>.01 )
01122          {
01123 
01124             this_wave = sed_gravity_wave_new( deep_wave , depth , this_wave );
01125 
01126             eh_require( !sed_wave_is_bad( this_wave ) );
01127 
01128             u_om  = get_near_bed_velocity( depth     ,
01129                                            this_wave ,
01130                                            breaker_depth );
01131             d_max = get_grain_size_threshold( u_om , wave_period );
01132 
01133 //d_max = G_MAXDOUBLE;
01134 
01135             for ( n=0 ; n<n_grains ; n++ )
01136             {
01137                if ( gz[n] > d_max )
01138                   qy = 0;
01139                else
01140                {
01141                   qy  = get_total_flux( depth      ,
01142                                         dz_dy[i]   ,
01143                                         this_wave  ,
01144                                         u_0        ,
01145                                         w_s[n]     ,
01146                                         breaker_depth ,
01147                                         data->h_b  ,
01148                                         y          ,
01149                                         y_b        ,
01150                                         k_b[n] )
01151                       * S_SECONDS_PER_DAY
01152                       / dy
01153                       / (double)n_grains;
01154                }
01155 
01156                du[i][n] = qy;
01157             }
01158 
01159          }
01160 
01161       }
01162 
01163       eh_free( gz  );
01164       eh_free( w_s );
01165       eh_grid_destroy( dz_dy_grid , TRUE );
01166       eh_grid_destroy( z_grid , TRUE );
01167    }
01168 
01169    {
01170       gssize i, n;
01171       gssize n_grains  = sed_sediment_env_n_types();
01172       gssize* bruun_ind = data->ind;
01173       gssize  ind_len = data->ind_len;
01174 /*
01175       gssize* bruun_ind = eh_new( gssize , sed_cube_n_y(p)+1 );
01176       gssize ind_len = get_zone_indices( p ,
01177                                          0 ,
01178                                          get_h_c( deep_wave ) ,
01179                                          0 ,
01180                                          S_WATER_DEPTH_FUNC ,
01181                                          bruun_ind );
01182 */
01183       double y_b, y_0, y;
01184       double* k_max = eh_new( double , sed_sediment_env_n_types() );
01185 
01186       if ( ind_len>0 )
01187       {
01188          gssize i_b = bruun_ind[ind_len-1] - bruun_ind[0];
01189          // Get Bruun k for each grain so that the fluxes match.
01190          i = bruun_ind[ind_len-1] + 1;
01191          for ( n=0 ; n<n_grains ; n++ )
01192             k_max[n] = du[i_b+1][n]/sed_cube_y_slope( p , 0 , i_b );
01193 //            k_max[n] = du[i_b][n]/sed_cube_y_slope( p , 0 , bruun_ind[ind_len-1] );
01194 
01195          // calculate the fluxes within the Bruun region
01196 //         y_0 = sed_cube_col_y( p , bruun_ind[0]         ) - sed_cube_y_res(p);
01197 //         y_b = sed_cube_col_y( p , bruun_ind[ind_len-1] ) - y_0;
01198          y_0 = sed_cube_col_y( p , 0   ) - sed_cube_y_res(p);
01199          y_b = sed_cube_col_y( p , i_b ) - y_0;
01200 //         for ( i=bruun_ind[0] ; i<=bruun_ind[ind_len-1] ; i++ )
01201          for ( i=0 ; i<=i_b ; i++ )
01202          {
01203             y = sed_cube_col_y( p , i ) - y_0;
01204             for ( n=0 ; n<n_grains ; n++ )
01205 {
01206                du[i][n] = k_max[n]*pow( y / y_b , 1.-XSHORE_BRUUN_M )*sed_cube_y_slope(p,0,i);
01207 //fprintf( stderr , "du[%d][%d] = %f , kmax = %f\n" , i , n , du[i][n] , k_max[n] );
01208 }
01209          }
01210       }
01211 
01212 /*
01213       eh_free( bruun_ind );
01214       eh_free( k_max );
01215 */
01216    }
01217 
01218    if ( in )
01219    {
01220       gssize n;
01221       gssize n_grains = sed_sediment_env_n_types();
01222       double t        = sed_cell_size(in);
01223 
01224       for ( n=0 ; n<n_grains ; n++ )
01225          du[0][n] += t*sed_cell_nth_fraction(in,n);
01226    }
01227 
01228    return du;
01229 }
01230 
01231 Sed_cell move_sediment( Sed_cube p            ,
01232                         double** du           ,
01233                         double* erosion_limit ,
01234                         double z_0            ,
01235                         double dt             ,
01236                         Bruun_data* data      ,
01237                         Sed_cell lost         ,
01238                         Sed_cell added        ,
01239                         Sed_cell in_suspension )
01240 {
01241    gssize n_grains;
01242    Sed_cell* rem_cell;
01243 
01244    eh_require( p    );
01245    eh_require( du   );
01246    eh_require( lost );
01247 
01248    n_grains = sed_sediment_env_n_types();
01249 
01250    // Convert the fluxes to amounts.  Create a temporary array to hold
01251    // the removed sediment.
01252    {
01253       gssize i, n;
01254       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01255          for ( n=0 ; n<n_grains ; n++ )
01256 {
01257             du[i][n] *= dt;
01258 if ( du[i][n] > 10 )
01259 {
01260    eh_watch_int( i );
01261    eh_watch_int( n );
01262    eh_watch_int( sed_cube_n_y(p) );
01263    eh_watch_dbl( du[i][n] );
01264    eh_watch_dbl( sed_cube_y_slope(p,0,i) );
01265    eh_watch_dbl( data->x_0 );
01266    eh_watch_dbl( data->x_b );
01267    eh_watch_dbl( data->h_b );
01268    eh_watch_int( data->ind_len );
01269    eh_watch_int( data->ind[0] );
01270    eh_watch_int( data->ind[data->ind_len-1] );
01271    exit(0);
01272 }
01273 }
01274       rem_cell = eh_new( Sed_cell , sed_cube_n_y(p) );
01275       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01276          rem_cell[i] = sed_cell_new_env( );
01277    }
01278 
01279    // Determine which column the sediment will be removed from and added to.
01280    // Remove the sediment and add it to the appropriate index of the temporary
01281    // array.
01282    {
01283       gssize i, add_index, remove_index;
01284       double du_tot;
01285       gssize top_i = sed_cube_n_y(p)-1;
01286       Sed_cell add_cell  = sed_cell_new_env();
01287       Sed_cell fill_cell;
01288       double*     dh_max = eh_new( double , sed_cube_n_y(p) );
01289 //      gssize* bruun_ind = eh_new( gssize , sed_cube_n_y(p)+1 );
01290 //      gssize ind_len = get_zone_indices( p , 0 , data->h_b , 0 , S_WATER_DEPTH_FUNC , bruun_ind );
01291       double total = 0;
01292       gssize    ind_len = data->ind_len;
01293 
01294       {
01295          double* f = eh_new0( double , n_grains );
01296 
01297          f[0] = 1.;
01298 
01299          fill_cell = sed_cell_new_sized( n_grains , G_MINDOUBLE , f );
01300 
01301          sed_cell_destroy( fill_cell );
01302          fill_cell = NULL;
01303 
01304          eh_free( f );
01305       }
01306 
01307       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01308 {
01309          dh_max[i] = erosion_limit[i]-sed_cube_water_depth(p,0,i);
01310 if ( dh_max[i]<0 )
01311    dh_max[i] = 0;
01312          total += dh_max[i];
01313 }
01314       for ( i=0 ; i<top_i ; i++ )
01315       {
01316          du_tot = eh_dbl_array_sum( du[i] , n_grains );
01317          eh_dbl_array_fabs( du[i] , n_grains );
01318 
01319          remove_index = (du_tot>0)?(i):(i+1);
01320          add_index    = (du_tot>0)?(i+1):(i);
01321 
01322          if ( fabs(du_tot) > 0 )
01323          {
01324             double m_0 = sed_column_mass( sed_cube_col(p,remove_index) );
01325             double m_1, dm;
01326 if ( fabs(du_tot)>dh_max[i] )
01327 {
01328    du_tot = dh_max[i];
01329 }
01330 //eh_watch_dbl( sed_cell_mass( add_cell ) );
01331 //eh_watch_dbl( sed_column_thickness( sed_cube_col(p,remove_index) ) );
01332             sed_column_separate_top_amounts_fill(
01333                                              sed_cube_col(p,remove_index) ,
01334                                              fabs(du_tot) ,
01335                                              du[i] ,
01336                                              fill_cell ,
01337                                              add_cell );
01338 m_1 = sed_column_mass( sed_cube_col(p,remove_index) );
01339 dm  = sed_cell_mass( add_cell );
01340 
01341 if ( fabs(m_1+dm-m_0) > 1e-6 )
01342 {
01343    eh_watch_int( i );
01344    eh_watch_int( remove_index );
01345    eh_watch_dbl( sed_column_thickness( sed_cube_col(p,remove_index) ) );
01346    eh_watch_dbl( du_tot );
01347    eh_watch_dbl( m_0 );
01348    eh_watch_dbl( m_1 );
01349    eh_watch_dbl( dm );
01350    exit( 0 );
01351 }
01352             sed_cell_add( rem_cell[add_index] , add_cell );
01353             sed_cell_add( added , fill_cell );
01354          }
01355       }
01356    
01357       {
01358          if ( ind_len > 0 )
01359          {
01360             //gssize i_0 = bruun_ind[0];
01361             gssize i_0 = 0;
01362 
01363             // Add whatever we removed from the first cell back.
01364             sed_cell_copy( rem_cell[i_0] , rem_cell[i_0+1] );
01365 //            sed_cell_add ( lost          , rem_cell[i_0]   );
01366 
01367 // NOTE: This sediment should be removed from the next river event.
01368             sed_cell_add ( added          , rem_cell[i_0]   );
01369          }
01370       }
01371 
01372 //      eh_free( bruun_ind );
01373 
01374       du_tot = eh_dbl_array_sum( du[0] , n_grains );
01375       eh_dbl_array_fabs( du[0] , n_grains );
01376       if ( du_tot < 0 )
01377       {
01378          du_tot = -dh_max[0];
01379          sed_column_separate_top_amounts_fill( sed_cube_col(p,0) ,
01380                                           -du_tot ,
01381                                           du[0] ,
01382                                           fill_cell ,
01383                                           add_cell );
01384          sed_cell_add( added , fill_cell );
01385       }
01386 
01387       du_tot = eh_dbl_array_sum( du[top_i] , n_grains );
01388       eh_dbl_array_fabs( du[top_i] , n_grains );
01389       if ( du_tot > 0 )
01390       {
01391          if ( du_tot>dh_max[top_i] )
01392             du_tot = dh_max[top_i];
01393 
01394          sed_column_separate_top_amounts_fill( sed_cube_col(p,top_i) ,
01395                                           du_tot ,
01396                                           du[top_i],
01397                                           fill_cell ,
01398                                           add_cell );
01399          sed_cell_add( added , fill_cell );
01400          sed_cell_add( lost  , add_cell  );
01401       }
01402       else 
01403          sed_cell_copy( rem_cell[top_i] , rem_cell[top_i-1] );
01404 
01405       sed_cell_destroy( fill_cell );
01406       sed_cell_destroy( add_cell  );
01407       eh_free( dh_max );
01408    }
01409 
01410    // Set the facies type, and age of the sediment.  Add the removed sediment
01411    // to the profile.
01412    {
01413       gssize i;
01414 //      Sed_cell clay_cell = sed_cell_new_env();
01415 //      double* just_clay = eh_new0( double , n_grains );
01416 //      double z_0 = 23;
01417 
01418 //      just_clay[n_grains-1] = 1;
01419 //      just_clay[n_grains-2] = 1;
01420 
01421       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01422       {
01423          sed_cell_set_facies( rem_cell[i] , S_FACIES_WAVE );
01424          sed_cell_set_age( rem_cell[i] , sed_cube_age_in_years(p) );
01425 
01426          sed_column_add_cell( sed_cube_col(p,i) , rem_cell[i] );
01427       }
01428 
01429 //      sed_cell_add( in_suspension , clay_cell );
01430 
01431 //      sed_cell_destroy( clay_cell );
01432    }
01433 
01434    // Free memory.
01435    {
01436       gssize i;
01437       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01438          sed_cell_destroy( rem_cell[i] );
01439       eh_free( rem_cell );
01440    }
01441 
01442    return lost;
01443 }
01444 
01450 void add_suspended_sediment( Sed_column* col , Sed_cell cell )
01451 {
01452    if ( col )
01453    {
01454       gssize i;
01455 
01456       eh_require( cell );
01457       for ( i=0 ; col[i] ; i++ )
01458          sed_column_add_cell( col[i] , cell );
01459    }
01460    return;
01461 }
01462 
01480 double get_bruun_depth( double y , double y_0 , double bruun_a , double bruun_m)
01481 {
01482    return bruun_a*pow( fabs(y-y_0) , bruun_m );
01483 }
01484 
01492 double get_bruun_a( Sed_cube p , double bruun_m )
01493 {
01494    double bruun_a;
01495 
01496    eh_require( p );
01497 
01498    if ( p )
01499    {
01500       double h_b = sed_cube_water_depth( p , 0 , sed_cube_n_y(p)-1 );
01501       double y_0 = sed_cube_col_y( p , 0        ) - sed_cube_y_res(p);
01502       double y_b = sed_cube_col_y( p , sed_cube_n_y(p)-1 );
01503 
01504       bruun_a = h_b / pow(y_b-y_0,bruun_m);
01505    }
01506    else
01507       bruun_a = eh_nan();
01508 
01509    return bruun_a;
01510 }
01511 
01512 double get_bruun_y_0( Sed_cube p )
01513 {
01514    return sed_cube_col_y( p , 0 ) - sed_cube_y_res(p);
01515 }
01516 
01517 double get_bruun_y_b( Sed_cube p )
01518 {
01519    return sed_cube_col_y( p , sed_cube_n_y(p)-1 );
01520 }
01521 
01522 double* get_bruun_profile( double* y      , gssize len     ,
01523                            double bruun_a , double bruun_m ,
01524                            double y_0     , double y_b )
01525 {
01526    double* h = NULL;
01527 
01528    eh_require( y     );
01529    eh_require( len>0 );
01530    eh_require( y_b>y_0 );
01531 
01532    eh_debug( "Is there an inner shelf?" );
01533    if ( y_b>y_0 )
01534    {
01535       h = eh_new( double , len );
01536 
01537       eh_debug( "Calculate the depths of the Bruun profile" );
01538       {
01539          gssize i;
01540          for ( i=0 ; i<len ; i++ )
01541          {
01542             if ( y[i] < y_0 || y[i]>y_b )
01543                h[i] = eh_nan();
01544             else
01545                h[i] = get_bruun_depth( y[i] , y_0 , bruun_a , bruun_m );
01546          }
01547       }
01548 
01549       eh_debug( "Check if all points are outside of inner shelf" );
01550       {
01551          gssize i;
01552          for ( i=0 ; i<len && eh_isnan(h[i]) ; i++ );
01553          if ( i==len )
01554          {
01555             eh_free( h );
01556             h = NULL;
01557          }
01558       }
01559    }
01560 
01561    eh_debug( "Done." );
01562 
01563    return h;
01564 }
01565 
01582 void fill_to_bruun( Sed_cube p ,
01583                     double* h   ,
01584                     Sed_cell fill_cell )
01585 {
01586    double total = 0;
01587 
01588    eh_require( p );
01589    eh_require( fill_cell );
01590 
01591    if ( h )
01592    {
01593       gssize i;
01594       double dh;
01595 
01596       sed_cell_set_age   ( fill_cell , sed_cube_age_in_years(p) );
01597       sed_cell_set_facies( fill_cell , S_FACIES_ALONG_SHORE         );
01598 
01599       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01600       {
01601          if ( !eh_isnan(h[i]) )
01602          {
01603             dh = sed_cube_water_depth( p , 0 , i ) - h[i];
01604 
01605             if ( dh > 0 )
01606             {
01607                sed_cell_resize( fill_cell , dh );
01608 
01609                sed_column_add_cell( sed_cube_col(p,i) , fill_cell );
01610 
01611                total += dh;
01612             }
01613          }
01614       }
01615    }
01616 
01617    sed_cell_resize( fill_cell , total );
01618 
01619    return;
01620 }
01621 
01622 void fill_to_bruun_profile( Sed_cube p             ,
01623                             Sed_wave deep_wave     ,
01624                             double bruun_m         ,
01625                             Sed_cell fill_cell     ,
01626                             Sed_cell added_fill_cell )
01627 {
01628    eh_require( p );
01629 
01630    sed_cell_set_facies( fill_cell , S_FACIES_BEDLOAD             );
01631    sed_cell_set_age   ( fill_cell , sed_cube_age_in_years(p) );
01632 
01633    if ( sed_cube_n_y(p)>2 )
01634    {
01635       double bruun_a, h_b;
01636       double y_0, y_b;
01637 
01638       h_b = sed_cube_water_depth( p , 0 , sed_cube_n_y(p)-1 );
01639       y_0 = sed_cube_col_y( p , 0        );
01640       y_b = sed_cube_col_y( p , sed_cube_n_y(p)-1 );
01641 
01642       //---
01643       // Define the coefficient in the Bruun equation so that the curve
01644       // joins the current profile.
01645       //---
01646       bruun_a = h_b / pow(y_b-y_0,bruun_m);
01647 
01648       //---
01649       // If a column has been eroded to below the Bruun profile, fill it up to
01650       // the profile using the fill sediment.
01651       //---
01652       {
01653          gssize i;
01654          double h, dh, h_total = 0.;
01655 
01656          for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01657          {
01658             h = bruun_a * pow( sed_cube_col_y(p,i) - y_0 , bruun_m );
01659 
01660             dh = sed_cube_water_depth( p , 0 , i ) - h;
01661 
01662             if ( dh > 0 )
01663             {
01664                sed_cell_resize( fill_cell , dh );
01665 
01666                sed_column_add_cell( sed_cube_col(p,i) , fill_cell );
01667 
01668                h_total += dh;
01669             }
01670          }
01671 
01672          sed_cell_resize( fill_cell , h_total );
01673       }
01674 
01675       if ( added_fill_cell )
01676          sed_cell_add( added_fill_cell , fill_cell );
01677    }
01678 
01679    return;
01680 }
01681 
01689 double get_closure_depth( Sed_cube p , Sed_wave wave )
01690 {
01691 //   return 25;
01692    return 3.*sed_wave_break_depth( wave );
01693 //   return sed_wave_length( wave );
01694 //   return 15;
01695 }
01696 
01697 double get_h_c( Sed_wave w )
01698 {
01699    double g = sed_gravity();
01700    double h = 1.25*sed_wave_height( w );
01701    double t = sed_wave_period( w );
01702    return 2.28*h - 6.85*( h*h / ( g * t*t ) );
01703 }
01704 
01711 double get_erosion_depth( double u )
01712 {
01713    double sua = 400;  // In Pa
01714    double sub = 0;    // In Pa/m
01715    double C_d = .004;
01716 
01717    eh_require( u>=0 );
01718 
01719    return (C_d*sed_rho_sea_water()*u*u-sub)/sua;
01720 }
01721 
01722 double* get_max_erosion_profile( Sed_cube p , Sed_wave w )
01723 {
01724    double* z_max = NULL;
01725 
01726    eh_require( p );
01727    eh_require( sed_cube_n_y(p)>0 );
01728    eh_require( w );
01729 
01730    z_max = eh_new( double , sed_cube_n_y(p) );
01731 
01732    if ( p && w )
01733    {
01734       gssize i;
01735       double z;
01736       double u;
01737       double h_b = sed_wave_break_depth( w );
01738 //      double h_b = get_h_c( w );
01739 
01740       for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
01741       {
01742          z = sed_cube_water_depth( p , 0 , i );
01743          if ( z>.1 )
01744          {
01745             u = get_near_bed_velocity( z , w , h_b );
01746             z_max[i] = get_erosion_depth( u ) + z;
01747          }
01748          else
01749             z_max[i] = z;
01750       }
01751    }
01752       
01753    return z_max;
01754 }
01755 
01767 double get_near_bed_velocity( double water_depth , Sed_wave w , double breaker_depth )
01768 {
01769    double u;
01770 
01771    // Assume that the near-bed velocity falls of linearly within the
01772    // breaker zone.
01773    if ( water_depth < breaker_depth )
01774       u = near_bed_velocity_func_mean( breaker_depth , w , breaker_depth )
01775         * pow( water_depth / breaker_depth , 1. ) ;
01776    else
01777       u = near_bed_velocity_func_mean( water_depth , w , breaker_depth );
01778 
01779    return u;
01780 }
01781 
01782 double near_bed_velocity_func_mean( double water_depth , Sed_wave w , double breaker_depth )
01783 {
01784 //   double alpha = (-atan(50*( w->h/water_depth-.5 ) ) + G_PI_2 )/G_PI;
01785    double alpha = (-atan(5*( sed_wave_height(w)/water_depth-.5 ) ) + G_PI_2 )/G_PI;
01786 
01787    alpha = 0.;
01788 
01789    return   (1.-alpha) * near_bed_velocity_func      ( water_depth , w , breaker_depth )
01790           +  alpha     * near_bed_velocity_func_komar( water_depth , w , breaker_depth );
01791 }
01792 
01808 double near_bed_velocity_func( double water_depth , Sed_wave w , double breaker_depth )
01809 {
01810    double gamma_b = .6; // breaker index varies from .4 - .8
01811 //   double breaker_depth = sed_wave_break_depth( w );
01812    return   .5*gamma_b
01813           * sqrt(sed_gravity()*breaker_depth)
01814           * pow(water_depth/breaker_depth,-.75);
01815 }
01816 
01831 double near_bed_velocity_func_komar( double water_depth ,
01832                                      Sed_wave w         ,
01833                                      double breaker_depth )
01834 {
01835    return sed_wave_frequency(w)*sed_wave_height(w) / ( 2.*sinh( sed_wave_number(w)*water_depth ) );
01836 }
01837 
01852 double near_bed_velocity_func_stokes( double water_depth ,
01853                                       Sed_wave w         ,
01854                                       double breaker_depth )
01855 {
01856    return .5*pow( sed_wave_number(w)*sed_wave_height(w)*.5/sinh(sed_wave_number(w)*water_depth) , 2. )
01857           * sed_wave_phase_velocity( w );
01858 }
01859 
01879 double get_grain_size_threshold( double orbital_velocity , double wave_period )
01880 {
01881    double rho   = sed_rho_sea_water();
01882    double rho_s = sed_rho_quartz();
01883    double g     = sed_gravity();
01884    double c_sq  = pow( rho/(.21*g*(rho_s-rho) ),2.);
01885    double orbital_diameter = orbital_velocity*wave_period/G_PI;
01886 
01887    return c_sq * pow(orbital_velocity,4.) / orbital_diameter;
01888 }
01889 
01890 /* @} */
01891 

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