#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <time.h>#include <unistd.h>#include "nco_getopt.h"#include <netcdf.h>#include "libnco.h"Include dependency graph for ncbo.c:

Go to the source code of this file.
Defines | |
| #define | MAIN_PROGRAM_FILE |
Functions | |
| int | main (int argc, char **argv) |
|
|
|
|
||||||||||||
|
Definition at line 83 of file ncbo.c. References dmn_sct_tag::cnt, copyright_prn(), var_sct_tag::dim, EXIT_FAILURE, EXIT_SUCCESS, False, FILE, getopt_long, var_sct_tag::has_mss_val, int_CEWI, lst_prs_2D(), var_sct_tag::mss_val, option::name, var_sct_tag::nbr_dim, NC_FORMAT_64BIT, NC_FORMAT_CLASSIC, NC_FORMAT_NETCDF4, NC_GLOBAL, NC_MAX_DIMS, NC_NOERR, NC_NOFILL, NC_NOWRITE, ncap_var_cnf_dmn(), nco_att_cpy(), nco_bool, nco_close(), nco_cmd_ln_sng(), nco_cnv_ccm_ccsm_cf_inq(), nco_create_mode_prs(), nco_dmn_dfn(), nco_dmn_dpl(), nco_dmn_fll(), nco_dmn_lmt_mrg(), nco_dmn_lst_ass_var(), nco_dmn_lst_free(), nco_dmn_xrf(), nco_enddef(), nco_err_exit(), nco_exit(), nco_exit_gracefully(), nco_fl_cmp_err_chk(), nco_fl_lst_mk(), nco_fl_mk_lcl(), nco_fl_nm_prs(), nco_fl_out_cls(), nco_fl_out_open(), nco_fl_rm(), nco_free(), nco_hst_att_cat(), nco_inq(), nco_lbr_vrs_prn(), nco_lmt_evl(), nco_lmt_lst_free(), nco_lmt_prs(), nco_lst_comma2hash(), nco_lst_srt_nm_id(), nco_malloc(), nco_mss_val_cnf(), nco_nm_id_lst_free(), nco_op_add, nco_op_dvd, nco_op_mlt, nco_op_nil, nco_op_sbt, nco_op_typ_get(), nco_open(), nco_openmp_ini(), nco_pck_map_nil, nco_pck_plc_nil, nco_put_var1(), nco_put_vara(), nco_set_fill(), nco_sng_lst_free(), nco_thr_att_cat(), nco_typ_sng(), nco_usg_prn(), nco_var_add(), nco_var_cnf_typ(), nco_var_dfn(), nco_var_dpl(), nco_var_dvd(), nco_var_fll(), nco_var_get(), nco_var_lst_add_crd(), nco_var_lst_ass_crd_add(), nco_var_lst_dvd(), nco_var_lst_free(), nco_var_lst_mk(), nco_var_lst_mrg(), nco_var_lst_xcl(), nco_var_mlt(), nco_var_mtd_refresh(), nco_var_sbt(), nco_var_srt_zero(), nco_var_val_cpy(), nco_xrf_dmn(), nco_xrf_var(), no_argument, NULL_CEWI, omp_get_thread_num(), optarg, optind, prg_nm_get(), prg_prs(), required_argument, True, type, var_sct_tag::type, var_sct_tag::val, option::val, and ptr_unn::vp. 00084 { 00085 nco_bool EXCLUDE_INPUT_LIST=False; /* Option c */ 00086 nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */ 00087 nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */ 00088 nco_bool FILE_1_RETRIEVED_FROM_REMOTE_LOCATION; 00089 nco_bool FILE_2_RETRIEVED_FROM_REMOTE_LOCATION; 00090 nco_bool FL_LST_IN_FROM_STDIN=False; /* [flg] fl_lst_in comes from stdin */ 00091 nco_bool FORCE_APPEND=False; /* Option A */ 00092 nco_bool FORCE_OVERWRITE=False; /* Option O */ 00093 nco_bool FORTRAN_IDX_CNV=False; /* Option F */ 00094 nco_bool HISTORY_APPEND=True; /* Option h */ 00095 nco_bool CNV_CCM_CCSM_CF; 00096 nco_bool REMOVE_REMOTE_FILES_AFTER_PROCESSING=True; /* Option R */ 00097 00098 char **fl_lst_abb=NULL; /* Option a */ 00099 char **fl_lst_in; 00100 char **var_lst_in=NULL_CEWI; 00101 char *cmd_ln; 00102 char *fl_in_1=NULL; /* fl_in_1 is nco_realloc'd when not NULL */; 00103 char *fl_in_2=NULL; /* fl_in_2 is nco_realloc'd when not NULL */; 00104 char *fl_out=NULL; /* Option o */ 00105 char *fl_out_tmp; 00106 char *fl_pth=NULL; /* Option p */ 00107 char *fl_pth_lcl=NULL; /* Option l */ 00108 char *lmt_arg[NC_MAX_DIMS]; 00109 char *nco_op_typ_sng=NULL; /* [sng] Operation type */ 00110 char *opt_crr=NULL; /* [sng] String representation of current long-option name */ 00111 char *optarg_lcl=NULL; /* [sng] Local copy of system optarg */ 00112 char *time_bfr_srt; 00113 00114 const char * const CVS_Id="$Id: ncbo.c,v 1.79 2006/02/26 07:41:55 zender Exp $"; 00115 const char * const CVS_Revision="$Revision: 1.79 $"; 00116 const char * const opt_sht_lst="4ACcD:d:Fhl:Oo:p:rRt:v:xy:-:"; 00117 00118 dmn_sct **dim_1; 00119 dmn_sct **dim_2; 00120 dmn_sct **dmn_out; 00121 00122 extern char *optarg; 00123 extern int optind; 00124 00125 /* Using naked stdin/stdout/stderr in parallel region generates warning 00126 Copy appropriate filehandle to variable scoped shared in parallel clause */ 00127 FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */ 00128 FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */ 00129 00130 int *in_id_1_arr; 00131 int *in_id_2_arr; 00132 00133 int abb_arg_nbr=0; 00134 int fl_idx; 00135 int fl_nbr=0; 00136 int fl_out_fmt=NC_FORMAT_CLASSIC; /* [enm] Output file format */ 00137 int fll_md_old; /* [enm] Old fill mode */ 00138 int idx; 00139 int in_id_1; 00140 int in_id_2; 00141 int lmt_nbr=0; /* Option d. NB: lmt_nbr gets incremented */ 00142 int nbr_dmn_fl_1; 00143 int nbr_dmn_fl_2; 00144 int nbr_dmn_xtr_1; 00145 int nbr_dmn_xtr_2; 00146 int nbr_var_fix_1; /* nbr_var_fix_1 gets incremented */ 00147 int nbr_var_fix_2; /* nbr_var_fix_2 gets incremented */ 00148 int nbr_var_fl_1; 00149 int nbr_var_fl_2; 00150 int nbr_var_prc_1; /* nbr_var_prc_1 gets incremented */ 00151 int nbr_var_prc_2; /* nbr_var_prc_2 gets incremented */ 00152 int nbr_xtr_1=0; /* nbr_xtr_1 won't otherwise be set for -c with no -v */ 00153 int nbr_xtr_2=0; /* nbr_xtr_2 won't otherwise be set for -c with no -v */ 00154 int nco_op_typ=nco_op_nil; /* [enm] Operation type */ 00155 int opt; 00156 int out_id; 00157 int rcd=NC_NOERR; /* [rcd] Return code */ 00158 int thr_idx; /* [idx] Index of current thread */ 00159 int thr_nbr=int_CEWI; /* [nbr] Thread number Option t */ 00160 int var_lst_in_nbr=0; 00161 00162 lmt_sct **lmt; 00163 00164 nm_id_sct *dmn_lst_1; 00165 nm_id_sct *dmn_lst_2; 00166 nm_id_sct *xtr_lst_1=NULL; /* xtr_lst_1 may be alloc()'d from NULL with -c option */ 00167 nm_id_sct *xtr_lst_2=NULL; /* xtr_lst_2 may be alloc()'d from NULL with -c option */ 00168 00169 time_t time_crr_time_t; 00170 00171 var_sct **var_1; 00172 var_sct **var_2; 00173 var_sct **var_fix_1; 00174 var_sct **var_fix_2; 00175 var_sct **var_fix_out; 00176 var_sct **var_out; 00177 var_sct **var_prc_1; 00178 var_sct **var_prc_2; 00179 var_sct **var_prc_out; 00180 00181 static struct option opt_lng[]= 00182 { /* Structure ordered by short option key if possible */ 00183 /* Long options with no argument, no short option counterpart */ 00184 /* Long options with argument, no short option counterpart */ 00185 {"fl_fmt",required_argument,0,0}, 00186 {"file_format",required_argument,0,0}, 00187 /* Long options with short counterparts */ 00188 {"4",no_argument,0,'4'}, 00189 {"64bit",no_argument,0,'4'}, 00190 {"netcdf4",no_argument,0,'4'}, 00191 {"append",no_argument,0,'A'}, 00192 {"coords",no_argument,0,'c'}, 00193 {"crd",no_argument,0,'c'}, 00194 {"no-coords",no_argument,0,'C'}, 00195 {"no-crd",no_argument,0,'C'}, 00196 {"debug",required_argument,0,'D'}, 00197 {"dbg_lvl",required_argument,0,'D'}, 00198 {"dimension",required_argument,0,'d'}, 00199 {"dmn",required_argument,0,'d'}, 00200 {"fortran",no_argument,0,'F'}, 00201 {"ftn",no_argument,0,'F'}, 00202 {"history",no_argument,0,'h'}, 00203 {"hst",no_argument,0,'h'}, 00204 {"local",required_argument,0,'l'}, 00205 {"lcl",required_argument,0,'l'}, 00206 {"overwrite",no_argument,0,'O'}, 00207 {"ovr",no_argument,0,'O'}, 00208 {"path",required_argument,0,'p'}, 00209 {"retain",no_argument,0,'R'}, 00210 {"rtn",no_argument,0,'R'}, 00211 {"revision",no_argument,0,'r'}, 00212 {"variable",required_argument,0,'v'}, 00213 {"version",no_argument,0,'r'}, 00214 {"vrs",no_argument,0,'r'}, 00215 {"thr_nbr",required_argument,0,'t'}, 00216 {"exclude",no_argument,0,'x'}, 00217 {"xcl",no_argument,0,'x'}, 00218 {"operation",required_argument,0,'y'}, 00219 {"op_typ",required_argument,0,'y'}, 00220 {"help",no_argument,0,'?'}, 00221 {0,0,0,0} 00222 }; /* end opt_lng */ 00223 int opt_idx=0; /* Index of current long option into opt_lng array */ 00224 00225 /* Start clock and save command line */ 00226 cmd_ln=nco_cmd_ln_sng(argc,argv); 00227 time_crr_time_t=time((time_t *)NULL); 00228 time_bfr_srt=ctime(&time_crr_time_t); time_bfr_srt=time_bfr_srt; /* Avoid compiler warning until variable is used for something */ 00229 00230 /* Get program name and set program enum (e.g., prg=ncra) */ 00231 prg_nm=prg_prs(argv[0],&prg); 00232 00233 /* Parse command line arguments */ 00234 while(1){ 00235 /* getopt_long_only() allows one dash to prefix long options */ 00236 opt=getopt_long(argc,argv,opt_sht_lst,opt_lng,&opt_idx); 00237 /* NB: access to opt_crr is only valid when long_opt is detected */ 00238 if(opt == EOF) break; /* Parse positional arguments once getopt_long() returns EOF */ 00239 opt_crr=(char *)strdup(opt_lng[opt_idx].name); 00240 00241 /* Process long options without short option counterparts */ 00242 if(opt == 0){ 00243 if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt); 00244 } /* opt != 0 */ 00245 /* Process short options */ 00246 switch(opt){ 00247 case 0: /* Long options have already been processed, return */ 00248 break; 00249 case '4': /* [flg] Catch-all to prescribe output storage format */ 00250 if(!strcmp(opt_crr,"64bit")) fl_out_fmt=NC_FORMAT_64BIT; else fl_out_fmt=NC_FORMAT_NETCDF4; 00251 break; 00252 case 'A': /* Toggle FORCE_APPEND */ 00253 FORCE_APPEND=!FORCE_APPEND; 00254 break; 00255 case 'C': /* Extract all coordinates associated with extracted variables? */ 00256 EXTRACT_ASSOCIATED_COORDINATES=False; 00257 break; 00258 case 'c': 00259 EXTRACT_ALL_COORDINATES=True; 00260 break; 00261 case 'D': /* The debugging level. Default is 0. */ 00262 dbg_lvl=(unsigned short)strtol(optarg,(char **)NULL,10); 00263 break; 00264 case 'd': /* Copy argument for later processing */ 00265 lmt_arg[lmt_nbr]=(char *)strdup(optarg); 00266 lmt_nbr++; 00267 break; 00268 case 'F': /* Toggle index convention. Default is 0-based arrays (C-style). */ 00269 FORTRAN_IDX_CNV=!FORTRAN_IDX_CNV; 00270 break; 00271 case 'h': /* Toggle appending to history global attribute */ 00272 HISTORY_APPEND=!HISTORY_APPEND; 00273 break; 00274 case 'l': /* Local path prefix for files retrieved from remote file system */ 00275 fl_pth_lcl=(char *)strdup(optarg); 00276 break; 00277 case 'O': /* Toggle FORCE_OVERWRITE */ 00278 FORCE_OVERWRITE=!FORCE_OVERWRITE; 00279 break; 00280 case 'o': /* Name of output file */ 00281 fl_out=(char *)strdup(optarg); 00282 break; 00283 case 'p': /* Common file path */ 00284 fl_pth=(char *)strdup(optarg); 00285 break; 00286 case 'R': /* Toggle removal of remotely-retrieved-files. Default is True. */ 00287 REMOVE_REMOTE_FILES_AFTER_PROCESSING=!REMOVE_REMOTE_FILES_AFTER_PROCESSING; 00288 break; 00289 case 'r': /* Print CVS program information and copyright notice */ 00290 (void)copyright_prn(CVS_Id,CVS_Revision); 00291 (void)nco_lbr_vrs_prn(); 00292 nco_exit(EXIT_SUCCESS); 00293 break; 00294 case 't': /* Thread number */ 00295 thr_nbr=(int)strtol(optarg,(char **)NULL,10); 00296 break; 00297 case 'v': /* Variables to extract/exclude */ 00298 /* Replace commas with hashes when within braces (convert back later) */ 00299 optarg_lcl=(char *)strdup(optarg); 00300 (void)nco_lst_comma2hash(optarg_lcl); 00301 var_lst_in=lst_prs_2D(optarg_lcl,",",&var_lst_in_nbr); 00302 optarg_lcl=(char *)nco_free(optarg_lcl); 00303 nbr_xtr_1=nbr_xtr_2=var_lst_in_nbr; 00304 break; 00305 case 'x': /* Exclude rather than extract variables specified with -v */ 00306 EXCLUDE_INPUT_LIST=True; 00307 break; 00308 case 'y': /* User-specified operation type overrides invocation default */ 00309 nco_op_typ_sng=(char *)strdup(optarg); 00310 nco_op_typ=nco_op_typ_get(nco_op_typ_sng); 00311 break; 00312 case '?': /* Print proper usage */ 00313 (void)nco_usg_prn(); 00314 nco_exit(EXIT_SUCCESS); 00315 break; 00316 case '-': /* Long options are not allowed */ 00317 (void)fprintf(stderr,"%s: ERROR Long options are not available in this build. Use single letter options instead.\n",prg_nm_get()); 00318 nco_exit(EXIT_FAILURE); 00319 break; 00320 default: /* Print proper usage */ 00321 (void)nco_usg_prn(); 00322 nco_exit(EXIT_FAILURE); 00323 break; 00324 } /* end switch */ 00325 if(opt_crr != NULL) opt_crr=(char *)nco_free(opt_crr); 00326 } /* end while loop */ 00327 00328 /* Process positional arguments and fill in filenames */ 00329 fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN); 00330 00331 /* Make uniform list of user-specified dimension limits */ 00332 lmt=nco_lmt_prs(lmt_nbr,lmt_arg); 00333 00334 /* Initialize thread information */ 00335 thr_nbr=nco_openmp_ini(thr_nbr); 00336 in_id_1_arr=(int *)nco_malloc(thr_nbr*sizeof(int)); 00337 in_id_2_arr=(int *)nco_malloc(thr_nbr*sizeof(int)); 00338 00339 /* Parse filenames */ 00340 fl_idx=0; /* Input file _1 */ 00341 fl_in_1=nco_fl_nm_prs(fl_in_1,fl_idx,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth); 00342 if(dbg_lvl > 0) (void)fprintf(stderr,"\nInput file %d is %s; ",fl_idx,fl_in_1); 00343 /* Make sure file is on local system and is readable or die trying */ 00344 fl_in_1=nco_fl_mk_lcl(fl_in_1,fl_pth_lcl,&FILE_1_RETRIEVED_FROM_REMOTE_LOCATION); 00345 if(dbg_lvl > 0) (void)fprintf(stderr,"local file %s:\n",fl_in_1); 00346 /* Open file once per thread to improve caching */ 00347 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in_1,NC_NOWRITE,in_id_1_arr+thr_idx); 00348 in_id_1=in_id_1_arr[0]; 00349 00350 fl_idx=1; /* Input file _2 */ 00351 fl_in_2=nco_fl_nm_prs(fl_in_2,fl_idx,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth); 00352 if(dbg_lvl > 0) (void)fprintf(stderr,"\nInput file %d is %s; ",fl_idx,fl_in_2); 00353 /* Make sure file is on local system and is readable or die trying */ 00354 fl_in_2=nco_fl_mk_lcl(fl_in_2,fl_pth_lcl,&FILE_2_RETRIEVED_FROM_REMOTE_LOCATION); 00355 if(dbg_lvl > 0) (void)fprintf(stderr,"local file %s:\n",fl_in_2); 00356 /* Open file once per thread to improve caching */ 00357 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in_2,NC_NOWRITE,in_id_2_arr+thr_idx); 00358 in_id_2=in_id_2_arr[0]; 00359 00360 /* Get number of variables and dimensions in file */ 00361 (void)nco_inq(in_id_1,&nbr_dmn_fl_1,&nbr_var_fl_1,(int *)NULL,(int *)NULL); 00362 (void)nco_inq(in_id_2,&nbr_dmn_fl_2,&nbr_var_fl_2,(int *)NULL,(int *)NULL); 00363 00364 /* Form initial extraction list which may include extended regular expressions */ 00365 xtr_lst_1=nco_var_lst_mk(in_id_1,nbr_var_fl_1,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr_1); 00366 xtr_lst_2=nco_var_lst_mk(in_id_2,nbr_var_fl_2,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr_2); 00367 00368 /* Change included variables to excluded variables */ 00369 if(EXCLUDE_INPUT_LIST) xtr_lst_1=nco_var_lst_xcl(in_id_1,nbr_var_fl_1,xtr_lst_1,&nbr_xtr_1); 00370 if(EXCLUDE_INPUT_LIST) xtr_lst_2=nco_var_lst_xcl(in_id_2,nbr_var_fl_2,xtr_lst_2,&nbr_xtr_2); 00371 00372 /* Add all coordinate variables to extraction list */ 00373 if(EXTRACT_ALL_COORDINATES) xtr_lst_1=nco_var_lst_add_crd(in_id_1,nbr_dmn_fl_1,xtr_lst_1,&nbr_xtr_1); 00374 if(EXTRACT_ALL_COORDINATES) xtr_lst_2=nco_var_lst_add_crd(in_id_2,nbr_dmn_fl_2,xtr_lst_2,&nbr_xtr_2); 00375 00376 /* Make sure coordinates associated extracted variables are also on extraction list */ 00377 if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst_1=nco_var_lst_ass_crd_add(in_id_1,xtr_lst_1,&nbr_xtr_1); 00378 if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst_2=nco_var_lst_ass_crd_add(in_id_2,xtr_lst_2,&nbr_xtr_2); 00379 00380 /* With fully symmetric 1<->2 ordering, may occasionally find nbr_xtr_2 > nbr_xtr_1 00381 This occurs, e.g., when fl_in_1 contains reduced variables and full coordinates 00382 are only in fl_in_2 and so will not appear xtr_lst_1 */ 00383 00384 /* Sort extraction list by variable ID for fastest I/O */ 00385 if(nbr_xtr_1 > 1) xtr_lst_1=nco_lst_srt_nm_id(xtr_lst_1,nbr_xtr_1,False); 00386 if(nbr_xtr_2 > 1) xtr_lst_2=nco_lst_srt_nm_id(xtr_lst_2,nbr_xtr_2,False); 00387 00388 /* We now have final list of variables to extract. Phew. */ 00389 00390 /* Find coordinate/dimension values associated with user-specified limits 00391 NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */ 00392 for(idx=0;idx<lmt_nbr;idx++) (void)nco_lmt_evl(in_id_1,lmt[idx],0L,FORTRAN_IDX_CNV); 00393 00394 /* Find dimensions associated with variables to be extracted */ 00395 dmn_lst_1=nco_dmn_lst_ass_var(in_id_1,xtr_lst_1,nbr_xtr_1,&nbr_dmn_xtr_1); 00396 dmn_lst_2=nco_dmn_lst_ass_var(in_id_2,xtr_lst_2,nbr_xtr_2,&nbr_dmn_xtr_2); 00397 00398 /* Fill in dimension structure for all extracted dimensions */ 00399 dim_1=(dmn_sct **)nco_malloc(nbr_dmn_xtr_1*sizeof(dmn_sct *)); 00400 dim_2=(dmn_sct **)nco_malloc(nbr_dmn_xtr_2*sizeof(dmn_sct *)); 00401 for(idx=0;idx<nbr_dmn_xtr_1;idx++) dim_1[idx]=nco_dmn_fll(in_id_1,dmn_lst_1[idx].id,dmn_lst_1[idx].nm); 00402 for(idx=0;idx<nbr_dmn_xtr_2;idx++) dim_2[idx]=nco_dmn_fll(in_id_2,dmn_lst_2[idx].id,dmn_lst_2[idx].nm); 00403 /* Dimension lists no longer needed */ 00404 dmn_lst_1=nco_nm_id_lst_free(dmn_lst_1,nbr_dmn_xtr_1); 00405 dmn_lst_2=nco_nm_id_lst_free(dmn_lst_2,nbr_dmn_xtr_2); 00406 00407 /* Merge hyperslab limit information into dimension structures */ 00408 if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim_1,nbr_dmn_xtr_1,lmt,lmt_nbr); 00409 if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim_2,nbr_dmn_xtr_2,lmt,lmt_nbr); 00410 00411 /* Duplicate input dimension structures for output dimension structures */ 00412 dmn_out=(dmn_sct **)nco_malloc(nbr_dmn_xtr_1*sizeof(dmn_sct *)); 00413 for(idx=0;idx<nbr_dmn_xtr_1;idx++){ 00414 dmn_out[idx]=nco_dmn_dpl(dim_1[idx]); 00415 (void)nco_dmn_xrf(dim_1[idx],dmn_out[idx]); 00416 } /* end loop over idx */ 00417 00418 if(dbg_lvl > 3){ 00419 for(idx=0;idx<nbr_xtr_1;idx++) (void)fprintf(stderr,"xtr_lst_1[%d].nm = %s, .id= %d\n",idx,xtr_lst_1[idx].nm,xtr_lst_1[idx].id); 00420 } /* end if */ 00421 00422 /* Is this an CCM/CCSM/CF-format history tape? */ 00423 CNV_CCM_CCSM_CF=nco_cnv_ccm_ccsm_cf_inq(in_id_1); 00424 00425 /* Fill in variable structure list for all extracted variables */ 00426 var_1=(var_sct **)nco_malloc(nbr_xtr_1*sizeof(var_sct *)); 00427 var_2=(var_sct **)nco_malloc(nbr_xtr_2*sizeof(var_sct *)); 00428 var_out=(var_sct **)nco_malloc(nbr_xtr_1*sizeof(var_sct *)); 00429 for(idx=0;idx<nbr_xtr_1;idx++){ 00430 var_1[idx]=nco_var_fll(in_id_1,xtr_lst_1[idx].id,xtr_lst_1[idx].nm,dim_1,nbr_dmn_xtr_1); 00431 var_out[idx]=nco_var_dpl(var_1[idx]); 00432 (void)nco_xrf_var(var_1[idx],var_out[idx]); 00433 (void)nco_xrf_dmn(var_out[idx]); 00434 } /* end loop over idx */ 00435 for(idx=0;idx<nbr_xtr_2;idx++){ 00436 var_2[idx]=nco_var_fll(in_id_2,xtr_lst_2[idx].id,xtr_lst_2[idx].nm,dim_2,nbr_dmn_xtr_2); 00437 } /* end loop over idx */ 00438 00439 /* Extraction lists no longer needed */ 00440 xtr_lst_1=nco_nm_id_lst_free(xtr_lst_1,nbr_xtr_1); 00441 xtr_lst_2=nco_nm_id_lst_free(xtr_lst_2,nbr_xtr_2); 00442 00443 /* Divide variable lists into lists of fixed variables and variables to be processed 00444 Create lists from file_1 last so those values remain in *_out arrays */ 00445 (void)nco_var_lst_dvd(var_2,var_out,nbr_xtr_2,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,(dmn_sct **)NULL,0,&var_fix_2,&var_fix_out,&nbr_var_fix_2,&var_prc_2,&var_prc_out,&nbr_var_prc_2); 00446 /* Avoid double-free() condition */ 00447 var_fix_out=(var_sct **)nco_free(var_fix_out); 00448 var_prc_out=(var_sct **)nco_free(var_prc_out); 00449 (void)nco_var_lst_dvd(var_1,var_out,nbr_xtr_1,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,(dmn_sct **)NULL,0,&var_fix_1,&var_fix_out,&nbr_var_fix_1,&var_prc_1,&var_prc_out,&nbr_var_prc_1); 00450 00451 /* Die gracefully on unsupported features... */ 00452 if(nbr_var_fix_1 < nbr_var_fix_2){ 00453 (void)fprintf(fp_stdout,"%s: ERROR First file has fewer fixed variables than second file (%d < %d). This feature is NCO TODO 581.\n",prg_nm,nbr_var_fix_1,nbr_var_fix_2); 00454 nco_exit(EXIT_FAILURE); 00455 } /* endif */ 00456 00457 /* Merge two variable lists into same order */ 00458 rcd=nco_var_lst_mrg(&var_prc_1,&var_prc_2,&nbr_var_prc_1,&nbr_var_prc_2); 00459 00460 /* Open output file */ 00461 fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&out_id); 00462 00463 /* Copy global attributes */ 00464 (void)nco_att_cpy(in_id_1,out_id,NC_GLOBAL,NC_GLOBAL,True); 00465 00466 /* Catenate time-stamped command line to "history" global attribute */ 00467 if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln); 00468 00469 if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr); 00470 00471 /* Define dimensions in output file */ 00472 (void)nco_dmn_dfn(fl_out,out_id,dmn_out,nbr_dmn_xtr_1); 00473 00474 /* fxm: TODO 550 put max_dim_sz/list(var_1,var_2) into var_def(var_out) */ 00475 /* Define variables in output file, copy their attributes */ 00476 (void)nco_var_dfn(in_id_1,fl_out,out_id,var_out,nbr_xtr_1,(dmn_sct **)NULL,(int)0,nco_pck_plc_nil,nco_pck_map_nil); 00477 00478 /* Turn off default filling behavior to enhance efficiency */ 00479 rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old); 00480 00481 /* Take output file out of define mode */ 00482 (void)nco_enddef(out_id); 00483 00484 /* Zero start vectors for all output variables */ 00485 (void)nco_var_srt_zero(var_out,nbr_xtr_1); 00486 00487 /* Copy variable data for non-processed variables */ 00488 (void)nco_var_val_cpy(in_id_1,out_id,var_fix_1,nbr_var_fix_1); 00489 00490 /* ncbo() code has been similar to ncea() (and ncra()) wherever possible 00491 Major differences occur where performance would otherwise suffer 00492 From now on, however, binary-file and binary-operation nature of ncbo() 00493 is too different from ncea() paradigm to justify following ncea() style. 00494 Instead, we adopt symmetric nomenclature (e.g., file_1, file_2), and 00495 perform differences variable-by-variable so peak memory usage goes as 00496 Order(2*maximum variable size) rather than Order(3*maximum record size) or 00497 Order(3*file size) */ 00498 00499 /* Perform various error-checks on input file */ 00500 if(False) (void)nco_fl_cmp_err_chk(); 00501 00502 /* Default operation depends on invocation name */ 00503 if(nco_op_typ_sng == NULL) nco_op_typ=nco_op_typ_get(nco_op_typ_sng); 00504 00505 /* Loop over variables */ 00506 #ifdef _OPENMP 00507 /* OpenMP notes: 00508 shared(): msk and wgt are not altered within loop 00509 private(): wgt_avg does not need initialization */ 00510 #pragma omp parallel for default(none) private(idx,in_id_1,in_id_2) shared(dbg_lvl,dim_1,fl_in_1,fl_in_2,fl_out,fp_stderr,in_id_1_arr,in_id_2_arr,nbr_dmn_xtr_1,nbr_var_prc_1,nbr_var_prc_2,nco_op_typ,out_id,prg_nm,var_prc_1,var_prc_2,var_prc_out) 00511 #endif /* !_OPENMP */ 00512 for(idx=0;idx<nbr_var_prc_1;idx++){ 00513 int has_mss_val=False; 00514 ptr_unn mss_val; 00515 00516 if(dbg_lvl > 0) (void)fprintf(fp_stderr,"%s, ",var_prc_1[idx]->nm); 00517 if(dbg_lvl > 0) (void)fflush(fp_stderr); 00518 00519 in_id_1=in_id_1_arr[omp_get_thread_num()]; 00520 in_id_2=in_id_2_arr[omp_get_thread_num()]; 00521 00522 (void)nco_var_mtd_refresh(in_id_1,var_prc_1[idx]); 00523 has_mss_val=var_prc_1[idx]->has_mss_val; 00524 (void)nco_var_get(in_id_1,var_prc_1[idx]); 00525 00526 /* Find and set variable dmn_nbr, ID, mss_val, type in second file */ 00527 (void)nco_var_mtd_refresh(in_id_2,var_prc_2[idx]); 00528 00529 /* Read hyperslab from second file */ 00530 (void)nco_var_get(in_id_2,var_prc_2[idx]); 00531 00532 /* Determine whether var1 and var2 conform */ 00533 if(var_prc_1[idx]->nbr_dim == var_prc_2[idx]->nbr_dim){ 00534 int dmn_idx; 00535 /* Do all dimensions match in sequence? */ 00536 for(dmn_idx=0;dmn_idx<var_prc_1[idx]->nbr_dim;dmn_idx++){ 00537 if( 00538 strcmp(var_prc_1[idx]->dim[dmn_idx]->nm,var_prc_2[idx]->dim[dmn_idx]->nm) || /* Dimension names do not match */ 00539 (var_prc_1[idx]->dim[dmn_idx]->cnt != var_prc_2[idx]->dim[dmn_idx]->cnt) || /* Dimension sizes do not match */ 00540 False){ 00541 (void)fprintf(fp_stdout,"%s: ERROR Variables do not conform:\nFile %s variable %s dimension %d is %s with size %li and count %li\nFile %s variable %s dimension %d is %s with size %li and count %li\n",prg_nm,fl_in_1,var_prc_1[idx]->nm,dmn_idx,var_prc_1[idx]->dim[dmn_idx]->nm,var_prc_1[idx]->dim[dmn_idx]->sz,var_prc_1[idx]->dim[dmn_idx]->cnt,fl_in_2,var_prc_2[idx]->nm,dmn_idx,var_prc_2[idx]->dim[dmn_idx]->nm,var_prc_2[idx]->dim[dmn_idx]->sz,var_prc_2[idx]->dim[dmn_idx]->cnt); 00542 if(var_prc_1[idx]->dim[dmn_idx]->cnt == 1 || var_prc_2[idx]->dim[dmn_idx]->cnt == 1) (void)fprintf(fp_stdout,"%s: HINT If a dimension is present in both files, it must be the same size. %s will not attempt to broadcast a degenerate (i.e., size 1) dimension (e.g., a single timestep) to a non-degenerate size. If one of the dimensions is degenerate, try removing it completely (e.g., by averaging over it with ncwa) before invoking %s\n",prg_nm,prg_nm,prg_nm); 00543 nco_exit(EXIT_FAILURE); 00544 } /* endif */ 00545 } /* end loop over dmn_idx */ 00546 }else{ /* var_prc_out[idx]->nbr_dim != var_prc_1[idx]->nbr_dim) */ 00547 /* Number of dimensions do not match, attempt to broadcast variables 00548 fxm: broadcasting here leads to memory leak later since var_[1,2] does not know */ 00549 00550 /* Die gracefully on unsupported features... */ 00551 if(var_prc_1[idx]->nbr_dim < var_prc_2[idx]->nbr_dim){ 00552 (void)fprintf(fp_stdout,"%s: ERROR Variable %s has lesser rank in first file than in second file (%d < %d). This feature is NCO TODO 552.\n",prg_nm,var_prc_1[idx]->nm,var_prc_1[idx]->nbr_dim,var_prc_2[idx]->nbr_dim); 00553 nco_exit(EXIT_FAILURE); 00554 } /* endif */ 00555 00556 (void)ncap_var_cnf_dmn(&var_prc_1[idx],&var_prc_2[idx]); 00557 } /* end else */ 00558 00559 /* var2 now conforms in size to var1, and is in memory */ 00560 00561 /* fxm: TODO 268 allow var1 or var2 to typecast */ 00562 /* Make sure var2 conforms to type of var1 */ 00563 if(var_prc_1[idx]->type != var_prc_2[idx]->type){ 00564 (void)fprintf(fp_stderr,"%s: WARNING Input variables do not conform in type:\nFile 1 = %s variable %s has type %s\nFile 2 = %s variable %s has type %s\nFile 3 = %s variable %s will have type %s\n",prg_nm,fl_in_1,var_prc_1[idx]->nm,nco_typ_sng(var_prc_1[idx]->type),fl_in_2,var_prc_2[idx]->nm,nco_typ_sng(var_prc_2[idx]->type),fl_out,var_prc_1[idx]->nm,nco_typ_sng(var_prc_1[idx]->type)); 00565 } /* endif different type */ 00566 var_prc_2[idx]=nco_var_cnf_typ(var_prc_1[idx]->type,var_prc_2[idx]); 00567 00568 /* Change missing_value of var_prc_2, if any, to missing_value of var_prc_1, if any */ 00569 has_mss_val=nco_mss_val_cnf(var_prc_1[idx],var_prc_2[idx]); 00570 00571 /* mss_val in fl_1, if any, overrides mss_val in fl_2 */ 00572 if(has_mss_val) mss_val=var_prc_1[idx]->mss_val; 00573 00574 /* Perform specified binary operation */ 00575 switch(nco_op_typ){ 00576 case nco_op_add: /* [enm] Add file_1 to file_2 */ 00577 (void)nco_var_add(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00578 case nco_op_mlt: /* [enm] Multiply file_1 by file_2 */ 00579 (void)nco_var_mlt(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00580 case nco_op_dvd: /* [enm] Divide file_1 by file_2 */ 00581 (void)nco_var_dvd(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00582 case nco_op_sbt: /* [enm] Subtract file_2 from file_1 */ 00583 (void)nco_var_sbt(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00584 default: /* Other defined nco_op_typ values are valid for ncra(), ncrcat(), ncwa(), not ncbo() */ 00585 (void)fprintf(fp_stdout,"%s: ERROR Illegal nco_op_typ in binary operation\n",prg_nm); 00586 nco_exit(EXIT_FAILURE); 00587 break; 00588 } /* end case */ 00589 00590 var_prc_2[idx]->val.vp=nco_free(var_prc_2[idx]->val.vp); 00591 00592 #ifdef _OPENMP 00593 #pragma omp critical 00594 #endif /* _OPENMP */ 00595 { /* begin OpenMP critical */ 00596 /* Copy result to output file and free workspace buffer */ 00597 if(var_prc_1[idx]->nbr_dim == 0){ 00598 (void)nco_put_var1(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_1[idx]->val.vp,var_prc_out[idx]->type); 00599 }else{ /* end if variable is scalar */ 00600 (void)nco_put_vara(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_1[idx]->val.vp,var_prc_out[idx]->type); 00601 } /* end else */ 00602 } /* end OpenMP critical */ 00603 var_prc_1[idx]->val.vp=nco_free(var_prc_1[idx]->val.vp); 00604 00605 } /* end (OpenMP parallel for) loop over idx */ 00606 if(dbg_lvl > 0) (void)fprintf(stderr,"\n"); 00607 00608 /* Close input netCDF files */ 00609 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_1_arr[thr_idx]); 00610 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_2_arr[thr_idx]); 00611 00612 /* Close output file and move it from temporary to permanent location */ 00613 (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id); 00614 00615 /* Remove local copy of file */ 00616 if(FILE_1_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in_1); 00617 if(FILE_2_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in_2); 00618 00619 /* ncbo-unique memory */ 00620 if(fl_in_1 != NULL) fl_in_1=(char *)nco_free(fl_in_1); 00621 if(fl_in_2 != NULL) fl_in_2=(char *)nco_free(fl_in_2); 00622 00623 /* NCO-generic clean-up */ 00624 /* Free individual strings/arrays */ 00625 if(cmd_ln != NULL) cmd_ln=(char *)nco_free(cmd_ln); 00626 if(fl_out != NULL) fl_out=(char *)nco_free(fl_out); 00627 if(fl_out_tmp != NULL) fl_out_tmp=(char *)nco_free(fl_out_tmp); 00628 if(fl_pth != NULL) fl_pth=(char *)nco_free(fl_pth); 00629 if(fl_pth_lcl != NULL) fl_pth_lcl=(char *)nco_free(fl_pth_lcl); 00630 if(in_id_1_arr != NULL) in_id_1_arr=(int *)nco_free(in_id_1_arr); 00631 if(in_id_2_arr != NULL) in_id_2_arr=(int *)nco_free(in_id_2_arr); 00632 /* Free lists of strings */ 00633 if(fl_lst_in != NULL && fl_lst_abb == NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,fl_nbr); 00634 if(fl_lst_in != NULL && fl_lst_abb != NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,1); 00635 if(fl_lst_abb != NULL) fl_lst_abb=nco_sng_lst_free(fl_lst_abb,abb_arg_nbr); 00636 if(var_lst_in_nbr > 0) var_lst_in=nco_sng_lst_free(var_lst_in,var_lst_in_nbr); 00637 /* Free limits */ 00638 for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]); 00639 if(lmt_nbr > 0) lmt=nco_lmt_lst_free(lmt,lmt_nbr); 00640 /* Free dimension lists */ 00641 if(nbr_dmn_xtr_1 > 0) dim_1=nco_dmn_lst_free(dim_1,nbr_dmn_xtr_1); 00642 if(nbr_dmn_xtr_2 > 0) dim_2=nco_dmn_lst_free(dim_2,nbr_dmn_xtr_2); 00643 if(nbr_dmn_xtr_1 > 0) dmn_out=nco_dmn_lst_free(dmn_out,nbr_dmn_xtr_1); 00644 /* Free variable lists 00645 Using nco_var_lst_free() to free main var_1 and var_2 lists would fail 00646 if ncap_var_prc_dmn() had to broadcast any variables because pointer 00647 var_1 and var_2 still contain dangling pointer to old variable. 00648 Hence, use nco_var_lst_free() to free prc and fix lists and 00649 use nco_free() to free main var_1 and var_2 lists. 00650 Dangling pointers in var_1 and var_2 are unsafe: fxm TODO 578 */ 00651 if(nbr_var_prc_1 > 0) var_prc_1=nco_var_lst_free(var_prc_1,nbr_var_prc_1); 00652 if(nbr_var_fix_1 > 0) var_fix_1=nco_var_lst_free(var_fix_1,nbr_var_fix_1); 00653 if(nbr_var_prc_2 > 0) var_prc_2=nco_var_lst_free(var_prc_2,nbr_var_prc_2); 00654 if(nbr_var_fix_2 > 0) var_fix_2=nco_var_lst_free(var_fix_2,nbr_var_fix_2); 00655 var_1=(var_sct **)nco_free(var_1); 00656 var_2=(var_sct **)nco_free(var_2); 00657 if(nbr_xtr_1 > 0) var_out=nco_var_lst_free(var_out,nbr_xtr_1); 00658 var_prc_out=(var_sct **)nco_free(var_prc_out); 00659 var_fix_out=(var_sct **)nco_free(var_fix_out); 00660 00661 if(rcd != NC_NOERR) nco_err_exit(rcd,"main"); 00662 nco_exit_gracefully(); 00663 return EXIT_SUCCESS; 00664 } /* end main() */
|
1.4.4