/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/bio/bio_sed_interface.c

Go to the documentation of this file.
00001 #define BIO_PROCESS_NAME_S "bioturbation"
00002 #define EH_LOG_DOMAIN BIO_PROCESS_NAME_S
00003 
00004 #include <glib.h>
00005 #include <utils/utils.h>
00006 #include <sed/sed_sedflux.h>
00007 #include "bio.h"
00008 
00009 G_GNUC_INTERNAL Sed_cell* bio_array_to_cell_array( Sed_cell* c_arr , double** data );
00010 G_GNUC_INTERNAL double**  sed_array_to_bio_array ( Sed_cell* c_arr , gint* n_grains , gint* n_layers );
00011 G_GNUC_INTERNAL void      sed_column_bioturbate  ( Sed_column c , double depth , double k , double duration , Bio_method m );
00012 
00013 #include <stdio.h>
00014 #include <sed/sed_sedflux.h>
00015 #include "bio.h"
00016 
00017 typedef struct
00018 {
00019    Eh_input_val k;
00020    Eh_input_val r;
00021    Eh_input_val depth;
00022    Bio_method   method;
00023 }
00024 Bio_param_t;
00025 
00026 static double bio_k;
00027 static double bio_r;
00028 
00029 static const GOptionEntry bio_args[] =
00030 {
00031    { "bio-k"     , 0 , 0 , G_OPTION_ARG_DOUBLE , &bio_k , "Set bioturbation diffusion coefficient (cm^2/y)" , "VAL" } ,
00032    { "bio-r"     , 0 , 0 , G_OPTION_ARG_DOUBLE , &bio_r , "Set bioturbation conveyor rate (cm/d)"           , "VAL" } ,
00033    { "bio-depth" , 0 , 0 , G_OPTION_ARG_DOUBLE , &bio_r , "Set depth of bioturbation (m)"                   , "VAL" } ,
00034    { NULL }
00035 };
00036 
00037 GOptionGroup*
00038 bio_get_option_group( void )
00039 {
00040    GOptionGroup* g = NULL;
00041 
00042    g = g_option_group_new( "bioturbation" , "Bioturbation options" , "Show Bioturbation options" , NULL , NULL );
00043    g_option_group_add_entries( g , bio_args );
00044 
00045    return g;
00046 }
00047 
00048 Sed_process_info
00049 bio_run( Sed_process proc , Sed_cube p )
00050 {
00051    Bio_param_t*     data = sed_process_user_data(proc);
00052    Sed_process_info info = SED_EMPTY_INFO;
00053 
00054    eh_require( data               );
00055    eh_require( data->depth        );
00056    eh_require( data->k || data->r );
00057 
00058    if ( data )
00059    {
00060       gint   i;
00061       gint   len   = sed_cube_size                ( p );
00062       double dt    = sed_cube_time_step_in_seconds( p );
00063       double time  = sed_cube_age_in_years        ( p );
00064       double depth = eh_input_val_eval( data->depth , time );
00065       double k;
00066       double r;
00067       double val;
00068 
00069       // Convert k from cm^2/y to m^2/s. Convert r from cm/d to m/s
00070       if ( data->k ) k = eh_input_val_eval( data->k , time ) * 1e-4/S_SECONDS_PER_YEAR;
00071       if ( data->r ) r = eh_input_val_eval( data->r , time ) * 1e-2/S_SECONDS_PER_DAY;
00072 
00073       switch ( data->method )
00074       {
00075          case BIO_METHOD_DIFFUSION: val = k; break;
00076          case BIO_METHOD_CONVEYOR : val = r; break;
00077          default: eh_require_not_reached();
00078       }
00079 
00080       eh_require( val>0   );
00081       eh_require( depth>0 );
00082       eh_require( dt>0    );
00083 
00084 //      EH_MEM_LEAK_START
00085 
00086       for ( i=0 ; i<len ; i++ ) sed_column_bioturbate( sed_cube_col(p,i) , depth , val , dt , data->method );
00087 
00088 //      EH_MEM_LEAK_END_WARN
00089    }
00090 
00091    return info;
00092 }
00093 
00094 /*
00095 typedef enum
00096 {
00097    BIO_KEY_MODEL ,
00098    BIO_KEY_DEPTH ,
00099    BIO_KEY_K ,
00100    BIO_KEY_R
00101 };
00102 
00103 static const gchar* bio_default_val[] =    { [BIO_KEY_MODEL] = "diffusion" ,
00104                                              [BIO_KEY_DEPTH] = ".1"        ,
00105                                              [BIO_KEY_K]     = "50."       ,
00106                                              [BIO_KEY_R]     = ".001" };
00107 static const gchar* bio_req_label[] =      { [BIO_KEY_MODEL] = "Bioturbation model" ,
00108                                              [BIO_KEY_DEPTH] = "Depth of bioturbation" };
00109 static const gchar* bio_diff_req_label[] = { [BIO_KEY_K]     = "Diffusion coefficient" };
00110 static const gchar* bio_conv_req_label[] = { [BIO_KEY_R]     = "Conveyor rate"         };
00111 */
00112 
00113 #define BIO_KEY_DEPTH   "depth of bioturbation"
00114 #define BIO_KEY_MODEL   "bioturbation model"
00115 #define BIO_KEY_K       "diffusion coefficient"
00116 #define BIO_KEY_R       "conveyor rate"
00117 
00118 static gchar* bio_diff_req_label[] = { BIO_KEY_K     , NULL };
00119 static gchar* bio_conv_req_label[] = { BIO_KEY_R     , NULL };
00120 static gchar* bio_req_label     [] = { BIO_KEY_DEPTH , BIO_KEY_MODEL , NULL };
00121 
00122 /*
00123 gint
00124 bio_fprint_kvf( FILE* fp )
00125 {
00126    gint n = 0;
00127 
00128    eh_require(fp);
00129 
00130    if ( fp )
00131    {
00132       n += fprintf( fp , "%s : %s\n" , bio_req_label[BIO_KEY_DEPTH] , bio_default_val[BIO_KEY_DEPTH] );
00133       n += fprintf( fp , "%s : %s\n" , bio_req_label[BIO_KEY_MODEL] , bio_default_val[BIO_KEY_MODEL] );
00134       n += fprintf( fp , "%s : %s\n" , bio_req_label[BIO_KEY_K]     , bio_default_val[BIO_KEY_K]     );
00135    }
00136 
00137    return n;
00138 }
00139 */
00140 
00141 gboolean
00142 bio_init( Sed_process p , Eh_symbol_table t , GError** error )
00143 {
00144    Bio_param_t* data    = sed_process_new_user_data( p , Bio_param_t );
00145    GError*      tmp_err = NULL;
00146    gboolean     is_ok   = TRUE;
00147 
00148    eh_return_val_if_fail( error==NULL || *error==NULL , FALSE );
00149    eh_require( t );
00150    eh_require( p );
00151 
00152    data->method = BIO_METHOD_UNKNOWN;
00153 
00154    if ( eh_symbol_table_require_labels( t , bio_req_label , &tmp_err ) )
00155    {
00156       gchar** err_s   = NULL;
00157       gchar*  model_s = eh_symbol_table_lookup( t , BIO_KEY_MODEL );
00158 
00159       data->depth = eh_symbol_table_input_value( t , BIO_KEY_DEPTH , &tmp_err );
00160 
00161       if      ( g_ascii_strcasecmp( model_s , "DIFFUSION" )==0 ) data->method = BIO_METHOD_DIFFUSION;
00162       else if ( g_ascii_strcasecmp( model_s , "CONVEYOR"  )==0 ) data->method = BIO_METHOD_CONVEYOR;
00163       else
00164          g_set_error( &tmp_err , BIO_ERROR , BIO_ERROR_BAD_ALGORITHM ,
00165                       "invalid bioturbation model (diffusion or conveyor): %s" , model_s );
00166 
00167       if ( !tmp_err
00168            && data->method == BIO_METHOD_DIFFUSION
00169            && eh_symbol_table_require_labels( t , bio_diff_req_label , &tmp_err ) )
00170          data->k = eh_symbol_table_input_value( t , BIO_KEY_K , &tmp_err );
00171 
00172       if ( !tmp_err
00173            && data->method == BIO_METHOD_CONVEYOR
00174            && eh_symbol_table_require_labels( t , bio_conv_req_label , &tmp_err ) )
00175          data->r = eh_symbol_table_input_value( t , BIO_KEY_R , &tmp_err );
00176    }
00177 
00178    if ( tmp_err )
00179    {
00180       g_propagate_error( error , tmp_err );
00181       is_ok = FALSE;
00182    }
00183 
00184    return is_ok;
00185 }
00186 
00187 gboolean
00188 bio_destroy( Sed_process p )
00189 {
00190    if ( p )
00191    {
00192       Bio_param_t* data = sed_process_user_data( p );
00193 
00194       if ( data )
00195       {
00196          eh_input_val_destroy( data->k     );
00197          eh_input_val_destroy( data->depth );
00198          eh_free             ( data        );
00199       }
00200    }
00201    return TRUE;
00202 }
00203 
00204 void
00205 sed_column_bioturbate( Sed_column c , double depth , double k , double duration , Bio_method m )
00206 {
00207 //   EH_MEM_LEAK_START
00208 
00209    eh_require( c          );
00210    eh_require( k>0        );
00211    eh_require( duration>0 );
00212 
00213    if ( c && depth>=0 )
00214    {
00215       double    mass_in  = sed_column_mass( c );
00216       double    mass_out = 0;
00217       double    z        = sed_column_top_height(c) - depth;
00218       Sed_cell* top      = sed_column_extract_cells_above( c , z );
00219 
00220       if ( top )
00221       {
00222          double   dz       = sed_column_z_res( c );
00223          gint     n_layers = g_strv_length( top );
00224 
00225          if ( n_layers>2 )
00226          {
00227             double**  data = NULL;
00228             double*   t    = eh_new( double , n_layers );
00229             gint      i;
00230 
00231             for ( i=0 ; i<n_layers ; i++ )
00232             {
00233                t[i] = sed_cell_size( top[i] );
00234 /*
00235                if ( !sed_cell_is_valid(top[i]) )
00236                   sed_cell_fprint( stderr , top[i] );
00237 */
00238             }
00239             {
00240                double sum = eh_dbl_array_sum( t , n_layers );
00241                if ( sum>.1 && !eh_compare_dbl(sum,.1,1e-12) ) eh_watch_dbl( sum-.1 );
00242             }
00243 
00244             switch ( m )
00245             {
00246                case BIO_METHOD_DIFFUSION: data = bio_diffuse_layers ( t , n_layers , dz , k , duration ); break;
00247                case BIO_METHOD_CONVEYOR : data = bio_conveyor_layers( t , n_layers , dz , k , duration ); break;
00248                default: eh_require_not_reached();
00249             }
00250 
00251             if ( data )
00252             {
00253                Sed_cell* new_top = bio_array_to_cell_array( top , data );
00254 
00255                sed_column_stack_cells_loc( c , new_top );
00256 
00257                eh_free  ( new_top );
00258                g_strfreev( data );
00259             }
00260             else
00261             {
00262                sed_column_stack_cells_loc( c , top );
00263                eh_free(top);
00264                top = NULL;
00265             }
00266             eh_free( t );
00267          }
00268          else
00269          {
00270             sed_column_stack_cells_loc( c , top );
00271             eh_free(top);
00272             top = NULL;
00273          }
00274 
00275       mass_out = sed_column_mass( c );
00276 
00277       if ( !eh_compare_dbl(mass_in,mass_out,1e-2) )
00278       {
00279          eh_require_not_reached();
00280          eh_watch_dbl( mass_in  );
00281          eh_watch_dbl( mass_out );
00282          eh_watch_int( n_layers );
00283          eh_watch_ptr( top      );
00284       }
00285 
00286          top = sed_cell_array_free( top );
00287       }
00288 
00289    }
00290 
00291 //   EH_MEM_LEAK_END_WARN
00292 }
00293 
00294 double**
00295 sed_array_to_bio_array( Sed_cell* col , gint* n_grains , gint* n_layers )
00296 {
00297    double** data = NULL;
00298 
00299    eh_require( col      );
00300    eh_require( n_grains );
00301    eh_require( n_layers );
00302 
00303    if ( col )
00304    {
00305       gint i, n;
00306 
00307       *n_grains = sed_sediment_env_n_types();
00308       *n_layers = g_strv_length( (gchar**)col );
00309 
00310       for ( n=0 ; n<*n_grains ; n++ )
00311          for ( i=0 ; i<*n_layers ; i++ )
00312             data[n][i] = sed_cell_nth_amount( col[i] , n );
00313    }
00314 
00315    return data;
00316 }
00317 
00318 Sed_cell*
00319 bio_array_to_cell_array( Sed_cell* c_arr , double** data )
00320 {
00321    Sed_cell* out_arr = NULL;
00322 
00323    if ( data && c_arr )
00324    {
00325       gint new_len  = g_strv_length( data  );
00326       gint orig_len = g_strv_length( c_arr );
00327       gint i;
00328       gint j;
00329       double mass_in, mass_out;
00330 
00331       mass_in = sed_cell_array_mass( c_arr );
00332 
00333       out_arr = eh_new0( Sed_cell , new_len+1 );
00334 
00335       for ( i=0 ; i<new_len ; i++ )
00336       {
00337          out_arr[i] = sed_cell_new_env();
00338 
00339          for ( j=0 ; j<orig_len ; j++ )
00340             if ( data[i][j]>1e-12 )
00341             {
00342 /*
00343                if ( !sed_cell_is_valid(c_arr[j]) )
00344                   sed_cell_fprint( stderr , c_arr[j] );
00345 */
00346                sed_cell_resize( c_arr[j] , data[i][j] );
00347 /*
00348                if ( !sed_cell_is_valid(c_arr[j]) )
00349                {
00350                   eh_watch_dbl( data[i][j] );
00351                   sed_cell_fprint( stderr , c_arr[j] );
00352                }
00353 */
00354                sed_cell_add( out_arr[i] , c_arr[j] );
00355             }
00356 /*
00357             if ( sed_cell_is_empty( out_arr[i] ) || sed_cell_is_clear( out_arr[i] ) || !sed_cell_is_valid(out_arr[i] ) )
00358             {
00359                sed_cell_fprint(stderr , out_arr[i] );
00360                sed_cell_fprint(stderr , c_arr[0] );
00361 fprintf( stderr , "Thickness = %g\n" , sed_cell_size(c_arr[0]) );
00362 eh_watch_int( i );
00363 eh_watch_int( j );
00364          for ( i=0 ; i<new_len ; i++ )
00365          {
00366             for ( j=0 ; j<orig_len ; j++ )
00367                fprintf( stderr , "%f " , data[i][j] );
00368             fprintf( stderr , "\n" );
00369          }
00370             }
00371 */
00372       }
00373 
00374       out_arr = sed_cell_array_delete_empty( out_arr );
00375 
00376       mass_out = sed_cell_array_mass( out_arr );
00377 
00378       if ( !eh_compare_dbl(mass_in,mass_out,1e-2) )
00379       {
00380          eh_require_not_reached();
00381          for ( i=0 ; i<new_len ; i++ )
00382          {
00383             for ( j=0 ; j<orig_len ; j++ )
00384                fprintf( stderr , "%f " , data[i][j] );
00385             fprintf( stderr , "\n" );
00386          }
00387          for ( i=0 ; i<new_len ; i++ )
00388             sed_cell_fprint( stderr , out_arr[i] );
00389          eh_watch_dbl( mass_in  );
00390          eh_watch_dbl( mass_out );
00391          eh_watch_int( g_strv_length( c_arr   ) );
00392          eh_watch_int( g_strv_length( out_arr ) );
00393 eh_exit(0);
00394       }
00395 
00396    }
00397    return out_arr;
00398 }
00399 
00400 /*
00401 Sed_cell*
00402 bio_array_to_cell_array( Sed_cell* c_arr , double** data , gint n_grains , gint n_layers )
00403 {
00404    if ( data && c_arr )
00405    {
00406       gint i, n;
00407       double* t = eh_new( double , n_grains );
00408 
00409       eh_require( n_layers==g_strv_length( (gchar**)c_arr )    );
00410       eh_require( n_grains==sed_sediment_env_n_types() );
00411 
00412       for ( i=0 ; i<n_layers ; i++ )
00413       {
00414          for ( n=0 ; n<n_grains ; n++ )
00415             t[n] = data[n][i];
00416 
00417          sed_cell_set_amount( c_arr[i] , t );
00418       }
00419 
00420       eh_free( t );
00421    }
00422 
00423    return c_arr;
00424 }
00425 */
00426 /*
00427 void
00428 sed_diffuse_array( Sed_cell* arr , double k , double duration )
00429 {
00430    {
00431 
00432       for ( n=0 ; n<n_grains ; n++ )
00433       {
00434          for ( i=0 ; i<len ; i++ )
00435          {
00436             dh[i] = sed_cell_nth_amount(arr[i+1],n)
00437                   - sed_cell_nth_amount(arr[i]  ,n);
00438             q[i]  = k*dh[i]/dz;
00439          }
00440       }
00441    }
00442 }
00443 */

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