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