00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <math.h>
00023 #include <pthread.h>
00024 #include <utils/utils.h>
00025 #include <sed/sed_sedflux.h>
00026 #include "failure.h"
00027
00028 #ifndef SECONDS_PER_YEAR
00029 # define SECONDS_PER_YEAR 31536000.
00030 #endif
00031
00032 #define FAIL_LOCAL_MODEL
00033 #undef FAIL_WITH_THREADS
00034
00035 Sed_cube get_failure_surface( const Sed_cube p , int start , int len )
00036 {
00037 Sed_cube fail;
00038
00039 double *ellipse;
00040 gssize *x, *y;
00041 int i;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 if ( sed_column_thickness( sed_cube_col(p,start) ) < 1e-5 )
00055 return NULL;
00056
00057
00058
00059
00060
00061 if ( sed_cube_top_height(p,0,start)
00062 < sed_cube_top_height(p,0,start+len-1) )
00063 return NULL;
00064
00065 x = eh_new0( gssize , len );
00066 y = eh_new0( gssize , len );
00067 ellipse = eh_new0( double , len );
00068
00069
00070
00071
00072 if ( !get_circle( p , start , len , ellipse ) )
00073 {
00074 eh_free(x);
00075 eh_free(y);
00076 eh_free(ellipse);
00077 return NULL;
00078 }
00079 for (i=0;i<len;i++)
00080 {
00081 x[i] = 0;
00082 y[i] = i+start;
00083 }
00084
00085
00086
00087 fail = sed_cube_copy_cols( p , x , y , ellipse , len );
00088
00089
00090
00091 for ( i=1 ; i<sed_cube_n_y(fail)-1 ; i++ )
00092 if ( sed_cube_thickness(fail,0,i) < 1e-5 )
00093 {
00094 sed_cube_destroy(fail);
00095 eh_free(x);
00096 eh_free(y);
00097 eh_free(ellipse);
00098 return NULL;
00099 }
00100
00101 eh_free(x);
00102 eh_free(y);
00103 eh_free(ellipse);
00104
00105 return fail;
00106 }
00107
00108 gboolean fail_check_failure_plane_is_valid( const Sed_cube p ,
00109 int start ,
00110 int len ,
00111 const double *failure_plane )
00112 {
00113 int i;
00114
00115 eh_require( p!=NULL );
00116 eh_require( sed_cube_is_1d(p) );
00117 eh_require( failure_plane!=NULL );
00118
00119 if ( start+len >= sed_cube_n_y(p) )
00120 return FALSE;
00121
00122 if ( sed_cube_top_height( p,0,start )
00123 < sed_cube_top_height( p,0,start+len-1 ) )
00124 return FALSE;
00125
00126 for ( i=1 ; i<len-1 ; i++ )
00127 {
00128 if ( failure_plane[i] >= sed_cube_top_height( p,0,start+i ) )
00129 return FALSE;
00130 if ( failure_plane[i] < sed_cube_base_height( p,0,start+i ) )
00131 return FALSE;
00132 }
00133
00134 return TRUE;
00135 }
00136
00137 double *get_circle( const Sed_cube p ,
00138 int failure_start ,
00139 int n_points ,
00140 double *circle)
00141 {
00142 int i;
00143 double x0, y0;
00144 double r;
00145 double rise, run;
00146 double width;
00147 double *x;
00148
00149 eh_require( p!=NULL );
00150 eh_require( sed_cube_is_1d(p) );
00151 eh_require( circle!=NULL );
00152
00153 if ( failure_start+n_points >= sed_cube_n_y(p) )
00154 return NULL;
00155
00156 width = sed_cube_y_res(p);
00157
00158 rise = fabs(
00159 sed_cube_top_height( p , 0 , failure_start )
00160 - sed_cube_top_height( p , 0 , failure_start+n_points-1) );
00161 run = (n_points-1)*width;
00162
00163 if ( rise < 1e-3 )
00164 return NULL;
00165
00166 r = (pow(rise,2) + pow(run,2))/2./rise;
00167
00168 y0 = sed_cube_top_height(p,0,failure_start+n_points-1) + r;
00169 x0 = (n_points-1)*width;
00170
00171 x = eh_new0(double,n_points);
00172 for (i=1;i<n_points;i++)
00173 x[i] = x[i-1] + width;
00174
00175 for (i=0;i<n_points;i++)
00176 circle[i] = y0 - sqrt(pow(r,2) - pow(x[i]-x0,2));
00177
00178 eh_free(x);
00179
00180 if ( !fail_check_failure_plane_is_valid( p ,
00181 failure_start ,
00182 n_points ,
00183 circle ) )
00184 return NULL;
00185
00186 return circle;
00187 }
00188
00189 double *get_ellipse( const Sed_cube p ,
00190 int failureStart ,
00191 int nPoints ,
00192 double *ellipse )
00193 {
00194 int i;
00195 double x0, y0;
00196 double rx, ry;
00197 double width, *x;
00198
00199 eh_require( p );
00200 eh_require( sed_cube_is_1d(p) );
00201
00202 x = eh_new( double , nPoints );
00203 width = sed_cube_y_res(p);
00204
00205 ry = fabs( sed_cube_top_height(p,0,failureStart)
00206 - sed_cube_top_height(p,0,failureStart+nPoints-1));
00207 rx = (nPoints-1)*width;
00208
00209 x0 = rx;
00210 y0 = MAX( sed_cube_top_height(p,0,failureStart) ,
00211 sed_cube_top_height(p,0,failureStart+nPoints-1) );
00212
00213
00214 if ( sed_cube_top_height(p,0,failureStart)
00215 > sed_cube_top_height(p,0,failureStart+nPoints-1) )
00216 x[0] = 0;
00217 else
00218 x[0] = rx;
00219
00220 for (i=1;i<nPoints;i++)
00221 x[i] = x[i-1] + width;
00222
00223 for (i=0;i<nPoints;i++)
00224 ellipse[i] = y0 - ry*sqrt(1-pow((x[i]-x0)/rx,2));
00225
00226 eh_free(x);
00227
00228 return ellipse;
00229 }
00230
00231 double get_m(const Sed_column s,double depth, double consolidation)
00232 {
00233 double delta_t, rate, t;
00234 double i1, i2;
00235
00236 if (sed_column_thickness(s) > 0 )
00237 {
00238
00239
00240 i2 = sed_column_index_depth(s,0);
00241
00242
00243 i1 = sed_column_index_depth(s,depth);
00244 if ( i1 < 0 ) i1 = 0;
00245
00246
00247
00248 delta_t = ( sed_cell_age( sed_column_nth_cell(s,(int)i2) )
00249 - sed_cell_age( sed_column_nth_cell(s,(int)i1) ) )
00250 *S_SECONDS_PER_YEAR;
00251
00252
00253 if ( delta_t <= 0. )
00254 rate = 0.;
00255 else
00256 rate = depth/delta_t;
00257
00258
00259
00260 t = rate*rate*delta_t/consolidation;
00261
00262
00263 if ( t > 16 )
00264 return 1.;
00265 else
00266 return 6.4*pow(1.-t/16.,17)+1.;
00267 }
00268 else
00269 return 1;
00270 }
00271
00272 #define FAIL_MIN_COL_LEN (128)
00273
00274 Fail_column *fail_create_fail_column( int n , gboolean allocate )
00275 {
00276 int i;
00277 Fail_column *f;
00278
00279 if ( n<0 )
00280 n=0;
00281
00282 f = eh_new( Fail_column , 1 );
00283
00284 f->w = eh_new( double , FAIL_MIN_COL_LEN );
00285 f->u = eh_new( double , FAIL_MIN_COL_LEN );
00286 f->phi = eh_new( double , FAIL_MIN_COL_LEN );
00287 f->height = eh_new( double , FAIL_MIN_COL_LEN );
00288 f->c = eh_new( double , FAIL_MIN_COL_LEN );
00289
00290 f->len = FAIL_MIN_COL_LEN;
00291 f->size = n;
00292
00293 if ( allocate )
00294 fail_resize_fail_column( f , n );
00295
00296 for ( i=0 ; i<MAX_FAILURE_LENGTH ; i++ )
00297 f->fs[i] = FAIL_FOS_NOT_VALID;
00298
00299 f->need_update = TRUE;
00300
00301 return f;
00302 }
00303
00304 Fail_column *fail_reuse_fail_column( Fail_column *f )
00305 {
00306 int i;
00307 for ( i=0 ; i<MAX_FAILURE_LENGTH ; i++ )
00308 f->fs[i] = 999;
00309
00310 f->need_update = TRUE;
00311
00312 return f;
00313 }
00314
00315 Fail_column *fail_resize_fail_column( Fail_column *f , int n )
00316 {
00317 if ( n>f->len )
00318 {
00319 f->w = g_renew( double , f->w , n );
00320 f->u = g_renew( double , f->u , n );
00321 f->phi = g_renew( double , f->phi , n );
00322 f->height = g_renew( double , f->height , n );
00323 f->c = g_renew( double , f->c , n );
00324 f->len = n;
00325 }
00326
00327 f->size = n;
00328
00329 return f;
00330 }
00331
00332 void fail_destroy_fail_column( Fail_column *f )
00333 {
00334
00335 if ( f!=NULL )
00336 {
00337 eh_free( f->w );
00338 eh_free( f->u );
00339 eh_free( f->c );
00340 eh_free( f->phi );
00341 eh_free( f->height );
00342
00343 eh_free( f );
00344 }
00345
00346 return;
00347 }
00348
00349 void fail_dump_fail_column( Fail_column *f , FILE *fp )
00350 {
00351 fwrite( f , sizeof(Fail_column) , 1 , fp );
00352 fwrite( f->w , sizeof(double) , f->len , fp );
00353 fwrite( f->u , sizeof(double) , f->len , fp );
00354 fwrite( f->phi , sizeof(double) , f->len , fp );
00355 fwrite( f->height , sizeof(double) , f->len , fp );
00356 fwrite( f->c , sizeof(double) , f->len , fp );
00357 }
00358
00359 gboolean fail_load_fail_column( Fail_column *f , FILE *fp )
00360 {
00361 fread( f , sizeof(Fail_column) , 1 , fp );
00362
00363 f->w = eh_new( double , f->len );
00364 f->u = eh_new( double , f->len );
00365 f->phi = eh_new( double , f->len );
00366 f->height = eh_new( double , f->len );
00367 f->c = eh_new( double , f->len );
00368
00369 fread( f->w , sizeof(double) , f->len , fp );
00370 fread( f->u , sizeof(double) , f->len , fp );
00371 fread( f->phi , sizeof(double) , f->len , fp );
00372 fread( f->height , sizeof(double) , f->len , fp );
00373 fread( f->c , sizeof(double) , f->len , fp );
00374
00375 return TRUE;
00376 }
00377
00378 typedef struct
00379 {
00380 Sed_cube p;
00381 Failure_t fail_const;
00382 double *failure_line;
00383 Fail_column **slice;
00384 }
00385 Init_failure_t;
00386
00387 void init_column( gpointer data , gpointer user_data );
00388
00389 Fail_profile *fail_init_fail_profile( Sed_cube p ,
00390 Failure_t fail_const )
00391 {
00392 return fail_reinit_fail_profile( NULL , p , fail_const );
00393 }
00394
00395 #define FAIL_INIT_N_THREADS (10)
00396
00397 Fail_profile *fail_reinit_fail_profile( Fail_profile *f ,
00398 Sed_cube p ,
00399 Failure_t fail_const )
00400 {
00401 int i, n_cols;
00402 #ifdef FAIL_WITH_THREADS
00403 GThreadPool *t_pool;
00404 #endif
00405 double *failure_line;
00406 Init_failure_t data;
00407 int *queue;
00408
00409 eh_require( p!=NULL );
00410 eh_require( sed_cube_is_1d(p) );
00411
00412 #ifdef FAIL_WITH_THREADS
00413 if ( !g_thread_supported() ) g_thread_init( NULL );
00414 #endif
00415
00416 n_cols = sed_cube_n_y(p);
00417
00418 if ( f )
00419 f = fail_reuse_fail_profile( f );
00420 else
00421 f = fail_create_fail_profile( n_cols );
00422
00423 f = fail_resize_fail_profile( f , n_cols );
00424
00425 f->p = p;
00426 f->fail_const = fail_const;
00427
00428 failure_line = fail_get_failure_line( p );
00429
00430 data.p = p;
00431 data.fail_const = fail_const;
00432 data.failure_line = failure_line;
00433 data.slice = f->col;
00434
00435 #ifdef FAIL_WITH_THREADS
00436 t_pool = g_thread_pool_new( (GFunc)&init_column ,
00437 &data ,
00438 FAIL_INIT_N_THREADS ,
00439 TRUE ,
00440 NULL );
00441 #endif
00442
00443 queue = eh_new( int , sed_cube_n_y(p) );
00444
00445
00446 for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
00447 {
00448 queue[i] = i;
00449
00450 #ifdef FAIL_WITH_THREADS
00451 g_thread_pool_push( t_pool , &(queue[i]) , NULL );
00452 #else
00453 init_column( &(queue[i]) , &data );
00454 #endif
00455
00456 }
00457
00458 #ifdef FAIL_WITH_THREADS
00459 g_thread_pool_free( t_pool , FALSE , TRUE );
00460 #endif
00461
00462 eh_free( failure_line );
00463 eh_free( queue );
00464
00465 return f;
00466 }
00467
00468 Fail_profile *fail_reuse_fail_profile( Fail_profile *f )
00469 {
00470 eh_require( f!=NULL );
00471
00472 f->p = NULL;
00473
00474 f->fs_min_val = 999;
00475 f->fs_min_start = -1;
00476 f->fs_min_len = -1;
00477
00478 f->count = 0;
00479
00480 return f;
00481 }
00482
00483 Fail_profile *fail_create_fail_profile( int n_cols )
00484 {
00485 Fail_profile *f;
00486
00487 f = eh_new ( Fail_profile , 1 );
00488 f->col = eh_new0( Fail_column* , n_cols );
00489 f->size = n_cols;
00490 f->len = n_cols;
00491
00492 f->count = 0;
00493
00494 return f;
00495 }
00496
00497 void fail_dump_fail_profile( Fail_profile *f , FILE *fp )
00498 {
00499 int i;
00500 fwrite( f , sizeof(Fail_profile) , 1 , fp );
00501 for ( i=0 ; i<f->size ; i++ )
00502 fail_dump_fail_column( f->col[i] , fp );
00503 sed_cube_write( fp , f->p );
00504 }
00505
00506 void fail_load_fail_profile( FILE *fp )
00507 {
00508 int i;
00509 Fail_profile *f = eh_new( Fail_profile , 1 );
00510
00511 fread( f , sizeof(Fail_profile) , 1 , fp );
00512 f->col = eh_new( Fail_column* , f->len );
00513 for ( i=0 ; i<f->size ; i++ )
00514 fail_load_fail_column( f->col[i] , fp );
00515 f->p = sed_cube_read( fp );
00516 }
00517
00518 Fail_profile *fail_resize_fail_profile( Fail_profile *f , int n_cols )
00519 {
00520 int i;
00521 if ( n_cols > f->len )
00522 {
00523 f->col = g_renew( Fail_column* , f->col , n_cols );
00524 for ( i=f->len ; i<n_cols ; i++ )
00525 f->col[i] = NULL;
00526 f->len = n_cols;
00527 }
00528
00529 f->size = n_cols;
00530
00531 return f;
00532 }
00533
00534 void init_column( gpointer data , gpointer user_data )
00535 {
00536 int i = *((int*)data);
00537 Sed_cube p = ((Init_failure_t*)user_data)->p;
00538 Failure_t fail_const = ((Init_failure_t*)user_data)->fail_const;
00539 double *failure_line = ((Init_failure_t*)user_data)->failure_line;
00540 Fail_column **slice = ((Init_failure_t*)user_data)->slice;
00541
00542 slice[i] = fail_reinit_fail_column( slice[i] ,
00543 sed_cube_col(p,i) ,
00544 failure_line[i] ,
00545 fail_const );
00546
00547 return;
00548 }
00549
00550 void fail_destroy_failure_profile( Fail_profile *f )
00551 {
00552 int i;
00553
00554 if ( f!=NULL )
00555 {
00556 for ( i=0 ; i<f->size ; i++ )
00557 fail_destroy_fail_column( f->col[i] );
00558 eh_free( f->col );
00559 eh_free( f );
00560 }
00561 return;
00562 }
00563
00564 #define FAIL_NO_FAIL_SURFACE (G_MAXDOUBLE)
00565
00566 double *fail_get_failure_line( Sed_cube p )
00567 {
00568 int i, j, len;
00569 double *ellipse;
00570 double *failure_line;
00571
00572 eh_require( p!=NULL );
00573 eh_require( sed_cube_is_1d(p) );
00574
00575 ellipse = eh_new( double , MAX_FAILURE_LENGTH );
00576 failure_line = eh_new( double , sed_cube_n_y(p) );
00577
00578 for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
00579 failure_line[i] = FAIL_NO_FAIL_SURFACE;
00580
00581
00582
00583 for ( i=0 ; i<sed_cube_n_y(p) ; i++ )
00584 {
00585 for ( len=MIN_FAILURE_LENGTH ; len<MAX_FAILURE_LENGTH ; len++ )
00586 if ( get_circle( p , i , len , ellipse ) )
00587 {
00588 for ( j=0 ; j<len && i+j<sed_cube_n_y(p) ; j++ )
00589 if ( ellipse[j]<failure_line[i+j] )
00590 failure_line[i+j] = ellipse[j];
00591 }
00592 }
00593
00594 eh_free( ellipse );
00595
00596 return failure_line;
00597 }
00598
00599 #define N_THREADS (4)
00600
00601 void fail_examine_fail_profile( Fail_profile *p )
00602 {
00603 int i, j;
00604 #ifdef FAIL_WITH_THREADS
00605 GThreadPool *fos_pool[N_THREADS];
00606 #endif
00607 int river_mouth, block_size;
00608 int start;
00609 int **queue;
00610
00611 eh_require( p!=NULL );
00612
00613 #ifdef FAIL_WITH_THREADS
00614 if ( !g_thread_supported() ) g_thread_init( NULL );
00615
00616 for ( i=0 ; i<N_THREADS ; i++ )
00617 fos_pool[i] = g_thread_pool_new( (GFunc)&get_node_fos ,
00618 p ,
00619 1 ,
00620 TRUE ,
00621 NULL );
00622 #endif
00623
00624
00625
00626 river_mouth = sed_cube_river_mouth_1d( p->p ) - 3;
00627 if ( river_mouth<0 )
00628 river_mouth = 0;
00629 block_size = ( p->size-river_mouth ) / N_THREADS;
00630 queue = eh_new( int* , N_THREADS );
00631
00632 for ( i=0 ; i<N_THREADS ; i++ )
00633 {
00634 queue[i] = eh_new( int , block_size );
00635 start = i*block_size + river_mouth;
00636
00637 for ( j=0 ; j<block_size ; j++, start++ )
00638 {
00639 queue[i][j] = start;
00640
00641 #ifdef FAIL_WITH_THREADS
00642 g_thread_pool_push( fos_pool[i] , &(queue[i][j]) , NULL );
00643 #else
00644 get_node_fos( &(queue[i][j]) , p );
00645 #endif
00646
00647 }
00648 }
00649
00650 #ifdef FAIL_WITH_THREADS
00651 for ( i=0 ; i<N_THREADS ; i++ )
00652 g_thread_pool_free( fos_pool[i] , FALSE , TRUE );
00653 #endif
00654
00655 for ( i=0 ; i<N_THREADS ; i++ )
00656 eh_free( queue[i] );
00657 eh_free( queue );
00658
00659
00660 for ( i=0 ; i<p->size ; i++ )
00661 p->col[i]->need_update = FALSE;
00662
00663 return;
00664 }
00665
00666 void fail_reset_fail_profile( Fail_profile *p )
00667 {
00668 int start, len;
00669
00670 p->fs_min_val = 999;
00671 p->fs_min_start = -1;
00672 p->fs_min_len = -1;
00673
00674 for ( start=0 ; start<p->size ; start++ )
00675 {
00676 for ( len=0 ; len<MAX_FAILURE_LENGTH ; len++ )
00677 p->col[start]->fs[len] = FAIL_FOS_NOT_VALID;
00678 p->col[start]->need_update = TRUE;
00679 }
00680 }
00681
00682 void fail_update_fail_profile( Fail_profile *p )
00683 {
00684 int i;
00685 int start, len;
00686 Fail_column *f_col;
00687 Sed_column s_col;
00688 double *failure_line;
00689 double fs, fs_min_val;
00690 double fail_col_h, sed_col_h;
00691
00692 eh_require( p!=NULL );
00693
00694
00695 failure_line = fail_get_failure_line( p->p );
00696
00697 p->count = 0;
00698
00699
00700
00701 for ( i=0 ; i<p->size ; i++ )
00702 {
00703
00704 f_col = p->col[i];
00705 s_col = sed_cube_col(p->p,i);
00706
00707 if ( f_col->size>0 )
00708 fail_col_h = f_col->height[f_col->size-1];
00709 else
00710 fail_col_h = f_col->failure_line;
00711 sed_col_h = sed_column_top_height( s_col );
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 if ( fabs(fail_col_h-sed_col_h) > .1 )
00726 {
00727
00728 p->col[i] = fail_reinit_fail_column( p->col[i] ,
00729 s_col ,
00730 failure_line[i] ,
00731 p->fail_const );
00732 p->col[i]->need_update = TRUE;
00733
00734 p->count++;
00735
00736 }
00737
00738 }
00739
00740 eh_free( failure_line );
00741
00742
00743 for ( i=0 ; i<p->size ; i++ )
00744 for ( len=0 ; len<MAX_FAILURE_LENGTH ; len++ )
00745 if ( i+len<p->size && p->col[i+len]->need_update )
00746 p->col[i]->fs[len] = FAIL_FOS_NOT_VALID;
00747
00748
00749 p->fs_min_val = 999;
00750 p->fs_min_start = -1;
00751 p->fs_min_len = -1;
00752
00753
00754 for ( start=0 , fs_min_val=999 ; start<p->size ; start++ )
00755 {
00756 for ( len=0 ; len<MAX_FAILURE_LENGTH ; len++ )
00757 {
00758 fs = p->col[start]->fs[len];
00759 if ( fail_fos_is_valid(fs) && fs<fs_min_val )
00760 {
00761 fs_min_val = fs;
00762 p->fs_min_val = fs_min_val;
00763 p->fs_min_start = start;
00764 p->fs_min_len = len;
00765 }
00766 }
00767 }
00768
00769 eh_debug( "%d of %d columns have changed since last examination" ,
00770 p->count ,
00771 p->size );
00772
00773 return;
00774 }
00775
00776 void get_node_fos( gpointer data , gpointer user_data )
00777 {
00778 #ifdef FAIL_WITH_THREADS
00779 static GStaticMutex fs_min_lock = G_STATIC_MUTEX_INIT;
00780 #endif
00781 int fail_start = *((int*)data);
00782 Fail_profile *p = (Fail_profile*)user_data;
00783 double fs, fs_min_val = 999;
00784 int fs_min_len;
00785 int fail_len;
00786
00787 for ( fail_len = MIN_FAILURE_LENGTH ;
00788 fail_len < MAX_FAILURE_LENGTH && fail_start+fail_len < p->size ;
00789 fail_len++ )
00790 {
00791 if ( !fail_get_ignore_surface( p , fail_start , fail_len ) )
00792 {
00793 fs = fail_get_fail_profile_fos( p , fail_start , fail_len );
00794
00795
00796
00797
00798 if ( fail_fos_is_valid(fs) && fs<fs_min_val )
00799
00800
00801
00802 {
00803 fs_min_val = fs;
00804 fs_min_len = fail_len;
00805 }
00806
00807 p->col[fail_start]->fs[fail_len] = fs;
00808 }
00809 else
00810 eh_debug( "ignoring surface at (%d,%d)" ,
00811 fail_start ,
00812 fail_len );
00813
00814 }
00815
00816 #ifdef FAIL_WITH_THREADS
00817 g_static_mutex_lock( &fs_min_lock );
00818 #endif
00819
00820 if ( fail_fos_is_valid( fs_min_val ) && fs_min_val<p->fs_min_val )
00821 {
00822 p->fs_min_val = fs_min_val;
00823 p->fs_min_start = fail_start;
00824 p->fs_min_len = fs_min_len;
00825 }
00826 p->count++;
00827
00828 #ifdef FAIL_WITH_THREADS
00829 g_static_mutex_unlock( &fs_min_lock );
00830 #endif
00831
00832 return;
00833 }
00834
00835 gboolean fail_fos_is_valid( double fos )
00836 {
00837 return (fos<0)?FALSE:TRUE;
00838 }
00839
00840 gboolean fail_surface_is_valid( double h )
00841 {
00842 return (h<FAIL_NO_FAIL_SURFACE)?TRUE:FALSE;
00843 }
00844
00845 void fail_set_failure_surface_ignore( Fail_profile *f , int start , int len )
00846 {
00847 f->col[start]->fs[len] = FAIL_IGNORE_SURFACE;
00848 }
00849
00850 gboolean fail_get_ignore_surface( Fail_profile *f , int start , int len )
00851 {
00852 return f->col[start]->fs[len]<=FAIL_IGNORE_SURFACE;
00853 }
00854
00855 double fail_get_fail_profile_fos( Fail_profile *f , int start , int len )
00856 {
00857 Fail_slice **s;
00858 double *ellipse;
00859 int i;
00860 double fs;
00861 gboolean need_update=FALSE;
00862
00863
00864 for ( i=0 ; i<len && need_update==FALSE ; i++ )
00865 if ( f->col[start+i]->need_update )
00866 need_update = TRUE;
00867
00868 if ( need_update )
00869 {
00870 ellipse = eh_new( double , len );
00871
00872
00873 if ( get_circle( f->p , start , len , ellipse ) )
00874 {
00875
00876 s = fail_get_janbu_parameters( f , start , ellipse , len );
00877 if ( s )
00878 {
00879
00880 fs = rtsafe_fos( &factor_of_safety , s , .005 , 500 , .01 );
00881
00882
00883 for ( i=0 ; s[i] ; i++ )
00884 eh_free( s[i] );
00885 eh_free( s );
00886 }
00887 else
00888 fs = FAIL_FOS_NOT_VALID;
00889
00890 }
00891 else
00892 fs = FAIL_FOS_NOT_VALID;
00893
00894 eh_free( ellipse );
00895 }
00896 else
00897 fs = f->col[start]->fs[len];
00898
00899 return fs;
00900 }
00901
00902 Fail_slice **fail_get_janbu_parameters( Fail_profile *f ,
00903 int start ,
00904 double *fail_height ,
00905 int fail_len )
00906 {
00907 int i;
00908 Fail_slice *s;
00909 Fail_slice **s_vec;
00910 Fail_column *c;
00911 double *depth;
00912 double a_angle=M_PI/8.;
00913 int ind, n_bins;
00914
00915 eh_require( f!=NULL );
00916 eh_require( fail_height!=NULL );
00917
00918 depth = eh_new( double , fail_len );
00919
00920 for ( i=0 ; i<fail_len && start+i<f->size ; i++ )
00921 {
00922 c = f->col[start+i];
00923 n_bins = c->size;
00924 if ( f->col[start+i]->size==0 )
00925 {
00926 eh_free( depth );
00927 return NULL;
00928 }
00929 if ( fail_height[i] > sed_cube_top_height( f->p , 0 , start+i ) )
00930 {
00931 eh_free( depth );
00932 return NULL;
00933 }
00934
00935 if ( fail_height[i] < sed_cube_base_height( f->p,0,start+i ) )
00936 depth[i] = sed_cube_base_height( f->p,0,start+i );
00937 else
00938 depth[i] = fail_height[i];
00939
00940
00941
00942
00943
00944
00945
00946 }
00947
00948 s_vec = eh_new( Fail_slice* , fail_len+1 );
00949 s_vec[fail_len] = NULL;
00950
00951 for ( i=0 ; i<fail_len ; i++ )
00952 {
00953 c = f->col[start+i];
00954
00955 n_bins = c->size;
00956
00957
00958 for ( ind=0 ; ind<n_bins && c->height[ind]<depth[i] ; ind++ );
00959 if ( ind>= n_bins )
00960 ind = n_bins - 1;
00961
00962 s = eh_new( Fail_slice , 1 );
00963
00964 s->a_vertical = sed_cube_quake( f->p )*cos(a_angle);
00965 s->a_horizontal = sed_cube_quake( f->p )*sin(a_angle);
00966
00967
00968
00969
00970
00971
00972 s->depth = sed_cube_top_height( f->p,0,start+i ) - depth[i];
00973
00974 s->c = c->c[ind];
00975 s->u = c->u[ind];
00976 s->phi = c->phi[ind];
00977
00978 s->b = sed_cube_y_res(f->p);
00979 s->w = c->w[ind]*s->b;
00980
00981 if ( i==fail_len-1 )
00982 s->alpha = fabs(atan( (depth[i]-depth[i-1])/s->b) );
00983 else
00984 s->alpha = fabs(atan( (depth[i+1]-depth[i])/s->b) );
00985
00986 if ( s->u > .9*s->w/s->b )
00987 s->u = .9*s->w/s->b;
00988
00989 s_vec[i] = s;
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 }
01013
01014
01015
01016
01017
01018
01019 eh_free( depth );
01020
01021 return s_vec;
01022 }
01023
01024 Fail_column *fail_reinit_fail_column( Fail_column *f ,
01025 Sed_column c ,
01026 double h ,
01027 Failure_t fail_const )
01028 {
01029 int i, i_bot;
01030 double depth;
01031 double gravity = sed_gravity();
01032 int n_bins;
01033 double hydro_static;
01034 Sed_property friction_angle = sed_property_new( "friction angle" );
01035 Sed_property cohesion = sed_property_new( "cohesion" );
01036
01037 eh_require( c!=NULL );
01038
01039
01040
01041 if ( fail_surface_is_valid( h ) )
01042 n_bins = sed_column_top_nbins( c , h );
01043 else
01044 n_bins = 0;
01045
01046 if ( f )
01047 f = fail_reuse_fail_column( f );
01048 else
01049 f = fail_create_fail_column( n_bins , TRUE );
01050
01051 f = fail_resize_fail_column( f , n_bins );
01052
01053 if ( n_bins>0 )
01054 {
01055
01056 i_bot = sed_column_index_at( c , h );
01057
01058 hydro_static = sed_column_water_pressure( c );
01059
01060 #ifdef FAIL_LOCAL_MODEL // the local model.
01061 f->phi = sed_column_avg_property( friction_angle ,
01062 c ,
01063 i_bot ,
01064 n_bins ,
01065 f->phi );
01066 f->c = sed_column_avg_property_with_load( cohesion ,
01067 c ,
01068 i_bot ,
01069 n_bins ,
01070 f->c );
01071 #endif
01072
01073 for ( i=0 ; i<n_bins ; i++ )
01074 {
01075 f->height[i] = sed_column_base_height( c )
01076 + sed_cell_size( sed_column_nth_cell( c , i_bot+i-1 ) );
01077
01078
01079
01080
01081 if ( f->height[i] < h )
01082 f->height[i] = h;
01083 depth = sed_column_top_height( c ) - f->height[i];
01084
01085
01086
01087
01088 f->w[i] = ( sed_column_top_rho(c,depth)
01089 - fail_const.density_sea_water)
01090 * gravity*depth;
01091
01092 #ifdef FAIL_LOCAL_MODEL
01093
01094
01095 f->phi[i] *= S_RADS_PER_DEGREE;
01096
01097
01098
01099 f->u[i] = sed_cell_excess_pressure( sed_column_nth_cell(c,i_bot+i) ,
01100 hydro_static );
01101
01102 #else // the global model
01103
01104 f->phi[i] = fail_const.frictionAngle;
01105 f->c[i] = fail_const.cohesion;
01106 f->u[i] = f->w[i] / get_m( c , depth , fail_const.consolidation );
01107
01108 #endif
01109
01110 }
01111
01112 }
01113
01114 f->failure_line = h;
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 sed_property_destroy( friction_angle );
01125 sed_property_destroy( cohesion );
01126
01127 return f;
01128 }
01129
01130
01131 Fail_column *fail_init_fail_column( Sed_column c , double h , Failure_t fail_const )
01132 {
01133 return fail_reinit_fail_column( NULL , c , h , fail_const );
01134 }
01135