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
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
00085
00086 for ( i=0 ; i<len ; i++ ) sed_column_bioturbate( sed_cube_col(p,i) , depth , val , dt , data->method );
00087
00088
00089 }
00090
00091 return info;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
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
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
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
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
00236
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
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
00344
00345
00346 sed_cell_resize( c_arr[j] , data[i][j] );
00347
00348
00349
00350
00351
00352
00353
00354 sed_cell_add( out_arr[i] , c_arr[j] );
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
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
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443