/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/sedflux/run_subsidence.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 <fcntl.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 #define SED_SUBSIDENCE_PROC_NAME "subsidence"
00027 #define EH_LOG_DOMAIN SED_SUBSIDENCE_PROC_NAME
00028 
00029 #include <utils/utils.h>
00030 #include <sed/sed_sedflux.h>
00031 #include "my_processes.h"
00032 
00033 typedef struct
00034 {
00035    double time;
00036    double *rate;
00037 }
00038 Subsidence_record_t;
00039 
00040 //GArray *read_tectonic_curve(const char *filename, double *x_resample, int len);
00041 int get_tectonics(GArray *rate_array, double year, double *rate_resample, int len);
00042 
00043 gboolean init_subsidence_data( Sed_process proc , Sed_cube prof , GError** error );
00044 
00045 Sed_process_info
00046 run_subsidence( Sed_process proc , Sed_cube prof )
00047 {
00048    Subsidence_t*    data = sed_process_user_data(proc);
00049    Sed_process_info info = SED_EMPTY_INFO;
00050    gsize i, j, n;
00051    double year;
00052    double start_year, end_year;
00053    double upper_edge, lower_edge;
00054    double time_step, total_time=0., total_subsidence=0.;
00055 
00056    if ( sed_process_run_count(proc)==0 )
00057       init_subsidence_data( proc , prof , NULL );
00058 
00059    start_year      = data->last_year;
00060    end_year        = sed_cube_age_in_years( prof );
00061    year            = sed_cube_age_in_years( prof );
00062    time_step       = year - data->last_year;
00063    data->last_year = year;
00064 
00065    eh_message( "subsidence time step (years): %f" , time_step );
00066 
00067    //---
00068    // Subside the basin.  If there is only one subsidence record, assume that 
00069    // subsidence is constant with time.  If there are multiple records
00070    // integrate the subsidence over the time step.
00071    //
00072    // Note that the time step will be 0 at the beginning of an epoch, in
00073    // this case, don't do anything.
00074    //---
00075    if ( data->subsidence_seq->len == 1 && time_step>1e-6 )
00076    {
00077       double** sub_grid = eh_dbl_grid_data(data->subsidence_seq->data[0]);
00078       for ( i=0 ; i<sed_cube_n_x(prof) ; i++ )
00079          for ( j=0 ; j<sed_cube_n_y(prof) ; j++ )
00080             sed_cube_adjust_base_height( prof , i , j , sub_grid[i][j]*time_step );
00081    }
00082    else if ( time_step>1e-6 )
00083    {
00084       for ( n=0,total_time=0 ; n<data->subsidence_seq->len ; n++ )
00085       {
00086          lower_edge = data->subsidence_seq->t[n];
00087          if ( n<data->subsidence_seq->len-1 )
00088             upper_edge = data->subsidence_seq->t[n+1];
00089          else
00090             upper_edge = G_MAXDOUBLE;
00091 
00092          if ( start_year >= upper_edge )
00093             time_step = -1;
00094          else if ( start_year >= lower_edge && end_year <  upper_edge )
00095             time_step = end_year - start_year;
00096          else if ( start_year < lower_edge && end_year >= upper_edge )
00097             time_step = upper_edge - lower_edge;
00098          else if ( start_year >= lower_edge && end_year >= upper_edge )
00099             time_step = upper_edge - start_year;
00100          else if ( start_year <  lower_edge && end_year <  upper_edge )
00101             time_step = end_year - lower_edge;
00102          else
00103             time_step = -1;
00104 
00105          if ( time_step > 0 )
00106          {
00107             double dz;
00108             double** sub_grid_l = eh_dbl_grid_data(data->subsidence_seq->data[n]  );
00109             double** sub_grid_h = eh_dbl_grid_data(data->subsidence_seq->data[n+1]);
00110             
00111             total_time += time_step;
00112             for ( i=0 ; i<sed_cube_n_x(prof) ; i++ )
00113                for ( j=0 ; j<sed_cube_n_y(prof) ; j++ )
00114                {
00115                   dz = (   (sub_grid_h[i][j] - sub_grid_l[i][j] )
00116                          / (upper_edge - lower_edge ) )
00117                      * (start_year - lower_edge)
00118                      + sub_grid_l[i][j];
00119                   sed_cube_adjust_base_height( prof , i , j , dz*time_step );
00120                   total_subsidence += dz*time_step;
00121                }
00122          }
00123       }
00124 
00125       if ( fabs( total_time - (end_year-start_year) ) > 1e-5 )
00126       {
00127          eh_warning( "The current time interval is not completely contained "
00128                      " within the subsidence curve." );
00129          eh_warning( "Start of this time interval: %f" , start_year );
00130          eh_warning( "End of this time interval: %f" , end_year );
00131          eh_warning( "Total time: %f" , total_time );
00132       }
00133    }
00134 
00135    eh_message( "Time: %f"                 , sed_cube_age( prof ) );
00136    eh_message( "Total subsidence (m): %f" , total_subsidence );
00137 
00138    return info;
00139 }
00140 
00141 #define SUBSIDENCE_KEY_FILENAME "subsidence file"
00142 
00143 static gchar* subsidence_req_labels[] =
00144 {
00145    SUBSIDENCE_KEY_FILENAME ,
00146    NULL
00147 };
00148 
00149 gboolean
00150 init_subsidence( Sed_process p , Eh_symbol_table tab , GError** error )
00151 {
00152    Subsidence_t* data    = sed_process_new_user_data( p , Subsidence_t );
00153    GError*       tmp_err = NULL;
00154    gboolean      is_ok   = TRUE;
00155 
00156    eh_return_val_if_fail( error==NULL || *error==NULL , FALSE );
00157 
00158    data->last_year      = 0.;
00159    data->subsidence_seq = NULL;
00160 
00161    eh_symbol_table_require_labels( tab , subsidence_req_labels , &tmp_err );
00162 
00163    if ( !tmp_err )
00164    {
00165       data->filename = eh_symbol_table_value( tab , SUBSIDENCE_KEY_FILENAME );
00166 
00167       eh_touch_file( data->filename , O_RDONLY , &tmp_err );
00168    }
00169 
00170    if ( tmp_err )
00171    {
00172       g_propagate_error( error , tmp_err );
00173       is_ok = FALSE;
00174    }
00175 
00176    return is_ok;
00177 }
00178 
00179 gboolean
00180 init_subsidence_data( Sed_process proc , Sed_cube prof , GError** error )
00181 {
00182    gboolean      is_ok = TRUE;
00183    Subsidence_t* data  = sed_process_user_data( proc );
00184 
00185    if ( data )
00186    {
00187       GError* tmp_err = NULL;
00188       double* y       = sed_cube_y( prof , NULL );
00189 
00190       data->last_year = sed_cube_age_in_years(prof);
00191 
00192       if ( sed_mode_is_3d() )
00193          data->subsidence_seq  = sed_get_floor_sequence_3(
00194                                     data->filename ,
00195                                     sed_cube_x_res( prof ) ,
00196                                     sed_cube_y_res( prof ) ,
00197                                     &tmp_err );
00198       else
00199          data->subsidence_seq  = sed_get_floor_sequence_2(
00200                                     data->filename     ,
00201                                     y                  ,
00202                                     sed_cube_n_y(prof) ,
00203                                     &tmp_err );
00204 
00205       eh_free( y );
00206 
00207       if ( tmp_err )
00208       {
00209          g_propagate_error( error , tmp_err );
00210          is_ok = FALSE;
00211       }
00212    }
00213 
00214    return is_ok;
00215 }
00216 
00217 gboolean
00218 destroy_subsidence( Sed_process p )
00219 {
00220    if ( p )
00221    {
00222       Subsidence_t* data = sed_process_user_data( p );
00223       
00224       if ( data )
00225       {
00226          gint i;
00227 
00228          if ( data->subsidence_seq )
00229          {
00230             for ( i=0 ; i<data->subsidence_seq->len ; i++ )
00231                eh_grid_destroy( data->subsidence_seq->data[i] , TRUE );
00232             eh_destroy_sequence( data->subsidence_seq , FALSE );
00233          }
00234 
00235          eh_free( data->filename );
00236          eh_free( data           );
00237       }
00238    }
00239 
00240    return TRUE;
00241 }
00242 
00243 gboolean dump_subsidence_data( gpointer ptr , FILE *fp )
00244 {
00245    Subsidence_t *data = (Subsidence_t*)ptr;
00246    guint len;
00247 
00248    len = strlen( data->filename )+1;
00249    fwrite( &len , sizeof(guint) , 1 , fp );
00250    fwrite( data->filename , sizeof(char) , len , fp );
00251 
00252    fwrite( &(data->last_year) , sizeof(double) , 1 , fp );
00253 
00254    len = data->tectonic_curve->len;
00255    fwrite( &len , sizeof(guint) , 1 , fp );
00256    fwrite( data->tectonic_curve->data , sizeof(double) , len , fp );
00257 
00258    return TRUE;
00259 }
00260 
00261 gboolean load_subsidence_data( gpointer ptr , FILE *fp )
00262 {
00263    Subsidence_t *data = (Subsidence_t*)ptr;
00264    guint len;
00265    double *tectonic_data;
00266 
00267    fread( &len , sizeof(guint) , 1 , fp );
00268    fread( data->filename , sizeof(char) , len , fp );
00269 
00270    fread( &(data->last_year) , sizeof(double) , 1 , fp );
00271 
00272    fread( &len , sizeof(guint) , 1 , fp );
00273    tectonic_data = eh_new( double , len );
00274    fread( tectonic_data , sizeof(double) , len , fp );
00275 
00276    data->tectonic_curve = g_array_new( FALSE , FALSE , sizeof(double) );
00277    g_array_append_vals( data->tectonic_curve , tectonic_data , len );
00278 
00279    return TRUE;
00280 }
00281 
00282 int get_tectonics(GArray *rate_array, double year, double *rate_resample, int len)
00283 {
00284    int i, j;
00285    Subsidence_record_t r1, r2;
00286    double time[2], rate[2], *rate1, *rate2;
00287 
00288 // Determine which times we are between.
00289    for ( i=0 ;
00290             i<rate_array->len 
00291          && g_array_index(rate_array,Subsidence_record_t,i).time <= year ;
00292          i++ );
00293 
00294 // Interpolate for the rates at the present time.  If we are at a time outside
00295 // of the data, use the last rate given.
00296    if ( i >= rate_array->len )
00297    {
00298       g_warning( "current time is outside of bounds in subsidence file" );
00299       g_warning( "using the rates from the last subsidence record"      );
00300       i = rate_array->len-1;
00301       year = g_array_index( rate_array , Subsidence_record_t , i ).time;
00302    }
00303    if ( i == 0 )
00304    {
00305       g_warning( "current time is outside of bounds in subsidence file" );
00306       g_warning( "using the rates from the first subsidence record"     );
00307       i = 1;
00308       year = g_array_index( rate_array , Subsidence_record_t , 0 ).time;
00309    }
00310 
00311    r1 = g_array_index( rate_array , Subsidence_record_t , i-1 );
00312    r2 = g_array_index( rate_array , Subsidence_record_t , i   );
00313 
00314    rate1 = r1.rate;
00315    rate2 = r2.rate;
00316 
00317    time[0] = r1.time;
00318    time[1] = r2.time;
00319 
00320    for ( j=0 ; j<len ; j++ )
00321    {
00322       rate[0] = rate1[j];
00323       rate[1] = rate2[j];
00324 
00325       interpolate( time , rate , 2 , &year , &rate_resample[j] , 1 );
00326    }
00327 
00328    return 0;
00329 
00330 }
00331 /*
00332 #define S_KEY_SUBSIDENCE_TIME "time"
00333 
00334 GArray *read_tectonic_curve(const char *filename, double *x_resample, int len)
00335 {
00336    int i;
00337    GPtrArray *data;
00338    GArray *rate_array = g_array_new( FALSE ,
00339                                      FALSE ,
00340                                      sizeof(Subsidence_record_t) );
00341    double *y_resample = eh_new0( double , len );
00342    double time;
00343    GPtrArray *x, *y;
00344    Subsidence_record_t rate;
00345    Eh_data_record *entry;
00346 
00347    data = eh_scan_data_file( filename , "," , FALSE , TRUE );
00348 
00349    if ( data->len < 2 )
00350       g_error("less than two subsidence records was found in %s." , filename );
00351 
00352    for ( i=0 ; i<data->len ; i++ )
00353    {
00354       y_resample = eh_new0( double , len );
00355 
00356       entry = g_ptr_array_index( data , i );
00357       time = strtotime( eh_symbol_table_lookup( entry->symbol_table ,
00358                                                 S_KEY_SUBSIDENCE_TIME ) );
00359       x = g_ptr_array_index( entry->data , 0 );
00360       y = g_ptr_array_index( entry->data , 1 );
00361 
00362       if (    x_resample[len-1] > ((double*)x->pdata)[x->len-1]
00363            || x_resample[0]     < ((double*)x->pdata)[0] )
00364          g_error( "subsidence rates not given for the entire model domain" );
00365 
00366       interpolate( (double*)x->pdata , (double*)y->pdata , x->len ,
00367                     x_resample       , y_resample        , len );
00368 
00369       rate.time = time;
00370       rate.rate = y_resample;
00371 
00372       g_array_append_val( rate_array , rate );
00373    }
00374 
00375    return rate_array;
00376 }
00377 */
00378 

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