00001 #include <stdio.h>
00002 #include <glib.h>
00003
00004 #include "utils/utils.h"
00005 #include "sed_property_file.h"
00006
00007 CLASS ( Sed_property_file_attr )
00008 {
00009 Sed_get_val_func get_val;
00010 double lower_clip;
00011 double upper_clip;
00012 double water_val;
00013 double rock_val;
00014 double x_res;
00015 double y_res;
00016 double z_res;
00017 double x_lim[2];
00018 double y_lim[2];
00019 double z_lim[2];
00020 Sed_data_type type;
00021 gpointer user_data;
00022 };
00023
00024 CLASS ( Sed_property_file_header )
00025 {
00026 gssize n_rows;
00027 gssize n_x_cols;
00028 gssize n_y_cols;
00029 double cell_dx;
00030 double cell_dy;
00031 double cell_dz;
00032 double min_value, max_value;
00033 double water_value, rock_value;
00034 Sed_property property;
00035 double sea_level;
00036 double ref_x, ref_y, ref_z;
00037 int byte_order;
00038 int element_size;
00039 };
00040
00041 CLASS ( Sed_property_file )
00042 {
00043 FILE* fp;
00044 Sed_property p;
00045 Sed_property_file_header h;
00046 Sed_property_file_attr attr;
00047 double** data;
00048 };
00049
00050 Sed_property_file sed_property_file_new( const char* file , Sed_property p , Sed_property_file_attr a )
00051 {
00052 Sed_property_file f = NULL;
00053
00054 eh_require( file );
00055 eh_require( p );
00056
00057 if ( file && p )
00058 {
00059 NEW_OBJECT( Sed_property_file , f );
00060
00061 f->fp = fopen( file , "wb" );
00062 if ( !f->fp )
00063 eh_error( "Cound not open sedflux property file." );
00064
00065 f->h = NULL;
00066 f->p = p;
00067
00068 if ( a )
00069 f->attr = sed_property_file_attr_dup( a );
00070 else
00071 f->attr = sed_property_file_attr_new( );
00072
00073 f->attr->get_val = NULL;
00074
00075 f->data = NULL;
00076 }
00077
00078 return f;
00079 }
00080
00081 Sed_property_file sed_property_file_destroy( Sed_property_file f )
00082 {
00083 if ( f )
00084 {
00085 if ( f->data )
00086 {
00087 eh_free( f->data[0] );
00088 eh_free( f->data );
00089 }
00090
00091 sed_property_file_attr_destroy( f->attr );
00092 sed_property_file_header_destroy( f->h );
00093
00094 fclose( f->fp );
00095 eh_free( f );
00096 }
00097 return NULL;
00098 }
00099
00100 Sed_property_file_attr sed_property_file_attr_new( )
00101 {
00102 Sed_property_file_attr a;
00103
00104 NEW_OBJECT( Sed_property_file_attr , a );
00105
00106 a->get_val = NULL;
00107 a->lower_clip = -G_MAXDOUBLE;
00108 a->upper_clip = G_MAXDOUBLE;
00109 a->water_val = -G_MAXDOUBLE;
00110 a->rock_val = G_MAXDOUBLE;
00111 a->x_res = 0;
00112 a->y_res = 0;
00113 a->z_res = 0;
00114 a->x_lim[0] = -G_MAXDOUBLE;
00115 a->x_lim[1] = G_MAXDOUBLE;
00116 a->y_lim[0] = -G_MAXDOUBLE;
00117 a->y_lim[1] = G_MAXDOUBLE;
00118 a->z_lim[0] = -G_MAXDOUBLE;
00119 a->z_lim[1] = G_MAXDOUBLE;
00120 a->type = SED_TYPE_UINT8;
00121 a->user_data = NULL;
00122
00123 return a;
00124 }
00125
00126 Sed_property_file_attr sed_property_file_attr_copy( Sed_property_file_attr dest , Sed_property_file_attr src )
00127 {
00128 if ( !dest )
00129 dest = sed_property_file_attr_new();
00130
00131 g_memmove( dest , src , sizeof( Sed_property_file_attr ) );
00132
00133 return dest;
00134 }
00135
00136 Sed_property_file_attr sed_property_file_attr_dup( Sed_property_file_attr src )
00137 {
00138 return sed_property_file_attr_copy( NULL , src );
00139 }
00140
00141 Sed_property_file_attr sed_property_file_attr_destroy( Sed_property_file_attr a )
00142 {
00143 if ( a )
00144 {
00145 eh_free( a );
00146 }
00147 return NULL;
00148 }
00149
00150 Sed_property_file_header sed_property_file_header_destroy( Sed_property_file_header h )
00151 {
00152 if ( h )
00153 {
00154 sed_property_destroy( h->property );
00155 eh_free( h );
00156 }
00157 return NULL;
00158 }
00159
00160 gssize sed_property_file_header_fprint( FILE *fp , Sed_property_file_header hdr );
00161 Sed_property_file_header sed_property_file_header_new( const Sed_cube p ,
00162 Eh_ndgrid g ,
00163 Sed_property property );
00164 double sed_cube_min_height( Sed_cube p , gssize **col_id );
00165 double sed_cube_max_height( Sed_cube p , gssize **col_id );
00166 gssize *sed_cube_x_cols_between( Sed_cube p , double dx , double left , double right );
00167 gssize *sed_cube_y_cols_between( Sed_cube p , double dy , double bottom , double top );
00168 gssize sed_cube_n_rows_between( Sed_cube p , double dz , double lower , double upper , gssize *col_id );
00169 Eh_ndgrid sed_cube_property_subgrid( Sed_cube p ,
00170 Sed_property property ,
00171 double lower_left[3] ,
00172 double upper_right[3] ,
00173 double resolution[3] );
00174
00175 gssize sed_property_file_write( Sed_property_file sed_fp , Sed_cube p )
00176 {
00177 gssize n = 0;
00178
00179 eh_require( sed_fp );
00180 eh_require( p );
00181
00182 if ( sed_fp && p )
00183 {
00184 Eh_ndgrid g;
00185 double lower_left[3];
00186 double upper_right[3];
00187 double resolution[3];
00188
00189 lower_left[0] = sed_fp->attr->x_lim[0];
00190 lower_left[1] = sed_fp->attr->y_lim[0];
00191 lower_left[2] = sed_fp->attr->z_lim[0];
00192 upper_right[0] = sed_fp->attr->x_lim[1];
00193 upper_right[1] = sed_fp->attr->y_lim[1];
00194 upper_right[2] = sed_fp->attr->z_lim[1];
00195 resolution[0] = sed_fp->attr->x_res;
00196 resolution[1] = sed_fp->attr->y_res;
00197 resolution[2] = sed_fp->attr->z_res;
00198
00199 g = sed_cube_property_subgrid( p ,
00200 sed_fp->p ,
00201 lower_left ,
00202 upper_right ,
00203 resolution );
00204
00205 sed_fp->h = sed_property_file_header_new( p , g , sed_fp->p );
00206
00207 n += sed_property_file_header_fprint( sed_fp->fp , sed_fp->h );
00208 n += eh_ndgrid_write( sed_fp->fp , g );
00209
00210 eh_ndgrid_destroy( g );
00211 }
00212
00213 return n;
00214 }
00215
00216 gssize sed_property_file_header_fprint( FILE *fp , Sed_property_file_header hdr )
00217 {
00218 gssize n = 0;
00219
00220 eh_require( fp );
00221 eh_require( hdr );
00222
00223 if ( fp && hdr )
00224 {
00225 char* date_str = eh_new( char , 2048 );
00226 char* program_str = eh_new( char , 2048 );
00227 char* property_name = sed_property_name( hdr->property );
00228 GDate *today = g_date_new( );
00229
00230 g_date_set_time( today , time(NULL) );
00231 g_date_strftime( date_str , 2048 , "%A %e %B %Y %T %Z" , today );
00232
00233 fflush( fp );
00234
00235 n += fprintf( fp , "--- header ---\n" );
00236
00237 g_snprintf( program_str , 2048 , "%s %s" ,
00238 PROGRAM_NAME ,
00239 SED_VERSION_S );
00240
00241 n += fprintf( fp , "SEDFLUX property file version: %s\n" , program_str );
00242 n += fprintf( fp , "Creation date: %s\n" , date_str );
00243 n += fprintf( fp , "Property: %s\n" , property_name );
00244 n += fprintf( fp , "Number of rows: %d\n" , (gint)hdr->n_rows );
00245 n += fprintf( fp , "Number of x-columns: %d\n" , (gint)hdr->n_x_cols );
00246 n += fprintf( fp , "Number of y-columns: %d\n" , (gint)hdr->n_y_cols );
00247 n += fprintf( fp , "dx: %f\n" , hdr->cell_dx );
00248 n += fprintf( fp , "dy: %f\n" , hdr->cell_dy );
00249 n += fprintf( fp , "dz: %f\n" , hdr->cell_dz );
00250 n += fprintf( fp , "Sea level: %f\n" , hdr->sea_level );
00251 n += fprintf( fp , "Bottom-side coordinate: %f\n" , hdr->ref_z );
00252 n += fprintf( fp , "North-side coordinate: %f\n" , hdr->ref_x );
00253 n += fprintf( fp , "West-side coordinate: %f\n" , hdr->ref_y );
00254 n += fprintf( fp , "Data type: %s\n" , "DOUBLE" );
00255 n += fprintf( fp , "Rock value: %g\n" , hdr->rock_value );
00256 n += fprintf( fp , "Water value: %g\n" , hdr->water_value );
00257 n += fprintf( fp , "Byte order: %d\n" , hdr->byte_order );
00258
00259 n += fprintf( fp , "--- data ---\n" );
00260
00261 fflush( fp );
00262
00263 g_date_free( today );
00264 eh_free( property_name );
00265 eh_free( program_str );
00266 eh_free( date_str );
00267 }
00268
00269 return n;
00270 }
00271
00272 Sed_property_file_header sed_property_file_header_new( const Sed_cube p ,
00273 Eh_ndgrid g ,
00274 Sed_property property )
00275 {
00276 Sed_property_file_header hdr = NULL;
00277
00278 eh_require( p );
00279 eh_require( g );
00280 eh_require( property );
00281
00282 if ( p && g && property )
00283 {
00284 NEW_OBJECT( Sed_property_file_header , hdr );
00285
00286 hdr->n_rows = eh_ndgrid_n( g , 2 );
00287 hdr->n_y_cols = eh_ndgrid_n( g , 1 );
00288 hdr->n_x_cols = eh_ndgrid_n( g , 0 );
00289 hdr->cell_dx = sed_cube_x_res( p );
00290 hdr->cell_dy = sed_cube_y_res( p );
00291 hdr->cell_dz = sed_cube_z_res( p );
00292 hdr->property = property;
00293 hdr->sea_level = sed_cube_sea_level( p );
00294 hdr->ref_z = eh_ndgrid_x( g , 2 )[0];
00295 hdr->ref_y = eh_ndgrid_x( g , 1 )[0];
00296 hdr->ref_x = eh_ndgrid_x( g , 0 )[0];
00297 hdr->byte_order = G_BYTE_ORDER;
00298 hdr->element_size = sizeof(double);
00299 hdr->rock_value = G_MAXDOUBLE;
00300 hdr->water_value = -G_MAXDOUBLE;
00301 }
00302
00303 return hdr;
00304 }
00305
00306 Eh_ndgrid sed_cube_property_subgrid( Sed_cube p ,
00307 Sed_property property ,
00308 double lower_left[3] ,
00309 double upper_right[3] ,
00310 double resolution[3] )
00311 {
00312 gssize i, j, k, n, id;
00313 double bottom, top;
00314 double dx, dy, dz;
00315 double hydro_static;
00316 double *load;
00317 gssize sediment_rows, rock_rows, water_rows;
00318 gssize top_sed, bot_sed;
00319 Sed_column col_temp;
00320 Eh_dbl_grid g;
00321 Eh_ndgrid g_3;
00322 double lower_left_x, lower_left_y, lower_left_z;
00323 double upper_right_x, upper_right_y, upper_right_z;
00324 gssize *cols, *x_cols, *y_cols;
00325 gssize n_rows, n_x_cols, n_y_cols;
00326 gboolean with_load, excess_pressure;
00327
00328 excess_pressure = sed_property_is_named( property , "EXCESS PRESSURE" );
00329 with_load = sed_property_is_named( property , "EXCESS PRESSURE" )
00330 | sed_property_is_named( property , "COHESION" )
00331 | sed_property_is_named( property , "SHEAR STRENGTH" );
00332
00333 lower_left_x = sed_cube_col_x( p,0 );
00334 lower_left_y = sed_cube_col_y( p,0 );
00335 lower_left_z = sed_cube_min_height( p , NULL );
00336
00337 if ( lower_left )
00338 {
00339 lower_left_x = eh_max( lower_left[0] , lower_left_x );
00340 lower_left_y = eh_max( lower_left[1] , lower_left_y );
00341 lower_left_z = eh_max( lower_left[2] , lower_left_z );
00342 }
00343
00344 upper_right_x = sed_cube_col_x( p , sed_cube_size(p)-1 );
00345 upper_right_y = sed_cube_col_y( p , sed_cube_size(p)-1 );
00346 upper_right_z = sed_cube_max_height( p , NULL );
00347
00348 if ( upper_right )
00349 {
00350 upper_right_x = eh_min( upper_right[0] , upper_right_x );
00351 upper_right_y = eh_min( upper_right[1] , upper_right_y );
00352 upper_right_z = eh_min( upper_right[2] , upper_right_z );
00353 }
00354
00355 dx = sed_cube_x_res( p );
00356 dy = sed_cube_y_res( p );
00357 dz = sed_cube_z_res( p );
00358
00359 if ( resolution )
00360 {
00361 dx = (resolution[0]>0)?resolution[0]:sed_cube_x_res( p );
00362 dy = (resolution[1]>0)?resolution[1]:sed_cube_y_res( p );
00363 dz = (resolution[2]>0)?resolution[2]:sed_cube_z_res( p );
00364 }
00365
00366 x_cols = sed_cube_x_cols_between( p , dx , lower_left_x , upper_right_x );
00367 y_cols = sed_cube_y_cols_between( p , dy , lower_left_y , upper_right_y );
00368
00369 for ( n_x_cols=0 ; x_cols[n_x_cols]>=0 ; n_x_cols++ );
00370 for ( n_y_cols=0 ; y_cols[n_y_cols]>=0 ; n_y_cols++ );
00371
00372 cols = eh_new( gssize , n_x_cols*n_y_cols+1 );
00373 for ( i=0,n=0 ; i<n_x_cols ; i++ )
00374 for ( j=0 ; j<n_y_cols ; j++,n++ )
00375 cols[n] = sed_cube_id( p , x_cols[i] , y_cols[j] );
00376 cols[n] = -1;
00377
00378 eh_free( x_cols );
00379 eh_free( y_cols );
00380
00381 n_rows = sed_cube_n_rows_between( p , dz , lower_left_z , upper_right_z , cols );
00382 g_3 = eh_ndgrid_malloc( 3 , sizeof(double) , n_x_cols , n_y_cols , n_rows );
00383 g = eh_ndgrid_to_grid( g_3 );
00384
00385 eh_dbl_array_grid( eh_ndgrid_x(g_3,0) , eh_ndgrid_n(g_3,0) , lower_left_x , dx );
00386 eh_dbl_array_grid( eh_ndgrid_x(g_3,1) , eh_ndgrid_n(g_3,1) , lower_left_y , dy );
00387 eh_dbl_array_grid( eh_ndgrid_x(g_3,2) , eh_ndgrid_n(g_3,2) , lower_left_z , dz );
00388
00389 col_temp = sed_column_dup( sed_cube_col(p,cols[0]) );
00390
00391 top = lower_left_z + n_rows*dz;
00392 bottom = lower_left_z;
00393 for ( i=0,id=cols[0],n=0 ; cols[n]>=0 ; i++,id=cols[++n] )
00394 {
00395 sed_column_copy( col_temp , sed_cube_col(p,id) );
00396
00397 sed_column_set_z_res( col_temp , dz );
00398 sed_column_rebin( col_temp );
00399 sed_column_strip( col_temp , bottom , top );
00400
00401 water_rows = eh_round( ( lower_left_z
00402 + n_rows*dz
00403 - sed_column_top_height( col_temp ) )
00404 / dz ,
00405 1. );
00406
00407 if ( water_rows<0 )
00408 water_rows = 0;
00409 sediment_rows = sed_column_len( col_temp );
00410 rock_rows = n_rows - sediment_rows - water_rows;
00411 top_sed = sediment_rows-1;
00412 bot_sed = 0;
00413
00414 if ( rock_rows<0 )
00415 {
00416 rock_rows = 0;
00417 sediment_rows = n_rows - water_rows;
00418 bot_sed = top_sed - sediment_rows+1;
00419 if ( sediment_rows<=0 )
00420 {
00421 sediment_rows = 0;
00422 water_rows = n_rows;
00423 top_sed = -1; bot_sed = 0;
00424 }
00425 }
00426
00427 if ( with_load )
00428 load = sed_column_load( col_temp , bot_sed , sediment_rows , NULL );
00429
00430 if ( excess_pressure )
00431 {
00432 hydro_static = sed_column_water_pressure( col_temp );
00433 for ( j=top_sed ; j>=bot_sed ; j-- )
00434 load[j-bot_sed] = hydro_static;
00435 }
00436
00437 for (j=0,k=0 ;j<water_rows;j++,k++)
00438 eh_dbl_grid_set_val( g , i , k , -G_MAXDOUBLE );
00439
00440 for ( j=top_sed ; j>=bot_sed ; j--,k++)
00441 eh_dbl_grid_set_val( g , i , k , sed_property_measure( property ,
00442 sed_column_nth_cell( col_temp , j ) ,
00443 (with_load)?(load[j-bot_sed]):(-1) ) );
00444
00445 for (j=0;j<rock_rows;j++,k++)
00446 eh_dbl_grid_set_val( g , i , k , G_MAXDOUBLE );
00447
00448 if ( with_load )
00449 eh_free( load );
00450 }
00451
00452 eh_free( cols );
00453 sed_column_destroy( col_temp );
00454 eh_grid_destroy( g , FALSE );
00455
00456 return g_3;
00457 }
00458
00459 double sed_cube_min_height( Sed_cube p , gssize **col_id )
00460 {
00461 double z = G_MAXDOUBLE;
00462
00463 eh_require( p )
00464 {
00465 gssize id, len = sed_cube_size(p);
00466
00467 for ( id=0 ; id<len ; id++ )
00468 z = eh_min( z , sed_cube_base_height(p,0,id) );
00469
00470 if ( col_id )
00471 {
00472 gssize n;
00473
00474 *col_id = NULL;
00475 for ( id=0,n=0 ; id<len ; id++ )
00476 if ( eh_compare_dbl( sed_cube_base_height(p,0,id) , z , 1e-12 ) )
00477 {
00478 *col_id = g_renew( gssize , *col_id , ++n );
00479 (*col_id)[n-1] = id;
00480 }
00481 *col_id = g_renew( gssize , *col_id , ++n );
00482 (*col_id)[n-1] = -1;
00483 }
00484 }
00485
00486 return z;
00487 }
00488
00489 double sed_cube_max_height( Sed_cube p , gssize **col_id )
00490 {
00491 double z = -G_MAXDOUBLE;
00492
00493 if ( p )
00494 {
00495 gssize id, len = sed_cube_size(p);
00496
00497 for ( id=0 ; id<len ; id++ )
00498 z = eh_max( z , sed_cube_top_height(p,0,id) );
00499
00500 if ( col_id )
00501 {
00502 gssize n;
00503
00504 *col_id = NULL;
00505 for ( id=0,n=0 ; id<len ; id++ )
00506 if ( eh_compare_dbl( sed_cube_top_height(p,0,id) , z , 1e-12 ) )
00507 {
00508 *col_id = g_renew( gssize , *col_id , ++n );
00509 (*col_id)[n-1] = id;
00510 }
00511 *col_id = g_renew( gssize , *col_id , ++n );
00512 (*col_id)[n-1] = -1;
00513 }
00514 }
00515
00516 return z;
00517 }
00518
00528 gssize *sed_cube_x_cols_between( Sed_cube p , double dx , double left , double right )
00529 {
00530 gssize *id=NULL;
00531
00532 eh_return_val_if_fail( dx>=0 , NULL );
00533
00534 eh_require( p )
00535 {
00536 gssize n=0;
00537 double x, y_0=sed_cube_col_y(p,0);
00538 Eh_ind_2 sub;
00539
00540 eh_lower_bound( left , sed_cube_col_x(p,0 ) );
00541 eh_upper_bound( right , sed_cube_col_x(p,sed_cube_size(p)-1) );
00542
00543 for ( x=left ; x<=right ; x+=dx )
00544 {
00545 id = g_renew( gssize , id , ++n );
00546 id[n-1] = sed_cube_column_id( p , x , y_0 );
00547 sub = sed_cube_sub( p , id[n-1] );
00548 id[n-1] = sub.i;
00549 }
00550 id = g_renew( gssize , id , ++n );
00551 id[n-1] = -1;
00552 }
00553
00554 return id;
00555 }
00556
00566 gssize *sed_cube_y_cols_between( Sed_cube p , double dy , double bottom , double top )
00567 {
00568 gssize *id=NULL;
00569
00570 eh_return_val_if_fail( dy>=0 , NULL );
00571
00572 eh_require( p )
00573 {
00574 gssize n=0;
00575 double x_0=sed_cube_col_x(p,0), y;
00576 Eh_ind_2 sub;
00577
00578 eh_lower_bound( bottom , sed_cube_col_y( p,0 ) );
00579 eh_upper_bound( top , sed_cube_col_y( p,sed_cube_size(p)-1) );
00580
00581 for ( y=bottom ; y<=top ; y+=dy )
00582 {
00583 id = g_renew( gssize , id , ++n );
00584 id[n-1] = sed_cube_column_id( p , x_0 , y );
00585 sub = sed_cube_sub( p , id[n-1] );
00586 id[n-1] = sub.j;
00587 }
00588 id = g_renew( gssize , id , ++n );
00589 id[n-1] = -1;
00590 }
00591
00592 return id;
00593 }
00594
00595 gssize
00596 sed_cube_n_rows_between( Sed_cube p , double dz , double lower , double upper , gssize *col_id )
00597 {
00598 gssize n_rows = 0;
00599
00600 eh_require( p )
00601 {
00602 gssize id, n;
00603 gssize row_0, row_1;
00604 gssize bottom_row = G_MAXINT32;
00605 gssize top_row = G_MININT32;
00606 double rows_per_cell = sed_cube_z_res(p)/dz;
00607
00608 for ( id=col_id[0],n=0 ; col_id[n]>=0 ; id=col_id[++n] )
00609 {
00610 row_0 = (long)(sed_cube_base_height(p,0,id)/dz);
00611 row_1 = row_0 + sed_column_len( sed_cube_col(p,id) )
00612 * ( rows_per_cell ) + 1;
00613 eh_set_min( bottom_row , row_0 );
00614 eh_set_max( top_row , row_1 );
00615 }
00616
00617 eh_lower_bound( bottom_row , lower/dz );
00618 eh_upper_bound( top_row , upper/dz );
00619
00620 n_rows = top_row-bottom_row;
00621 }
00622
00623 return n_rows;
00624 }
00625