/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/failure/getsurface.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 
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 //    GStaticMutex fail_mutex=G_STATIC_MUTEX_INIT;
00039    double *ellipse;
00040    gssize *x, *y;
00041    int i;
00042    
00043 /*
00044    g_mutex_lock( fail_mutex );
00045    if ( !fail )
00046    {
00047 // create a profile that is large enough to hold any potential failure surface.
00048       fail = sed_create_cube( 1 , FAIL_MAX_FAILURE_LENGTH , p->sed );
00049    }
00050    g_mutex_unlock( fail_mutex );
00051 */
00052 
00053    // if there is no sediment in the first column, return null.
00054    if ( sed_column_thickness( sed_cube_col(p,start) ) < 1e-5 )
00055       return NULL;
00056 
00057    // if the end of the failure is higher than the start, return null.  
00058    // this should be changed to allow failures on slopes that are negative.
00059    // the main reason to turn this off is because the turbidity current 
00060    // model isn't set up to move flows from right to left.
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    // get the elevations of the failure surface.  the failure surface 
00070    // will either be a quarter ellipse (get_ellipse) or a semi circle 
00071    // (get_circle).
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    // remove the failure surface from the profile.
00086 //   fail = sed_get_1d_cube_from_cube( p , x , ellipse , len , NULL );
00087    fail = sed_cube_copy_cols( p , x , y , ellipse , len );
00088 
00089    // check if the failure surface is ok.  if there are columns with 
00090    // no sediment, return null.
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       // Get the index to the top bin.
00240       i2 = sed_column_index_depth(s,0);
00241 
00242       // Get the index to the bottom bin.
00243       i1 = sed_column_index_depth(s,depth);
00244       if ( i1 < 0 ) i1 = 0;
00245 
00246       // Time (in seconds) over which this thickness of sediment was 
00247       // deposited.
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       // The average rate at which this sediment was deposited.
00253       if ( delta_t <= 0. )
00254          rate = 0.;
00255       else
00256          rate = depth/delta_t;
00257 
00258       // The time factor used in polynomial approximation for constant
00259       // relating excess pore pressure to gamma' and failure depth.
00260       t = rate*rate*delta_t/consolidation;
00261 
00262       // Return the approximated relation.
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    // allocate memory for the failure slices.
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    // draw potential failure planes to determine which cells need 
00582    // to be examined.
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 // divide the profile up into blocks of block_size columns each.  
00625 // a single thread pool will work on each block.
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 // mark each column as updated.
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    // calculate the new elevations of the failure line.
00695    failure_line = fail_get_failure_line( p->p );
00696 
00697 p->count = 0;
00698 
00699    // look for changes in the elevation of the failure plane between the 
00700    // sed_profile and the fail_profile.
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 eh_watch_dbl( fabs(fail_col_h-sed_col_h) );
00714 eh_watch_dbl( f_col->failure_line );
00715 eh_watch_dbl( fail_col_h );
00716 eh_watch_dbl( sed_col_h );
00717 eh_watch_int( f_col->size-1 );
00718 eh_watch_dbl_vec( f_col->height , 0 , f_col->size-1 );
00719 */
00720 
00721       // Assume the the factor of safety does not need to be recalculated if
00722       // the column did not change in thickness by some amount.  Say for now,
00723       // 10cm.
00724 //      if ( fabs(fail_col_h-sed_col_h) > FAIL_MIN_DELTA_H )
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 // mark all of the failure surfaces that need to be calculated again.
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 // reset the minimum factor of safety values for the profile.
00749    p->fs_min_val   = 999;
00750    p->fs_min_start = -1;
00751    p->fs_min_len   = -1;
00752 
00753 // find the minimum factor of safety from the surfaces that have not changed.
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 // NOTE: Toggle between these statements to choose the surface to fail.
00796 // Choose the surface with the lowest factor of safety or choose the
00797 // largest surface that is less than the factor of safety needed for failure.
00798          if ( fail_fos_is_valid(fs) && fs<fs_min_val )
00799 //         if (    fail_fos_is_valid(fs)
00800 //              && fs<MIN_FACTOR_OF_SAFETY
00801 //              && fail_len>fs_min_len )
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    // first check if the fos has already been calculated.
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       // get the elevations to the failure surface.
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             // s is null terminated.
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       if ( depth[i] > c->height[n_bins-1] )
00941       {
00942          eh_free( depth );
00943          return NULL;
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       // determine the index to the cell at the failure surface.
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 //      s->depth        = c->height[n_bins-1] - depth[i];
00967 //      s->depth        = sed_get_floor_height( c ) - depth[i];
00968 
00969       // The thickness of sediment in the failure (s->depth) should be
00970       // measured from the sea floor to the failure plane.  Remember that
00971       // c->depth[] is the elevation measured to the bottom of each bin.
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 //      s->b            = f->p->colWidth;
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 if ( start == 788 && fail_len == 22 )
00992 {
00993    eh_watch_dbl( s->a_vertical );
00994    eh_watch_dbl( s->a_horizontal );
00995    eh_watch_dbl( s->depth );
00996    eh_watch_dbl( s->c );
00997    eh_watch_dbl( s->u );
00998    eh_watch_dbl( s->phi );
00999    eh_watch_dbl( s->b );
01000    eh_watch_dbl( s->w );
01001    eh_watch_dbl( s->alpha );
01002    eh_watch_dbl( s->u );
01003    eh_watch_int( n_bins );
01004 }
01005 */
01006 
01007 /*
01008 if ( s->depth < 0 )
01009    eh_error( "DEPTH = %f" , s->depth );
01010 */
01011 
01012    }
01013 /*
01014 if ( start == 788 && fail_len == 22 )
01015    eh_exit(-1);
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    // check the number of cells in the new column and make sure that it
01040    // is less then the length of the recycled column.
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          // The height of the failure column (f->height) is measured to the
01079          // bottom of a bin and so if the failure plane (h) cuts through this
01080          // bin, it will be heigher than the elevation of the bin.
01081          if ( f->height[i] < h )
01082             f->height[i] = h;
01083          depth        = sed_column_top_height( c ) - f->height[i];
01084 
01085 // the weight of the sediment.
01086 //         f->w[i]      = sed_get_top_rho( c , depth );
01087 //         f->w[i]      = (f->w[i]-fail_const.density_sea_water)*gravity*depth;
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   // the local model.
01093 
01094 //         f->phi[i]    = sed_get_top_property( S_FRICTION_ANGLE , c , depth )
01095          f->phi[i]   *= S_RADS_PER_DEGREE;
01096 //         f->c[i]      = sed_get_top_property_with_load( S_COHESION ,
01097 //                                                        c ,
01098 //                                                        depth );
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    if ( h>1e50 )
01117    {
01118       eh_message( "%f" , h );
01119       eh_message( "%f" , FAIL_NO_FAIL_SURFACE );
01120       eh_error( "FAILURE LINE : %f" , h );
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 

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