/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/diffusion/diffusion.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 
00031 
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 "diffusion.h"
00039 
00040 // this defines the percent of maximum that the diffusion coefficient will be
00041 // at the supplied skin depth.
00042 #define SKIN_DEPTH_PERCENT (1.)
00043 
00044 #define DIFFUSION_OPT_FILL  (1<<0)
00045 #define DIFFUSION_OPT_LAND  (1<<1)
00046 #define DIFFUSION_OPT_WATER (1<<2)
00047 
00081 Sed_cell *diffuse_sediment( Sed_cube prof     , double k_max , 
00082                             double skin_depth , double dt    ,
00083                             int options )
00084 {
00085    Sed_cell *rem_cell, add_cell;
00086    Sed_cell *lost_cell;
00087    Sed_cell lost_left;
00088    Sed_cell lost_right;
00089    Sed_cell in_susp;
00090    Sed_cell added_fill;
00091    Sed_cell bedload_cell;
00092    double *just_bedload_fraction, *just_suspended_fraction;
00093    double *alpha_grain;
00094    double a, *k;
00095    double qx, *z, *u, *du, *dudx, *u_init;
00096    double dt_new;
00097    double depth;
00098    double dx;
00099    double u_0;
00100    long i, n, iter, n_iter=1;
00101    long remove_index, add_index;
00102    int n_grains, n_cols;
00103    Sed_facies facies;
00104    gssize *cols;
00105 
00106    eh_require( sed_cube_is_1d(prof) );
00107 
00108    sed_cube_find_all_river_mouths( prof );
00109 
00110    if ( options&DIFFUSION_OPT_LAND )
00111    {
00112       cols = sed_cube_find_column_above( prof , sed_cube_sea_level(prof) );
00113       if ( cols )
00114       {
00115          for ( n_cols=0 ;
00116                cols[n_cols]>=0 && cols[n_cols]+1==cols[n_cols+1] ;
00117                n_cols++ );
00118          if ( cols[n_cols]>=0 )
00119             n_cols++;
00120          eh_free( cols );
00121       }
00122       else
00123          n_cols = 0;
00124 
00125 //      n_cols = sed_find_all_river_mouths( prof );
00126 
00127       facies = S_FACIES_RIVER;
00128    }
00129    else
00130    {
00131       n_cols = sed_cube_n_y(prof);
00132       facies = S_FACIES_DIFFUSED;
00133    }
00134 
00135    if ( n_cols<3 )
00136       return NULL;
00137 
00138    //---
00139    // this will be the height to sea level.  the diffusion coefficient falls off
00140    // exponentially below this height and is constant above this height.
00141    //---
00142 //   u_0 = sed_get_floor_from_cube( prof , 0 , j_river );
00143    u_0 = sed_cube_sea_level( prof );
00144 
00145    n_grains = sed_sediment_env_n_types( );
00146    dx       = sed_cube_y_res( prof );
00147    
00148    //---
00149    // alpha_grain defines the ease at which different grain types can be moved.
00150    // values near zero are hard to move, values near one are easily moved.
00151    //---
00152    alpha_grain = sed_sediment_property( NULL , &sed_type_diff_coef );
00153 
00154    just_bedload_fraction   = eh_new0( double , n_grains );
00155    just_suspended_fraction = eh_new0( double , n_grains );
00156    for ( n=1 ; n<n_grains ; n++ )
00157    {
00158       just_suspended_fraction[n] = 1.;
00159    }
00160    just_suspended_fraction[0] = 0.;
00161    just_bedload_fraction[0]   = 1.;
00162 
00163    //---
00164    // If necessary, adjust the time step for stability.
00165    //---
00166    if ( k_max*dt/(dx*dx) > .5 )
00167    {
00168       dt_new=(dx*dx)/2./k_max;
00169       if ( options&DIFFUSION_OPT_LAND )
00170          dt_new /= 2.;
00171       if ( dt_new < dt )
00172       {
00173          n_iter=(int)(dt/dt_new)+1;
00174          dt=dt/n_iter;
00175       }
00176    }
00177 
00178    //---
00179    // a defines how quickly the diffusion coefficient falls off with depth.
00180    //---
00181    if ( skin_depth != 0 )
00182       a=(1./skin_depth)*log(SKIN_DEPTH_PERCENT/100.);
00183    else
00184       a=0;
00185 
00186 
00187    u_init   = eh_new( double   , n_cols );
00188    z        = eh_new( double   , n_cols );
00189    u        = eh_new( double   , n_cols );
00190    du       = eh_new( double   , n_cols );
00191    dudx     = eh_new( double   , n_cols );
00192    k        = eh_new( double   , n_cols );
00193    rem_cell = eh_new( Sed_cell , n_cols );
00194    for ( i=0 ; i<n_cols ; i++ )
00195       rem_cell[i] = sed_cell_new( n_grains );
00196    add_cell         = sed_cell_new( n_grains );
00197    bedload_cell     = sed_cell_new( n_grains );
00198    sed_cell_set_fraction( bedload_cell ,
00199                           just_bedload_fraction );
00200    in_susp    = sed_cell_new( n_grains );
00201    added_fill = sed_cell_new( n_grains );
00202    lost_left  = sed_cell_new( n_grains );
00203    lost_right = sed_cell_new( n_grains );
00204    lost_cell  = eh_new( Sed_cell , 4 );
00205    
00206    for ( iter=0 ; iter<n_iter ; iter++ )
00207    {
00208       //---
00209       // initialize these variables for each iteration.
00210       //---
00211       for ( i=0 ; i<n_cols ; i++ )
00212          sed_cell_clear( rem_cell[i] );
00213       sed_cell_clear( add_cell );
00214 
00215       //---
00216       // get the water depths at each point along the profile.
00217       //---
00218       for ( i=0 ; i<n_cols ; i++ )
00219          z[i] = sed_cube_water_depth( prof , 0 , i );
00220       
00221       //---
00222       // get diffusion constants.  the diffusion coefficient will fall
00223       // exponentially with depth below u_0 (the surface).
00224       //---
00225       if ( options&DIFFUSION_OPT_LAND )
00226          for ( i=0 ; i<n_cols ; i++ )
00227             k[i] = k_max;
00228       else
00229          for ( i=0 ; i<n_cols ; i++ )
00230          {
00231             depth = u_0 - sed_cube_top_height(prof,0,i);
00232             k[i] = k_max*exp(a*depth); 
00233             if ( k[i]>k_max ) k[i] = k_max;
00234             if ( depth < 0 ) k[i] = 0.;
00235          }
00236       
00237       //---
00238       // Get slopes.  Forward difference to find slope
00239       //---
00240       for ( i=0 ; i<n_cols-1 ; i++ )
00241          dudx[i] = -sed_cube_y_slope(prof,0,i);
00242       dudx[n_cols-1] = dudx[n_cols-2];
00243       dudx[0] = dudx[1];
00244       
00245       //---
00246       // Determine sediment fluxes between cells.
00247       // '+' means move to the right, '-' to the left find in meters
00248       //---
00249       for ( i=0 ; i<n_cols ; i++ )
00250       {
00251          qx = -k[i]*dudx[i];
00252          du[i] = qx*dt/dx;
00253       }
00254 
00255       //---
00256       // Determine the new elevations.
00257       //---
00258       if ( options&DIFFUSION_OPT_FILL )
00259       {
00260          for ( i=0 ; i<n_cols ; i++ )
00261             u_init[i] = sed_cube_top_height(prof,0,i);
00262          for ( i=1 ; i<n_cols-1 ; i++ )
00263             u[i] = u_init[i]
00264                  + ( k[i]*(u_init[i+1]-2*u_init[i]+u_init[i-1])/dx/dx
00265                    + (k[i+1]-k[i])/dx*(u_init[i+1]-u_init[i])/dx )*dt;
00266          u[0]            = u_init[0];
00267          u[n_cols-1] = u_init[n_cols-1];
00268       }
00269       
00270       //---
00271       // Remove the sediment that was diffused and move it to appropriate bins.
00272       // the amount of sediment to be moved (du[i]) is adjusted for grain size
00273       // by alpha_grain.  for easily moved grains alpha_grain will be near one,
00274       // for hard to move grains, alpha_grain will be near zero.
00275       //---
00276       for ( i=0 ; i<n_cols-1 ; i++ )
00277       {
00278          remove_index = (du[i]>0)?(i):(i+1);
00279          add_index    = (du[i]>0)?(i+1):(i);
00280 
00281          if ( fabs(du[i]) > 0 )
00282          {
00283             sed_column_separate_top( sed_cube_col(prof,remove_index) ,
00284                                      fabs(du[i]) ,
00285                                      alpha_grain ,
00286                                      add_cell );
00287             if ( options&DIFFUSION_OPT_LAND )
00288                sed_cell_move_fraction( add_cell ,
00289                                        in_susp ,
00290                                        just_suspended_fraction );
00291             sed_cell_add( rem_cell[add_index] , add_cell );
00292          }
00293 
00294 
00295       }
00296       
00297       //---
00298       // assume the the flux in (or out) of the first cell is the same as the
00299       // flux in (or out) of the second cell.
00300       //---
00301       if ( du[0] < 0 )
00302       {
00303          sed_column_separate_top( sed_cube_col(prof,0) ,
00304                                        -du[0] ,
00305                                        alpha_grain ,
00306                                        add_cell );
00307          sed_cell_add( lost_left , add_cell );
00308       }
00309       else
00310          sed_cell_copy( rem_cell[0] , rem_cell[1] );
00311             
00312       //---
00313       // do the same for the last cell.
00314       //---
00315       if ( du[n_cols-1] > 0 )
00316       {
00317          sed_column_separate_top( sed_cube_col(prof,n_cols-1) ,
00318                                        du[n_cols-1] ,
00319                                        alpha_grain ,
00320                                        add_cell );
00321          sed_cell_add( lost_right , add_cell );
00322       }
00323       else 
00324          sed_cell_copy( rem_cell[n_cols-1] , rem_cell[n_cols-2] );
00325             
00326       //---
00327       // Add the sediment that was diffused.
00328       //---
00329       for (i=0;i<n_cols;i++)
00330       {
00331          sed_cell_set_facies( rem_cell[i] , facies );
00332          sed_column_add_cell( sed_cube_col(prof,i) ,rem_cell[i]);
00333       }
00334 
00335       if ( options&DIFFUSION_OPT_FILL )
00336       {
00337          for ( i=0 ; i<n_cols ; i++ )
00338          {
00339             if ( u[i]-sed_cube_top_height(prof,0,i) > 1e-5 )
00340             {
00341                sed_cell_set_facies( bedload_cell , facies                               );
00342                sed_cell_set_age   ( bedload_cell , sed_cube_age_in_years(prof)          );
00343                sed_cell_resize    ( bedload_cell , u[i] - sed_cube_top_height(prof,0,i) );
00344 
00345                sed_column_add_cell( sed_cube_col(prof,i) , bedload_cell );
00346 
00347                sed_cell_add( added_fill , bedload_cell );
00348             }
00349          }
00350       }
00351 
00352    }
00353 
00354    lost_cell[0] = lost_left;
00355    lost_cell[1] = lost_right;
00356    lost_cell[2] = in_susp;
00357    lost_cell[3] = added_fill;
00358 
00359    sed_cell_destroy( add_cell );
00360    sed_cell_destroy( bedload_cell );
00361    for ( i=0 ; i<n_cols ; i++ )
00362       sed_cell_destroy( rem_cell[i] );
00363    eh_free( rem_cell );
00364    eh_free( z    );
00365    eh_free( u    );
00366    eh_free( du   );
00367    eh_free( dudx );
00368    eh_free( k    );
00369    eh_free( u_init );
00370    eh_free( alpha_grain             );
00371    eh_free( just_bedload_fraction   );
00372    eh_free( just_suspended_fraction );
00373    
00374    return lost_cell;
00375 }
00376 
00377 
00378 void get_diffusion_components( Eh_dbl_grid slope_dir ,
00379                                Eh_dbl_grid k_long    ,
00380                                Eh_dbl_grid k_cross   ,
00381                                Eh_dbl_grid k_x       ,
00382                                Eh_dbl_grid k_y );
00383 Eh_dbl_grid diffuse_grid( Eh_dbl_grid g , double **k_x , double **k_y ,
00384                           double dt     , double dx    , double dy );
00385 
00425 Sed_cell *diffuse_sediment_2( Sed_cube prof      , double k_long_max , 
00426                               double k_cross_max , double skin_depth ,
00427                               double dt          , int options )
00428 {
00429    Sed_cell **rem_cell_x, **rem_cell_y, **rem_cell, add_cell;
00430    Sed_cell_grid rem_cell_x_grid, rem_cell_y_grid, rem_cell_grid;
00431    Sed_cell *lost_cell;
00432    Sed_cell lost_left;
00433    Sed_cell lost_right;
00434    Sed_cell in_susp;
00435    Sed_cell added_fill;
00436    Sed_cell bedload_cell;
00437    Eh_dbl_grid u;
00438    Eh_dbl_grid dudx;
00439    Eh_dbl_grid dudy;
00440    Eh_dbl_grid slope_dir;
00441    Eh_dbl_grid k_long, k_cross;
00442    Eh_dbl_grid x_current, y_current;
00443    Eh_dbl_grid k_x, k_y;
00444    Eh_dbl_grid qx_grid, qy_grid;
00445    double **qx, **qy;
00446    double *just_bedload_fraction, *just_suspended_fraction;
00447    double *alpha_grain;
00448    double a, k_max, dt_new, depth;
00449    double dx, dy;
00450    double water_depth;
00451    gssize i, j, n, iter, n_iter=1;
00452    gssize remove_index, add_index;
00453    gssize n_x, n_y;
00454    gsize n_grains;
00455    Sed_facies facies;
00456 
00457    if ( options&DIFFUSION_OPT_LAND )
00458       facies = S_FACIES_RIVER;
00459    else
00460       facies = S_FACIES_DIFFUSED;
00461    
00462    n_grains = sed_sediment_env_n_types( );
00463    dx       = sed_cube_x_res( prof );
00464    dy       = sed_cube_y_res( prof );
00465 
00466    //---
00467    // alpha_grain defines the ease at which different grain types can be moved.
00468    // values near zero are hard to move, values near one are easily moved.
00469    //---
00470    alpha_grain = sed_sediment_property( NULL , &sed_type_diff_coef );
00471 
00472    just_bedload_fraction   = eh_new( double , n_grains );
00473    just_suspended_fraction = eh_new( double , n_grains );
00474    for ( n=1 ; n<n_grains ; n++ )
00475    {
00476       just_bedload_fraction[n]   = 0.;
00477       just_suspended_fraction[n] = 1.;
00478    }
00479    just_bedload_fraction[0]   = 1.;
00480    just_suspended_fraction[0] = 0.;
00481 
00482    //---
00483    // If necessary, adjust the time step for stability.
00484    //---
00485    k_max = sqrt( pow(k_long_max,2) + pow(k_cross_max,2) );
00486    if ( k_max*dt*(1./dx/dx+1./dy/dy) > .25 )
00487    {
00488       dt_new=.25/k_max/(1/dx/dx+1./dy/dy);
00489       dt_new /= 2;
00490       if ( options&DIFFUSION_OPT_LAND )
00491          dt_new /= 2.;
00492       if ( dt_new < dt )
00493       {
00494          n_iter=(int)(dt/dt_new)+1;
00495          dt=dt/n_iter;
00496       }
00497    }
00498 
00499    //---
00500    // a defines how quickly the diffusion coefficient falls off with depth.
00501    //---
00502    if ( skin_depth != 0 )
00503       a=(1./skin_depth)*log(SKIN_DEPTH_PERCENT/100.);
00504    else
00505       a=0;
00506 
00507    n_x = sed_cube_n_x( prof );
00508    n_y = sed_cube_n_y( prof );
00509 
00510    rem_cell_x_grid = sed_cell_grid_new( n_x , n_y );
00511    rem_cell_y_grid = sed_cell_grid_new( n_x , n_y );
00512    rem_cell_grid   = sed_cell_grid_new( n_x , n_y );
00513    sed_cell_grid_init( rem_cell_x_grid , n_grains );
00514    sed_cell_grid_init( rem_cell_y_grid , n_grains );
00515    sed_cell_grid_init( rem_cell_grid   , n_grains );
00516    k_x           = eh_grid_new( double , n_x , n_y );
00517    k_y           = eh_grid_new( double , n_x , n_y );
00518    k_long        = eh_grid_new( double , n_x , n_y );
00519    k_cross       = eh_grid_new( double , n_x , n_y );
00520    x_current     = eh_grid_new( double , n_x , n_y );
00521    y_current     = eh_grid_new( double , n_x , n_y );
00522 /*
00523    qx_grid       = eh_create_dbl_grid( prof->n_x+2 , prof->n_y+2 );
00524    qy_grid       = eh_create_dbl_grid( prof->n_x+2 , prof->n_y+2 );
00525 */
00526    qx_grid       = eh_grid_new( double , n_x , n_y );
00527    qy_grid       = eh_grid_new( double , n_x , n_y );
00528 //   eh_reindex_grid( qx_grid , -1 , -1 );
00529 //   eh_reindex_grid( qy_grid , -1 , -1 );
00530    add_cell      = sed_cell_new( n_grains );
00531    bedload_cell  = sed_cell_new( n_grains );
00532    sed_cell_set_fraction( bedload_cell ,
00533                           just_bedload_fraction );
00534    in_susp    = sed_cell_new( n_grains );
00535    added_fill = sed_cell_new( n_grains );
00536    lost_left  = sed_cell_new( n_grains );
00537    lost_right = sed_cell_new( n_grains );
00538    lost_cell  = eh_new( Sed_cell , 4 );
00539 
00540    rem_cell_x = sed_cell_grid_data( rem_cell_x_grid );
00541    rem_cell_y = sed_cell_grid_data( rem_cell_y_grid );
00542    rem_cell   = sed_cell_grid_data( rem_cell_grid   );
00543    qx         = eh_dbl_grid_data( qx_grid );
00544    qy         = eh_dbl_grid_data( qy_grid );
00545 
00546    for ( i=0 ; i<eh_grid_n_x(x_current) ; i++ )
00547       for ( j=0 ; j<eh_grid_n_y(x_current) ; j++ )
00548       {
00549          eh_dbl_grid_set_val( x_current , i , j ,
00550                                  -2
00551                                * (eh_grid_n_x(x_current)-i)/(double)eh_grid_n_x(x_current)
00552                                * j/(double)eh_grid_n_y(x_current) );
00553          eh_dbl_grid_set_val( y_current , i , j , 0. );
00554       }
00555    
00556    for ( iter=0 ; iter<n_iter ; iter++ )
00557    {
00558 eh_message( "initialize grids to zero" );
00559       //---
00560       // initialize these variables for each iteration.
00561       //---
00562       for ( i=0 ; i<n_x ; i++ )
00563          for ( j=0 ; j<n_y ; j++ )
00564          {
00565             sed_cell_clear( rem_cell_x[i][j] );
00566             sed_cell_clear( rem_cell_y[i][j] );
00567             sed_cell_clear( rem_cell[i][j]   );
00568          }
00569       sed_cell_clear( add_cell );
00570       
00571 eh_message( "calculate diffusion coefficients" );
00572       //---
00573       // get diffusion constants.  the diffusion coefficient will fall
00574       // exponentially with depth below the water surface.
00575       //---
00576       if ( options&DIFFUSION_OPT_LAND )
00577          for ( i=0 ; i<n_x; i++ )
00578             for ( j=0 ; j<n_y; j++ )
00579             {
00580                eh_dbl_grid_set_val( k_long  , i , j , k_long_max  );
00581                eh_dbl_grid_set_val( k_cross , i , j , k_cross_max );
00582             }
00583       else
00584          for ( i=0 ; i<n_x; i++ )
00585             for ( j=0 ; j<n_y; j++ )
00586             {
00587                depth = sed_cube_water_depth(prof,i,j);
00588                if ( depth > 0 )
00589                {
00590                   eh_dbl_grid_set_val( k_long  , i , j , k_long_max *exp(a*depth) );
00591                   eh_dbl_grid_set_val( k_cross , i , j , k_cross_max*exp(a*depth) );
00592                   eh_clamp( eh_dbl_grid_data(k_long) [i][j] , 0 , k_long_max );
00593                   eh_clamp( eh_dbl_grid_data(k_cross)[i][j] , 0 , k_cross_max );
00594                }
00595                else
00596                {
00597                   eh_dbl_grid_set_val( k_long  , i , j , 0. );
00598                   eh_dbl_grid_set_val( k_cross , i , j , 0. );
00599                }
00600             }
00601 
00602       slope_dir = sed_cube_slope_dir_grid( prof , NULL );
00603       get_diffusion_components( slope_dir , k_long , k_cross , k_x , k_y );
00604       
00605 eh_message( "calculate seafloor slopes" );
00606       //---
00607       // Get slopes.  Forward difference to find slope
00608       //---
00609       dudx = sed_cube_x_slope_grid( prof , NULL );
00610       dudy = sed_cube_y_slope_grid( prof , NULL );
00611       
00612 eh_message( "calculate sediment fluxes" );
00613       //---
00614       // Determine sediment fluxes between cells.
00615       // '+' means move to the right, '-' to the left
00616       //---
00617       for ( i=0 ; i<n_x ; i++ )
00618       {
00619          for ( j=0 ; j<n_y ; j++ )
00620          {
00621             qy[i][j] = eh_dbl_grid_val(k_y,i,j)*eh_dbl_grid_val(dudy,i,j)*dt/dy;
00622             qx[i][j] = eh_dbl_grid_val(k_x,i,j)*eh_dbl_grid_val(dudx,i,j)*dt/dx;
00623 /*
00624             qy[i][j] = k_y->data[i][j]*dudy->data[i][j]*dt/dy
00625                      + y_current->data[i][j]*dt/dy;
00626             qx[i][j] = k_x->data[i][j]*dudx->data[i][j]*dt/dx
00627                      + x_current->data[i][j]*dt/dx;
00628             long_shore = slope_dir->data[i][j] + M_PI_2;
00629             long_shore = 0;
00630             qy[i][j] = x_current->data[i][j]*dt/dy*sin( long_shore );
00631             qx[i][j] = x_current->data[i][j]*dt/dx*cos( long_shore );
00632 */
00633          }
00634       }
00635 
00636       eh_grid_destroy( slope_dir , TRUE );
00637 /*
00638       for ( i=0 ; i<prof->n_x ; i++ )
00639       {
00640 //         qy[i][0]        = qy[i][1];
00641          qy[i][-1]          = qy[i][0];
00642          qy[i][prof->n_y-1] = qy[i][prof->n_y-2];
00643 //         qy[i][prof->n_x] = qy[i][prof->n_x-1];
00644 //         qy[i][-1]        = 0;
00645 //         qy[i][prof->n_x] = 0;
00646       }
00647       for ( j=0 ; j<prof->n_y ; j++ )
00648       {
00649 //         qx[0][j]        = qx[1][j];
00650          qx[-1][j]          = qx[0][j];
00651          qx[prof->n_x-1][j] = qx[prof->n_x-2][j];
00652 //         qx[prof->n_y][j] = qx[prof->n_y-1][j];
00653 //         qx[-1][j]        = 0;
00654 //         qx[prof->n_y][j] = 0;
00655       }
00656       qx[-1][-1] = 0;
00657       qy[-1][-1] = 0;
00658 */
00659       eh_grid_destroy( dudx , TRUE );
00660       eh_grid_destroy( dudy , TRUE );
00661 
00662       //---
00663       // Determine the new elevations.
00664       //---
00665       if ( options&DIFFUSION_OPT_FILL )
00666       {
00667 eh_require_not_reached();
00668          u = sed_cube_water_depth_grid( prof , NULL );
00669          u = diffuse_grid( u , eh_dbl_grid_data(k_x) , eh_dbl_grid_data(k_y) , dt , dx , dy );
00670       }
00671 
00672 /*
00673       for ( i=0 ; i<prof->n_x ; i++ )
00674          for ( j=0 ; j<prof->n_y ; j++ )
00675          {
00676 sed_cell_clear( add_cell , n_grains );
00677 sed_cell_clear( rem_cell[i][j], n_grains );
00678             q = fabs(qx[i][j]) + fabs(qy[i][j]);
00679             if ( q>0 )
00680             {
00681                sed_column_separate_top( prof->col[i][j] ,
00682                                              q               ,
00683                                              alpha_grain     ,
00684                                              add_cell );
00685                sed_add_cell_to_cell( rem_cell[i][j] ,
00686                                      add_cell       ,
00687                                      n_grains );
00688 eh_watch_dbl( q );
00689 eh_watch_int( i );
00690 eh_watch_int( j );
00691 eh_watch_dbl( add_cell->thickness );
00692 eh_watch_dbl( rem_cell[i][j]->thickness );
00693             }
00694          }
00695             
00696       for ( i=0 ; i<prof->n_x ; i++ )
00697       {
00698          for ( j=-1 ; j<prof->n_y+1 ; j++ )
00699          {
00700             remove_index = j;
00701             add_index    = (qy[i][j]>0)?(j+1):(j-1);
00702             if ( fabs( qy[i][j] ) > 0 )
00703             {
00704 sed_cell_clear( add_cell , n_grains );
00705 f = fabs( qy[i][j] ) / ( fabs(qy[i][j] ) + fabs( qx[i][j] ) );
00706 if ( f>1 )
00707    eh_watch_dbl( f );
00708                if ( is_in_domain( prof->n_x , prof->n_y , i , remove_index ) )
00709                {
00710                   sed_copy_cell( add_cell , rem_cell[i][j] , n_grains );
00711                   sed_cell_resize(
00712                      add_cell ,
00713                      add_cell->thickness
00714                      * fabs( qy[i][j] )/(fabs(qx[i][j])+fabs(qy[i][j]) ) );
00715 eh_watch_dbl( qy[i][j] );
00716 eh_watch_dbl( qx[i][j] );
00717 eh_watch_dbl( rem_cell[i][j]->thickness );
00718 eh_watch_dbl( add_cell->thickness );
00719                }
00720                else if ( is_in_domain( prof->n_x , prof->n_y , i , add_index ) )
00721                {
00722                   sed_copy_cell( add_cell , rem_cell[i][add_index] , n_grains );
00723                   sed_cell_resize(
00724                      add_cell ,
00725                      add_cell->thickness
00726                      * fabs( qy[i][j] )/(fabs(qx[i][j])+fabs(qy[i][j]) ) );
00727                }
00728                else
00729                   sed_cell_clear( add_cell , n_grains );
00730 
00731 if ( add_cell->thickness > fabs( qy[i][j] ) )
00732    eh_watch_dbl( add_cell->thickness );
00733 
00734                if ( options&DIFFUSION_OPT_FILL )
00735                   sed_move_sediment_to_cell_by_fraction(
00736                      add_cell                ,
00737                      in_susp                 ,
00738                      just_suspended_fraction ,
00739                      n_grains );
00740 
00741                if ( is_in_domain( prof->n_x , prof->n_y , i , add_index ) )
00742 {
00743                   sed_add_cell_to_cell( rem_cell_y[i][add_index] ,
00744                                         add_cell                 ,
00745                                         n_grains );
00746 eh_watch_dbl( rem_cell_y[i][add_index]->thickness );
00747 eh_watch_int( i );
00748 eh_watch_int( add_index );
00749 }
00750                else
00751                   sed_add_cell_to_cell( lost_left , add_cell , n_grains );
00752             }
00753          }
00754       }
00755 
00756       for ( i=-1 ; i<prof->n_x+1 ; i++ )
00757       {
00758          for ( j=0 ; j<prof->n_y ; j++ )
00759          {
00760             remove_index = i;
00761             add_index    = (qx[i][j]>0)?(i+1):(i-1);
00762             if ( fabs( qx[i][j] ) > 0 )
00763             {
00764 sed_cell_clear( add_cell , n_grains );
00765 f = fabs( qx[i][j] ) / ( fabs(qy[i][j] ) + fabs( qx[i][j] ) );
00766 if ( f>1 )
00767    eh_watch_dbl( f );
00768                if ( is_in_domain( prof->n_x , prof->n_y , remove_index , j ) )
00769                {
00770                   sed_copy_cell( add_cell , rem_cell[i][j] , n_grains );
00771                   sed_cell_resize(
00772                      add_cell ,
00773                      add_cell->thickness
00774                      * fabs( qx[i][j] )/(fabs(qx[i][j])+fabs(qy[i][j]) ) );
00775                }
00776                else if ( is_in_domain( prof->n_x , prof->n_y , add_index , j ) )
00777                {
00778                   sed_copy_cell( add_cell , rem_cell[add_index][j] , n_grains );
00779                   sed_cell_resize(
00780                      add_cell ,
00781                      add_cell->thickness
00782                      * fabs( qx[i][j] )/(fabs(qx[i][j])+fabs(qy[i][j]) ) );
00783                }
00784                else
00785                   sed_cell_clear( add_cell , n_grains );
00786 
00787 if ( add_cell->thickness > fabs( qx[i][j] ) )
00788    eh_watch_dbl( add_cell->thickness );
00789 
00790                if ( options&DIFFUSION_OPT_FILL )
00791                   sed_move_sediment_to_cell_by_fraction(
00792                      add_cell                ,
00793                      in_susp                 ,
00794                      just_suspended_fraction ,
00795                      n_grains );
00796 
00797                if ( is_in_domain( prof->n_x , prof->n_y , add_index , j ) )
00798                   sed_add_cell_to_cell( rem_cell_x[add_index][j] ,
00799                                         add_cell                 ,
00800                                         n_grains );
00801                else
00802                   sed_add_cell_to_cell( lost_left , add_cell , n_grains );
00803             }
00804          }
00805       }
00806 
00807 */
00808 
00809 eh_message( "remove the diffused sediment" );
00810       //---
00811       // Remove the sediment that was diffused and move it to appropriate bins.
00812       // the amount of sediment to be moved (du[i]) is adjusted for grain size
00813       // by alpha_grain.  for easily moved grains alpha_grain will be near one,
00814       // for hard to move grains, alpha_grain will be near zero.
00815       //---
00816       for ( i=0 ; i<n_x ; i++ )
00817       {
00818 //         for ( j=-1 ; j<n_y ; j++ )
00819          for ( j=0 ; j<n_y-1 ; j++ )
00820          {
00821 
00822             //---
00823             // Calculate the sediment flux in the y-direction.  For a positive
00824             // flux, move sediment from this cell to the next.  For a negative
00825             // flux, move sediment from the next cell to this one.  If the
00826             // flux moves the sediment out of the domain, remove the sediment
00827             // from this cell and add it to the accumulated lost sediment.
00828             // If the flux moves sediment into the domain, assume that the
00829             // flux into this cell is the same as that leaving this cell.
00830             // Thus, the final height of this cell will remain unchanged.
00831             //---
00832             remove_index = (qy[i][j]>0)?(j):(j+1);
00833             add_index    = (qy[i][j]>0)?(j+1):(j);
00834 //            remove_index = j;
00835 //            add_index    = (qy[i][j]>0)?(j+1):(j-1);
00836             if ( fabs( qy[i][j] ) > 0 )
00837             {
00838 //               if ( is_in_domain( prof->n_x , prof->n_y , i , remove_index ) )
00839                if ( remove_index != 0 && remove_index != n_y-1 )
00840                   sed_column_separate_top( sed_cube_col_ij(prof,i,remove_index) ,
00841                                            fabs(qy[i][j])                       ,
00842                                            alpha_grain                          ,
00843                                            add_cell );
00844 //               else if ( is_in_domain( prof->n_x , prof->n_y , i , add_index ) )
00845                else 
00846                   sed_column_top( sed_cube_col_ij(prof,i,remove_index) ,
00847                                   fabs(qy[i][j])             ,
00848                                   add_cell );
00849 //               else
00850 //                  sed_cell_clear( add_cell , n_grains );
00851 
00852                if ( options&DIFFUSION_OPT_FILL )
00853                   sed_cell_move_fraction( add_cell                ,
00854                                           in_susp                 ,
00855                                           just_suspended_fraction );
00856 
00857                if ( sed_cube_is_in_domain( prof , i , add_index ) )
00858                   sed_cell_add( rem_cell_y[i][add_index] , add_cell );
00859                else
00860                   sed_cell_add( lost_left , add_cell );
00861             }
00862          }
00863       }
00864 
00865 
00866       //---
00867       // Now do the fluxes in the x-direction.
00868       //---
00869 //      for ( i=-1 ; i<prof->n_x ; i++ )
00870       for ( i=0 ; i<n_x-1 ; i++ )
00871       {
00872          for ( j=0 ; j<n_y ; j++ )
00873          {
00874             remove_index = (qx[i][j]>0)?(i):(i+1);
00875             add_index    = (qx[i][j]>0)?(i+1):(i);
00876 //            remove_index = i;
00877 //            add_index    = (qx[i][j]>0)?(i+1):(i-1);
00878 
00879             if ( fabs( qx[i][j] ) > 0 )
00880             {
00881 //               if ( is_in_domain( prof->n_x , prof->n_y , remove_index , j ) )
00882                if ( remove_index != 0 && remove_index != n_x-1 )
00883                   sed_column_separate_top( sed_cube_col_ij(prof,remove_index,j) ,
00884                                            fabs(qx[i][j])             ,
00885                                            alpha_grain                ,
00886                                            add_cell );
00887 //               else if ( is_in_domain( prof->n_x , prof->n_y , add_index , j ) )
00888                else
00889                   sed_column_top( sed_cube_col_ij(prof,remove_index,j) ,
00890                                   fabs(qx[i][j])             ,
00891                                   add_cell );
00892 //               else
00893 //                  sed_cell_clear( add_cell , n_grains );
00894 
00895                if ( options&DIFFUSION_OPT_FILL )
00896                   sed_cell_move_fraction( add_cell                ,
00897                                           in_susp                 ,
00898                                           just_suspended_fraction );
00899 
00900                if ( sed_cube_is_in_domain( prof , add_index , j ) )
00901                   sed_cell_add( rem_cell_x[add_index][j] , add_cell );
00902                else
00903                   sed_cell_add( lost_left , add_cell );
00904             }
00905          }
00906       }
00907       
00908 eh_message( "add the diffused sediment" );
00909       //---
00910       // Add the sediment that was diffused.
00911       //---
00912       for ( i=0 ; i<n_x ; i++ )
00913          for ( j=0 ; j<n_y ; j++ )
00914          {
00915             sed_cell_copy( add_cell , rem_cell_x[i][j] );
00916             sed_cell_add( add_cell , rem_cell_y[i][j] );
00917             sed_cell_set_facies( add_cell , facies );
00918 
00919             water_depth = sed_cube_water_depth( prof , i , j );
00920             if ( sed_cell_size(add_cell) > water_depth )
00921                sed_cell_resize( add_cell , eh_max( water_depth , 0 ) );
00922 
00923             sed_column_add_cell( sed_cube_col_ij(prof,i,j) , add_cell );
00924          }
00925 
00926       for ( i=0 ; i<n_x ; i++ )
00927       {
00928          sed_cell_clear( add_cell );
00929          if ( qy[i][0] < 0 )
00930             sed_column_separate_top( sed_cube_col_ij(prof,i,0) ,
00931                                           fabs(qy[i][0])  ,
00932                                           alpha_grain     ,
00933                                           add_cell );
00934          else
00935          {
00936 /*
00937             sed_get_top_from_column( prof->col[i][0] ,
00938                                      fabs(qy[i][0])  ,
00939                                      add_cell );
00940             sed_column_add_cell( prof->col[i][1] , add_cell );
00941 */
00942          }
00943          sed_cell_clear( add_cell );
00944          if ( qy[i][n_y-1] > 0 )
00945             sed_column_separate_top( sed_cube_col_ij(prof,i,n_y-1) ,
00946                                      fabs(qy[i][n_y-1])            ,
00947                                      alpha_grain                   ,
00948                                      add_cell );
00949          else
00950          {
00951 /*
00952             sed_get_top_from_column( prof->col[i][prof->n_y-1] ,
00953                                      fabs(qy[i][prof->n_y-1])  ,
00954                                      add_cell );
00955 
00956             water_depth = sed_get_depth_from_cube( prof , i , prof->n_y-1 );
00957             if ( add_cell->thickness > water_depth )
00958                sed_cell_resize( add_cell , eh_max( water_depth , 0 ) );
00959 
00960             sed_column_add_cell( prof->col[i][prof->n_y-2] , add_cell );
00961 */
00962          }
00963       }
00964 
00965       for ( j=0 ; j<n_y ; j++ )
00966       {
00967          sed_cell_clear( add_cell );
00968          if ( qx[0][j] < 0 )
00969             sed_column_separate_top( sed_cube_col_ij(prof,0,j) ,
00970                                           fabs(qx[0][j])  ,
00971                                           alpha_grain     ,
00972                                           add_cell );
00973          else
00974          {
00975 /*
00976             sed_get_top_from_column( prof->col[0][j] ,
00977                                      fabs(qx[0][j])  ,
00978                                      add_cell );
00979             sed_column_add_cell( prof->col[1][j] , add_cell );
00980 */
00981          }
00982          sed_cell_clear( add_cell );
00983          if ( qx[n_x-1][j] > 0 )
00984             sed_column_separate_top( sed_cube_col_ij(prof,n_x-1,j) ,
00985                                      fabs(qx[n_x-1][j])            ,
00986                                      alpha_grain                   ,
00987                                      add_cell );
00988          else
00989          {
00990 /*
00991             sed_get_top_from_column( prof->col[prof->n_x-1][j] ,
00992                                      fabs(qx[prof->n_x-1][j])  ,
00993                                      add_cell );
00994 
00995             water_depth = sed_get_depth_from_cube( prof , prof->n_x-1 , j );
00996             if ( add_cell->thickness > water_depth )
00997                sed_cell_resize( add_cell , eh_max( water_depth , 0 ) );
00998 
00999             sed_column_add_cell( prof->col[prof->n_x-2][j] , add_cell );
01000 */
01001          }
01002       }
01003 
01004       if ( options&DIFFUSION_OPT_FILL )
01005       {
01006 eh_require_not_reached();
01007          for ( i=0 ; i<n_x ; i++ )
01008             for ( j=0 ; j<n_y ; j++ )
01009             {
01010                if ( eh_dbl_grid_val(u,i,j)-sed_cube_water_depth(prof,i,j) > 1e-5 )
01011                {
01012                   sed_cell_set_facies( bedload_cell , facies );
01013                   sed_cell_resize( bedload_cell ,
01014                                      eh_dbl_grid_val(u,i,j)
01015                                    - sed_cube_water_depth(prof,i,j) );
01016                   sed_column_add_cell( sed_cube_col_ij(prof,i,j) , bedload_cell );
01017                   sed_cell_add( added_fill , bedload_cell );
01018                }
01019             }
01020       }
01021 
01022    }
01023 
01024    lost_cell[0] = lost_left;
01025    lost_cell[1] = lost_right;
01026    lost_cell[2] = in_susp;
01027    lost_cell[3] = added_fill;
01028 
01029    for ( i=0 ; i<4 ; i++ )
01030       sed_cell_destroy( lost_cell[i] );
01031    eh_free( lost_cell );
01032    lost_cell = NULL;
01033 
01034    sed_cell_destroy( add_cell     );
01035    sed_cell_destroy( bedload_cell );
01036    sed_cell_grid_free( rem_cell_x_grid );
01037    sed_cell_grid_free( rem_cell_y_grid );
01038    sed_cell_grid_free( rem_cell_grid   );
01039 
01040    eh_grid_destroy( k_long        , TRUE );
01041    eh_grid_destroy( k_cross       , TRUE );
01042    eh_grid_destroy( x_current     , TRUE );
01043    eh_grid_destroy( y_current     , TRUE );
01044    eh_grid_destroy( k_x           , TRUE );
01045    eh_grid_destroy( k_y           , TRUE );
01046    eh_grid_destroy( qx_grid       , TRUE );
01047    eh_grid_destroy( qy_grid       , TRUE );
01048    eh_grid_destroy( rem_cell_x_grid , TRUE );
01049    eh_grid_destroy( rem_cell_y_grid , TRUE );
01050    eh_grid_destroy( rem_cell_grid   , TRUE );
01051 
01052    if ( options&DIFFUSION_OPT_FILL )
01053       eh_grid_destroy( u , TRUE );
01054    eh_free(alpha_grain);
01055    eh_free(just_bedload_fraction);
01056    eh_free(just_suspended_fraction);
01057    
01058    return lost_cell;
01059 }
01060 
01061 void get_diffusion_components( Eh_dbl_grid slope_dir ,
01062                                Eh_dbl_grid k_long    ,
01063                                Eh_dbl_grid k_cross   ,
01064                                Eh_dbl_grid k_x       ,
01065                                Eh_dbl_grid k_y )
01066 {
01067    gsize i, j;
01068 
01069    eh_require( slope_dir );
01070    eh_require( k_long    );
01071    eh_require( k_cross   );
01072    eh_require( k_x       );
01073    eh_require( k_y       );
01074    eh_require( eh_grid_is_compatible( slope_dir , k_long  ) );
01075    eh_require( eh_grid_is_compatible( slope_dir , k_cross ) );
01076    eh_require( eh_grid_is_compatible( slope_dir , k_x     ) );
01077    eh_require( eh_grid_is_compatible( slope_dir , k_y     ) );
01078 
01079    for ( i=0 ; i<eh_grid_n_x(slope_dir) ; i++ )
01080       for ( j=0 ; j<eh_grid_n_y(slope_dir) ; j++ )
01081       {
01082          eh_dbl_grid_set_val( k_x , i , j , fabs(   eh_dbl_grid_val(k_cross,i,j)
01083                                                   * cos( eh_dbl_grid_val(slope_dir,i,j) ) )
01084                                                   + fabs(   eh_dbl_grid_val(k_long,i,j)
01085                                                   * sin( eh_dbl_grid_val(slope_dir,i,j) ) ) );
01086          eh_dbl_grid_set_val( k_y , i , j , fabs(   eh_dbl_grid_val(k_cross,i,j)
01087                                                   * sin( eh_dbl_grid_val(slope_dir,i,j) ) )
01088                                                   + fabs(   eh_dbl_grid_val(k_long,i,j)
01089                                                   * cos( eh_dbl_grid_val(slope_dir,i,j) ) ) );
01090       }
01091 
01092    return;
01093 }
01094 
01106 Eh_dbl_grid diffuse_grid( Eh_dbl_grid g , double **k_x , double **k_y ,
01107                           double dt     , double dx    , double dy )
01108 {
01109    gsize i, j;
01110    Eh_dbl_grid g_temp = eh_grid_new( double , eh_grid_n_x(g) , eh_grid_n_y(g) );
01111    double **u = eh_dbl_grid_data(g);
01112    gssize n_x = eh_grid_n_x( g );
01113    gssize n_y = eh_grid_n_y( g );
01114 
01115    for ( i=1 ; i<=n_x ; i++ )
01116       for ( j=1 ; j<=n_y ; j++ )
01117          eh_dbl_grid_set_val( g_temp , i , j ,
01118                               (   u[i-1][j] * k_x[i][j] 
01119                                 - u[i][j]   * ( k_x[i][j] + k_x[i+1][j] )
01120                                 + u[i+1][j] * k_x[i+1][j] ) * dt / (dx * dx)
01121                             + (   u[i][j-1] * k_y[i][j] 
01122                                 - u[i][j]   * ( k_y[i][j] + k_y[i][j+1] )
01123                                 + u[i][j+1] * k_y[i][j+1] ) * dt / (dy * dy) );
01124    for ( j=0 ; j<n_y ; j++ )
01125    {
01126       eh_dbl_grid_set_val( g_temp , 0     , j     , u[0][j]     );
01127       eh_dbl_grid_set_val( g_temp , n_x-1 , j     , u[n_x-1][j] );
01128    }
01129    for ( i=0 ; i<n_x ; i++ )
01130    {
01131       eh_dbl_grid_set_val( g_temp , i     , 0     , u[i][0]     );
01132       eh_dbl_grid_set_val( g_temp , i     , n_y-1 , u[i][n_y-1] );
01133    }
01134 
01135    eh_grid_set_data( g      , eh_grid_data(g_temp) );
01136    eh_grid_set_data( g_temp , (void**)u            );
01137 
01138    eh_grid_destroy( g_temp , TRUE );
01139 
01140    return g;
01141 }
01142 

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