00001 #include <glib.h>
00002 #include <utils/utils.h>
00003 #include "bio.h"
00004
00005 G_GNUC_INTERNAL void diffuse_col( double* u , gint len , double dz , double k , double total_t );
00006
00007 GQuark
00008 bio_error_quark( void )
00009 {
00010 return g_quark_from_static_string( "bio-error-quark" );
00011 }
00012
00013 void
00014 bioturbate( double** col , gint n_grains , gint n_layers , double dz , double k , double total_t )
00015 {
00016 eh_require( n_grains>0 );
00017 eh_require( dz>0 );
00018 eh_require( k>0 );
00019
00020 if ( col && n_layers>1 )
00021 {
00022 gint n;
00023
00024 for ( n=0 ; n<n_grains ; n++ )
00025 diffuse_col( col[n] , n_layers , dz , k , total_t );
00026 }
00027 }
00028
00029 void
00030 diffuse_col( double* f , gint len , double dz , double k , double total_t )
00031 {
00032 if ( len>2 )
00033 {
00034 {
00035 Eh_num_method method = EH_NUM_IMPLICIT;
00036 gint i, n;
00037 double* f_new = eh_dbl_array_dup( f , len );
00038 const double dt_opt = .9*.5*dz*dz/k;
00039
00040 const double dt = total_t;
00041 const double c = dt * k / (dz*dz);
00042 const gint n_t = total_t / dt;
00043 const double dt_rem = fmod( total_t , dt );
00044
00045 for ( n=0 ; n<n_t ; n++ ) eh_dbl_array_diffuse( f , len , c , method );
00046 if ( dt_rem > 0. ) eh_dbl_array_diffuse( f , len , c * ( dt_rem / dt ) , method );
00047
00048 eh_free( f_new );
00049 }
00050 }
00051
00052 return;
00053 }
00054
00055 double**
00056 bio_diffuse_layers( double* t , gint n_layers , double dz , double k , double duration )
00057 {
00058 double** u_out = NULL;
00059
00060 if ( n_layers>2 )
00061 {
00062 gint i;
00063 double* u_copy;
00064
00065 u_out = eh_new( double* , n_layers+1 );
00066
00067 for ( i=0 ; i<n_layers ; i++ )
00068 {
00069 u_copy = eh_new0( double , n_layers );
00070 u_copy[i] = t[i];
00071
00072 diffuse_col( u_copy , n_layers , dz , k , duration );
00073
00074 u_out[i] = u_copy;
00075 }
00076 u_out[n_layers] = NULL;
00077 }
00078
00079 return u_out;
00080 }
00081
00082 double**
00083 bio_conveyor_layers( double* t , gint n_layers , double dz , double r , double duration )
00084 {
00085 double** u_out = NULL;
00086
00087 eh_require( dz > 0 );
00088 eh_require( n_layers > 0 );
00089
00090 if ( r > 0 && duration > 0 )
00091 {
00092 const double h = eh_dbl_array_sum(t,n_layers);
00093 const double dh = r*duration;
00094
00095 if ( dh >= h )
00096 {
00097 u_out = eh_new( double* , 2 );
00098 u_out[0] = eh_dbl_array_dup( t , n_layers );
00099 u_out[1] = NULL;
00100 }
00101 else if ( dh > 0 )
00102 {
00103 double* u_avg = eh_new0( double , n_layers );
00104 gint i, i_shift, j;
00105 gint new_len;
00106 double tot;
00107
00108 for ( i=0,tot=t[0] ; tot<=dh && i<n_layers ; i++,tot+=t[i] ) u_avg[i] = t[i];
00109 u_avg[i] = t[i] - (tot-dh);
00110
00111 i_shift = i;
00112
00113 eh_require( tot >= dh );
00114 eh_require( i_shift < n_layers );
00115
00116 new_len = n_layers-i_shift+1;
00117
00118 u_out = eh_new( double* , new_len+1 );
00119
00120 for ( i=0,j=i_shift ; i<new_len-1 ; i++,j++ )
00121 {
00122 u_out[i] = eh_new0( double , n_layers );
00123 u_out[i][j] = t[j];
00124 }
00125 u_out[0][i_shift] = tot-dh;
00126
00127 u_out[new_len-1] = u_avg;
00128 u_out[new_len] = NULL;
00129 }
00130 else
00131 {
00132 gint i;
00133 u_out = eh_new( double* , n_layers+1 );
00134 for ( i=0 ; i<n_layers ; i++ )
00135 {
00136 u_out[i] = eh_new0( double , n_layers );
00137 u_out[i][i] = t[i];
00138 }
00139 u_out[n_layers] = NULL;
00140 }
00141 }
00142
00143 return u_out;
00144 }
00145
00146 void
00147 bio_conveyor( double* u , gint len , double r , double total_t , double** u_out , gint** i_out , gint* len_out )
00148 {
00149 eh_require( u );
00150
00151 if ( u )
00152 {
00153 const double h = eh_dbl_array_sum( u , len );
00154 const double dh = fmod( r*total_t , h );
00155 gint* i_in = eh_new( gint , len );
00156 gint i;
00157 gint i_shift;
00158 double z;
00159
00160 *u_out = eh_new( double , len+1 );
00161 *i_out = eh_new( gint , len+1 );
00162 *len_out = len+1;
00163
00164 for ( i=0 ; i<len ; i++ ) i_in[i] = i;
00165
00166
00167 for ( i_shift=0 ; i_shift<len && z<dh ; z+=u[i_shift],i_shift++ );
00168
00169
00170 g_memmove( *u_out , u+i_shift , sizeof(double)*(len-i_shift) );
00171 g_memmove( *u_out+(len-i_shift) , u , sizeof(double)*( i_shift) );
00172 g_memmove( i_out , i_in+i_shift , sizeof(gint) *(len-i_shift) );
00173 g_memmove( i_out+(len-i_shift) , i_in , sizeof(gint) *( i_shift) );
00174
00175
00176 (*u_out)[0] = z - dh;
00177 (*u_out)[len] = u[i_shift] - (z-dh);
00178
00179 eh_free( i_in );
00180 }
00181
00182 return;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216