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

Go to the source code of this file.
Defines | |
| #define | MAIN_PROGRAM_FILE |
Functions | |
| int | main (int argc, char **argv) |
|
|
|
|
||||||||||||
|
Definition at line 68 of file ncpdq.c. References aed_sct::att_nm, dmn_sct_tag::cnt, var_sct_tag::cnt, copyright_prn(), var_sct_tag::dim, var_sct_tag::dmn_id, dmn_sct_tag::end, var_sct_tag::end, EXIT_FAILURE, EXIT_SUCCESS, False, FILE, getopt_long, var_sct_tag::has_dpl_dmn, dmn_sct_tag::id, int_CEWI, dmn_sct_tag::is_rec_dmn, var_sct_tag::is_rec_var, lst_prs_2D(), option::name, var_sct_tag::nbr_dim, NC_FORMAT_64BIT, NC_FORMAT_CLASSIC, NC_FORMAT_NETCDF4, NC_GLOBAL, var_sct_tag::nc_id, NC_MAX_DIMS, NC_NOERR, NC_NOFILL, NC_NOWRITE, nco_aed_prc(), 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_lst_mk(), nco_dmn_xrf(), nco_enddef(), nco_exit(), nco_exit_gracefully(), 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_malloc_flg(), nco_nm_id_lst_free(), nco_open(), nco_openmp_ini(), nco_pck_map_flt_sht, nco_pck_map_get(), nco_pck_map_sng_get(), nco_pck_mtd(), nco_pck_plc_all_new_att, nco_pck_plc_all_xst_att, nco_pck_plc_get(), nco_pck_plc_nil, nco_pck_plc_sng_get(), nco_pck_plc_typ_get(), nco_pck_plc_upk, nco_pck_plc_xst_new_att, nco_pck_val(), nco_put_var1(), nco_put_vara(), nco_realloc(), NCO_REC_DMN_UNDEFINED, nco_redef(), nco_set_fill(), nco_sng_lst_free(), nco_thr_att_cat(), nco_typ_lng(), nco_usg_prn(), nco_var_dfn(), nco_var_dmn_rdr_mtd(), nco_var_dmn_rdr_val(), nco_var_dpl(), 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_xcl(), nco_var_prc_crr_prn(), nco_var_srt_zero(), nco_var_val_cpy(), nco_xrf_dmn(), nco_xrf_var(), dmn_sct_tag::nm, no_argument, NULL_CEWI, omp_get_thread_num(), optarg, optind, var_sct_tag::pck_ram, prg_nm_get(), prg_prs(), required_argument, dmn_sct_tag::srd, var_sct_tag::srd, dmn_sct_tag::srt, var_sct_tag::srt, True, var_sct_tag::type, type, option::val, var_sct_tag::val, and ptr_unn::vp. 00069 { 00070 aed_sct *aed_lst_add_fst=NULL_CEWI; 00071 aed_sct *aed_lst_scl_fct=NULL_CEWI; 00072 00073 nco_bool **dmn_rvr_in=NULL; /* [flg] Reverse dimension */ 00074 nco_bool *dmn_rvr_rdr=NULL; /* [flg] Reverse dimension */ 00075 nco_bool EXCLUDE_INPUT_LIST=False; /* Option c */ 00076 nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */ 00077 nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */ 00078 nco_bool FILE_RETRIEVED_FROM_REMOTE_LOCATION; 00079 nco_bool FL_LST_IN_FROM_STDIN=False; /* [flg] fl_lst_in comes from stdin */ 00080 nco_bool FORCE_APPEND=False; /* Option A */ 00081 nco_bool FORCE_OVERWRITE=False; /* Option O */ 00082 nco_bool FORTRAN_IDX_CNV=False; /* Option F */ 00083 nco_bool HISTORY_APPEND=True; /* Option h */ 00084 nco_bool CNV_CCM_CCSM_CF; 00085 nco_bool REDEFINED_RECORD_DIMENSION=False; /* [flg] Re-defined record dimension */ 00086 nco_bool REMOVE_REMOTE_FILES_AFTER_PROCESSING=True; /* Option R */ 00087 00088 char **dmn_rdr_lst_in=NULL_CEWI; /* Option a */ 00089 char **fl_lst_abb=NULL; /* Option n */ 00090 char **fl_lst_in=NULL_CEWI; 00091 char **var_lst_in=NULL_CEWI; 00092 char *cmd_ln; 00093 char *fl_in=NULL; 00094 char *fl_out=NULL; /* Option o */ 00095 char *fl_out_tmp=NULL_CEWI; 00096 char *fl_pth=NULL; /* Option p */ 00097 char *fl_pth_lcl=NULL; /* Option l */ 00098 char *lmt_arg[NC_MAX_DIMS]; 00099 char *nco_pck_plc_sng=NULL_CEWI; /* [sng] Packing policy Option P */ 00100 char *nco_pck_map_sng=NULL_CEWI; /* [sng] Packing map Option M */ 00101 char *opt_crr=NULL; /* [sng] String representation of current long-option name */ 00102 char *optarg_lcl=NULL; /* [sng] Local copy of system optarg */ 00103 char *rec_dmn_nm_in=NULL; /* [sng] Record dimension name, original */ 00104 char *rec_dmn_nm_out=NULL; /* [sng] Record dimension name, re-ordered */ 00105 char *rec_dmn_nm_out_crr=NULL; /* [sng] Name of record dimension, if any, required by re-order */ 00106 char *time_bfr_srt; 00107 00108 char add_fst_sng[]="add_offset"; /* [sng] Unidata standard string for add offset */ 00109 char scl_fct_sng[]="scale_factor"; /* [sng] Unidata standard string for scale factor */ 00110 00111 const char * const CVS_Id="$Id: ncpdq.c,v 1.100 2006/02/20 20:59:23 zender Exp $"; 00112 const char * const CVS_Revision="$Revision: 1.100 $"; 00113 const char * const opt_sht_lst="4Aa:CcD:d:Fhl:M:Oo:P:p:Rrt:v:UxZ-:"; 00114 00115 dmn_sct **dim=NULL_CEWI; 00116 dmn_sct **dmn_out; 00117 dmn_sct **dmn_rdr=NULL; /* [sct] Dimension structures to be re-ordered */ 00118 00119 extern char *optarg; 00120 extern int optind; 00121 00122 /* Using naked stdin/stdout/stderr in parallel region generates warning 00123 Copy appropriate filehandle to variable scoped shared in parallel clause */ 00124 FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */ 00125 FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */ 00126 00127 int **dmn_idx_out_in=NULL; /* [idx] Dimension correspondence, output->input CEWI */ 00128 00129 int *in_id_arr; 00130 00131 int abb_arg_nbr=0; 00132 int dmn_out_idx; /* [idx] Index over output dimension list */ 00133 int dmn_out_idx_rec_in=NCO_REC_DMN_UNDEFINED; /* [idx] Record dimension index in output dimension list, original */ 00134 int dmn_rdr_nbr=0; /* [nbr] Number of dimension to re-order */ 00135 int dmn_rdr_nbr_in=0; /* [nbr] Original number of dimension to re-order */ 00136 int dmn_rdr_nbr_utl=0; /* [nbr] Number of dimension to re-order, utilized */ 00137 int fl_idx=int_CEWI; 00138 int fl_nbr=0; 00139 int fl_out_fmt=NC_FORMAT_CLASSIC; /* [enm] Output file format */ 00140 int fll_md_old; /* [enm] Old fill mode */ 00141 int idx=int_CEWI; 00142 int idx_rdr=int_CEWI; 00143 int in_id; 00144 int lmt_nbr=0; /* Option d. NB: lmt_nbr gets incremented */ 00145 int nbr_dmn_fl; 00146 int nbr_dmn_out; 00147 int nbr_dmn_xtr; 00148 int nbr_var_fix; /* nbr_var_fix gets incremented */ 00149 int nbr_var_fl; 00150 int nbr_var_prc; /* nbr_var_prc gets incremented */ 00151 int nbr_xtr=0; /* nbr_xtr won't otherwise be set for -c with no -v */ 00152 int nco_pck_map=nco_pck_map_flt_sht; /* [enm] Packing map */ 00153 int nco_pck_plc=nco_pck_plc_nil; /* [enm] Packing policy */ 00154 int opt; 00155 int out_id; 00156 int rcd=NC_NOERR; /* [rcd] Return code */ 00157 int rec_dmn_id_in=NCO_REC_DMN_UNDEFINED; /* [id] Record dimension ID in input file */ 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; 00165 nm_id_sct *dmn_rdr_lst; 00166 nm_id_sct *xtr_lst=NULL; /* xtr_lst may be alloc()'d from NULL with -c option */ 00167 00168 time_t time_crr_time_t; 00169 00170 var_sct **var; 00171 var_sct **var_fix; 00172 var_sct **var_fix_out; 00173 var_sct **var_out; 00174 var_sct **var_prc; 00175 var_sct **var_prc_out; 00176 00177 static struct option opt_lng[]= 00178 { /* Structure ordered by short option key if possible */ 00179 /* Long options with no argument, no short option counterpart */ 00180 /* Long options with argument, no short option counterpart */ 00181 {"fl_fmt",required_argument,0,0}, 00182 {"file_format",required_argument,0,0}, 00183 /* Long options with short counterparts */ 00184 {"4",no_argument,0,'4'}, 00185 {"64bit",no_argument,0,'4'}, 00186 {"netcdf4",no_argument,0,'4'}, 00187 {"append",no_argument,0,'A'}, 00188 {"arrange",required_argument,0,'a'}, 00189 {"permute",required_argument,0,'a'}, 00190 {"reorder",required_argument,0,'a'}, 00191 {"rdr",required_argument,0,'a'}, 00192 {"no-coords",no_argument,0,'C'}, 00193 {"no-crd",no_argument,0,'C'}, 00194 {"coords",no_argument,0,'c'}, 00195 {"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 {"pck_map",required_argument,0,'M'}, 00207 {"map",required_argument,0,'M'}, 00208 {"overwrite",no_argument,0,'O'}, 00209 {"ovr",no_argument,0,'O'}, 00210 {"output",required_argument,0,'o'}, 00211 {"fl_out",required_argument,0,'o'}, 00212 {"pack_policy",required_argument,0,'P'}, 00213 {"pck_plc",required_argument,0,'P'}, 00214 {"path",required_argument,0,'p'}, 00215 {"retain",no_argument,0,'R'}, 00216 {"rtn",no_argument,0,'R'}, 00217 {"revision",no_argument,0,'r'}, 00218 {"version",no_argument,0,'r'}, 00219 {"vrs",no_argument,0,'r'}, 00220 {"thr_nbr",required_argument,0,'t'}, 00221 {"threads",required_argument,0,'t'}, 00222 {"omp_num_threads",required_argument,0,'t'}, 00223 {"unpack",no_argument,0,'U'}, 00224 {"upk",no_argument,0,'U'}, 00225 {"variable",required_argument,0,'v'}, 00226 {"exclude",no_argument,0,'x'}, 00227 {"xcl",no_argument,0,'x'}, 00228 {"help",no_argument,0,'?'}, 00229 {0,0,0,0} 00230 }; /* end opt_lng */ 00231 int opt_idx=0; /* Index of current long option into opt_lng array */ 00232 00233 /* Start clock and save command line */ 00234 cmd_ln=nco_cmd_ln_sng(argc,argv); 00235 time_crr_time_t=time((time_t *)NULL); 00236 time_bfr_srt=ctime(&time_crr_time_t); time_bfr_srt=time_bfr_srt; /* Avoid compiler warning until variable is used for something */ 00237 00238 time_bfr_srt=time_bfr_srt; /* CEWI: Avert compiler warning that variable is set but never used */ 00239 00240 /* Get program name and set program enum (e.g., prg=ncra) */ 00241 prg_nm=prg_prs(argv[0],&prg); 00242 00243 /* Parse command line arguments */ 00244 while(1){ 00245 /* getopt_long_only() allows one dash to prefix long options */ 00246 opt=getopt_long(argc,argv,opt_sht_lst,opt_lng,&opt_idx); 00247 /* NB: access to opt_crr is only valid when long_opt is detected */ 00248 if(opt == EOF) break; /* Parse positional arguments once getopt_long() returns EOF */ 00249 opt_crr=(char *)strdup(opt_lng[opt_idx].name); 00250 00251 /* Process long options without short option counterparts */ 00252 if(opt == 0){ 00253 if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt); 00254 } /* opt != 0 */ 00255 /* Process short options */ 00256 switch(opt){ 00257 case 0: /* Long options have already been processed, return */ 00258 break; 00259 case '4': /* [flg] Catch-all to prescribe output storage format */ 00260 if(!strcmp(opt_crr,"64bit")) fl_out_fmt=NC_FORMAT_64BIT; else fl_out_fmt=NC_FORMAT_NETCDF4; 00261 break; 00262 case 'A': /* Toggle FORCE_APPEND */ 00263 FORCE_APPEND=!FORCE_APPEND; 00264 break; 00265 case 'a': /* Re-order dimensions */ 00266 dmn_rdr_lst_in=lst_prs_2D(optarg,",",&dmn_rdr_nbr_in); 00267 dmn_rdr_nbr=dmn_rdr_nbr_in; 00268 break; 00269 case 'C': /* Extract all coordinates associated with extracted variables? */ 00270 EXTRACT_ASSOCIATED_COORDINATES=False; 00271 break; 00272 case 'c': 00273 EXTRACT_ALL_COORDINATES=True; 00274 break; 00275 case 'D': /* Debugging level. Default is 0. */ 00276 dbg_lvl=(unsigned short)strtol(optarg,(char **)NULL,10); 00277 break; 00278 case 'd': /* Copy argument for later processing */ 00279 lmt_arg[lmt_nbr]=(char *)strdup(optarg); 00280 lmt_nbr++; 00281 break; 00282 case 'F': /* Toggle index convention. Default is 0-based arrays (C-style). */ 00283 FORTRAN_IDX_CNV=!FORTRAN_IDX_CNV; 00284 break; 00285 case 'h': /* Toggle appending to history global attribute */ 00286 HISTORY_APPEND=!HISTORY_APPEND; 00287 break; 00288 case 'l': /* Local path prefix for files retrieved from remote file system */ 00289 fl_pth_lcl=(char *)strdup(optarg); 00290 break; 00291 case 'M': /* Packing map */ 00292 nco_pck_map_sng=(char *)strdup(optarg); 00293 nco_pck_map=nco_pck_map_get(nco_pck_map_sng); 00294 break; 00295 case 'O': /* Toggle FORCE_OVERWRITE */ 00296 FORCE_OVERWRITE=!FORCE_OVERWRITE; 00297 break; 00298 case 'o': /* Name of output file */ 00299 fl_out=(char *)strdup(optarg); 00300 break; 00301 case 'P': /* Packing policy */ 00302 nco_pck_plc_sng=(char *)strdup(optarg); 00303 break; 00304 case 'p': /* Common file path */ 00305 fl_pth=(char *)strdup(optarg); 00306 break; 00307 case 'R': /* Toggle removal of remotely-retrieved-files. Default is True. */ 00308 REMOVE_REMOTE_FILES_AFTER_PROCESSING=!REMOVE_REMOTE_FILES_AFTER_PROCESSING; 00309 break; 00310 case 'r': /* Print CVS program information and copyright notice */ 00311 (void)copyright_prn(CVS_Id,CVS_Revision); 00312 (void)nco_lbr_vrs_prn(); 00313 nco_exit(EXIT_SUCCESS); 00314 break; 00315 case 't': /* Thread number */ 00316 thr_nbr=(int)strtol(optarg,(char **)NULL,10); 00317 break; 00318 case 'U': /* Unpacking switch */ 00319 nco_pck_plc_sng=(char *)strdup("upk"); 00320 break; 00321 case 'v': /* Variables to extract/exclude */ 00322 /* Replace commas with hashes when within braces (convert back later) */ 00323 optarg_lcl=(char *)strdup(optarg); 00324 (void)nco_lst_comma2hash(optarg_lcl); 00325 var_lst_in=lst_prs_2D(optarg_lcl,",",&var_lst_in_nbr); 00326 optarg_lcl=(char *)nco_free(optarg_lcl); 00327 nbr_xtr=var_lst_in_nbr; 00328 break; 00329 case 'x': /* Exclude rather than extract variables specified with -v */ 00330 EXCLUDE_INPUT_LIST=True; 00331 break; 00332 case '?': /* Print proper usage */ 00333 (void)nco_usg_prn(); 00334 nco_exit(EXIT_SUCCESS); 00335 break; 00336 case '-': /* Long options are not allowed */ 00337 (void)fprintf(stderr,"%s: ERROR Long options are not available in this build. Use single letter options instead.\n",prg_nm_get()); 00338 nco_exit(EXIT_FAILURE); 00339 break; 00340 default: /* Print proper usage */ 00341 (void)nco_usg_prn(); 00342 nco_exit(EXIT_FAILURE); 00343 break; 00344 } /* end switch */ 00345 if(opt_crr != NULL) opt_crr=(char *)nco_free(opt_crr); 00346 } /* end while loop */ 00347 00348 /* Process positional arguments and fill in filenames */ 00349 fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN); 00350 00351 /* Make uniform list of user-specified dimension limits */ 00352 lmt=nco_lmt_prs(lmt_nbr,lmt_arg); 00353 00354 /* Initialize thread information */ 00355 thr_nbr=nco_openmp_ini(thr_nbr); 00356 in_id_arr=(int *)nco_malloc(thr_nbr*sizeof(int)); 00357 00358 /* Parse filename */ 00359 fl_in=nco_fl_nm_prs(fl_in,0,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth); 00360 /* Make sure file is on local system and is readable or die trying */ 00361 fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION); 00362 /* Open file for reading */ 00363 rcd=nco_open(fl_in,NC_NOWRITE,&in_id); 00364 00365 /* Get number of variables, dimensions, and record dimension ID of input file */ 00366 (void)nco_inq(in_id,&nbr_dmn_fl,&nbr_var_fl,(int *)NULL,&rec_dmn_id_in); 00367 00368 /* Form initial extraction list which may include extended regular expressions */ 00369 xtr_lst=nco_var_lst_mk(in_id,nbr_var_fl,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr); 00370 00371 /* Change included variables to excluded variables */ 00372 if(EXCLUDE_INPUT_LIST) xtr_lst=nco_var_lst_xcl(in_id,nbr_var_fl,xtr_lst,&nbr_xtr); 00373 00374 /* Add all coordinate variables to extraction list */ 00375 if(EXTRACT_ALL_COORDINATES) xtr_lst=nco_var_lst_add_crd(in_id,nbr_dmn_fl,xtr_lst,&nbr_xtr); 00376 00377 /* Make sure coordinates associated extracted variables are also on extraction list */ 00378 if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst=nco_var_lst_ass_crd_add(in_id,xtr_lst,&nbr_xtr); 00379 00380 /* Sort extraction list by variable ID for fastest I/O */ 00381 if(nbr_xtr > 1) xtr_lst=nco_lst_srt_nm_id(xtr_lst,nbr_xtr,False); 00382 00383 /* Find coordinate/dimension values associated with user-specified limits 00384 NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */ 00385 for(idx=0;idx<lmt_nbr;idx++) (void)nco_lmt_evl(in_id,lmt[idx],0L,FORTRAN_IDX_CNV); 00386 00387 /* Find dimensions associated with variables to be extracted */ 00388 dmn_lst=nco_dmn_lst_ass_var(in_id,xtr_lst,nbr_xtr,&nbr_dmn_xtr); 00389 00390 /* Fill in dimension structure for all extracted dimensions */ 00391 dim=(dmn_sct **)nco_malloc(nbr_dmn_xtr*sizeof(dmn_sct *)); 00392 for(idx=0;idx<nbr_dmn_xtr;idx++) dim[idx]=nco_dmn_fll(in_id,dmn_lst[idx].id,dmn_lst[idx].nm); 00393 /* Dimension list no longer needed */ 00394 dmn_lst=nco_nm_id_lst_free(dmn_lst,nbr_dmn_xtr); 00395 00396 /* Merge hyperslab limit information into dimension structures */ 00397 if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim,nbr_dmn_xtr,lmt,lmt_nbr); 00398 00399 /* Duplicate input dimension structures for output dimension structures */ 00400 nbr_dmn_out=nbr_dmn_xtr; 00401 dmn_out=(dmn_sct **)nco_malloc(nbr_dmn_out*sizeof(dmn_sct *)); 00402 for(idx=0;idx<nbr_dmn_out;idx++){ 00403 dmn_out[idx]=nco_dmn_dpl(dim[idx]); 00404 (void)nco_dmn_xrf(dim[idx],dmn_out[idx]); 00405 } /* end loop over idx */ 00406 00407 /* No re-order dimensions specified implies packing request */ 00408 if(dmn_rdr_nbr == 0){ 00409 if(nco_pck_plc == nco_pck_plc_nil) nco_pck_plc=nco_pck_plc_get(nco_pck_plc_sng); 00410 if(dbg_lvl > 0) (void)fprintf(stderr,"%s: DEBUG Packing map is %s and packing policy is %s\n",prg_nm_get(),nco_pck_map_sng_get(nco_pck_map),nco_pck_plc_sng_get(nco_pck_plc)); 00411 } /* endif */ 00412 00413 /* From this point forward, assume ncpdq operator packs or re-orders, not both */ 00414 if(dmn_rdr_nbr > 0 && nco_pck_plc != nco_pck_plc_nil){ 00415 (void)fprintf(fp_stdout,"%s: ERROR %s does not support simultaneous dimension re-ordering (-a switch) and packing (-P switch).\nHINT: Invoke %s twice, once to re-order (with -a), and once to pack (with -P).\n",prg_nm,prg_nm,prg_nm); 00416 nco_exit(EXIT_FAILURE); 00417 } /* end if */ 00418 00419 if(dmn_rdr_nbr > 0){ 00420 /* NB: Same logic as in ncwa, perhaps combine into single function, nco_dmn_avg_rdr_prp()? */ 00421 /* Make list of user-specified dimension re-orders */ 00422 00423 /* Create reversed dimension list */ 00424 dmn_rvr_rdr=(nco_bool *)nco_malloc(dmn_rdr_nbr*sizeof(nco_bool)); 00425 for(idx_rdr=0;idx_rdr<dmn_rdr_nbr;idx_rdr++){ 00426 if(dmn_rdr_lst_in[idx_rdr][0] == '-'){ 00427 dmn_rvr_rdr[idx_rdr]=True; 00428 /* Copy string to new memory one past negative sign to avoid losing byte */ 00429 optarg_lcl=dmn_rdr_lst_in[idx_rdr]; 00430 dmn_rdr_lst_in[idx_rdr]=(char *)strdup(optarg_lcl+1); 00431 optarg_lcl=(char *)nco_free(optarg_lcl); 00432 }else{ 00433 dmn_rvr_rdr[idx_rdr]=False; 00434 } /* end else */ 00435 } /* end loop over idx_rdr */ 00436 00437 /* Create structured list of re-ordering dimension names and IDs */ 00438 dmn_rdr_lst=nco_dmn_lst_mk(in_id,dmn_rdr_lst_in,dmn_rdr_nbr); 00439 00440 /* Form list of re-ordering dimensions from extracted input dimensions */ 00441 dmn_rdr=(dmn_sct **)nco_malloc(dmn_rdr_nbr*sizeof(dmn_sct *)); 00442 /* Loop over original number of re-order dimensions */ 00443 for(idx_rdr=0;idx_rdr<dmn_rdr_nbr;idx_rdr++){ 00444 for(idx=0;idx<nbr_dmn_xtr;idx++){ 00445 if(!strcmp(dmn_rdr_lst[idx_rdr].nm,dim[idx]->nm)) break; 00446 } /* end loop over idx_rdr */ 00447 if(idx != nbr_dmn_xtr) dmn_rdr[dmn_rdr_nbr_utl++]=dim[idx]; else (void)fprintf(stderr,"%s: WARNING re-ordering dimension \"%s\" is not contained in any variable in extraction list\n",prg_nm,dmn_rdr_lst[idx_rdr].nm); 00448 } /* end loop over idx_rdr */ 00449 dmn_rdr_nbr=dmn_rdr_nbr_utl; 00450 /* Collapse extra dimension structure space to prevent accidentally using it */ 00451 dmn_rdr=(dmn_sct **)nco_realloc(dmn_rdr,dmn_rdr_nbr*sizeof(dmn_sct *)); 00452 /* Dimension list in name-ID format is no longer needed */ 00453 dmn_rdr_lst=nco_nm_id_lst_free(dmn_rdr_lst,dmn_rdr_nbr); 00454 00455 /* Make sure no re-ordering dimension is specified more than once */ 00456 for(idx=0;idx<dmn_rdr_nbr;idx++){ 00457 for(idx_rdr=0;idx_rdr<dmn_rdr_nbr;idx_rdr++){ 00458 if(idx_rdr != idx){ 00459 if(dmn_rdr[idx]->id == dmn_rdr[idx_rdr]->id){ 00460 (void)fprintf(fp_stdout,"%s: ERROR %s specified more than once in reducing list\n",prg_nm,dmn_rdr[idx]->nm); 00461 nco_exit(EXIT_FAILURE); 00462 } /* end if */ 00463 } /* end if */ 00464 } /* end loop over idx_rdr */ 00465 } /* end loop over idx */ 00466 00467 if(dmn_rdr_nbr > nbr_dmn_xtr){ 00468 (void)fprintf(fp_stdout,"%s: ERROR More re-ordering dimensions than extracted dimensions\n",prg_nm); 00469 nco_exit(EXIT_FAILURE); 00470 } /* end if */ 00471 00472 } /* dmn_rdr_nbr <= 0 */ 00473 00474 /* Is this an CCM/CCSM/CF-format history tape? */ 00475 CNV_CCM_CCSM_CF=nco_cnv_ccm_ccsm_cf_inq(in_id); 00476 00477 /* Fill in variable structure list for all extracted variables */ 00478 var=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *)); 00479 var_out=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *)); 00480 for(idx=0;idx<nbr_xtr;idx++){ 00481 var[idx]=nco_var_fll(in_id,xtr_lst[idx].id,xtr_lst[idx].nm,dim,nbr_dmn_xtr); 00482 var_out[idx]=nco_var_dpl(var[idx]); 00483 (void)nco_xrf_var(var[idx],var_out[idx]); 00484 (void)nco_xrf_dmn(var_out[idx]); 00485 } /* end loop over idx */ 00486 /* Extraction list no longer needed */ 00487 xtr_lst=nco_nm_id_lst_free(xtr_lst,nbr_xtr); 00488 00489 /* Divide variable lists into lists of fixed variables and variables to be processed */ 00490 (void)nco_var_lst_dvd(var,var_out,nbr_xtr,CNV_CCM_CCSM_CF,nco_pck_map,nco_pck_plc,dmn_rdr,dmn_rdr_nbr,&var_fix,&var_fix_out,&nbr_var_fix,&var_prc,&var_prc_out,&nbr_var_prc); 00491 00492 /* We now have final list of variables to extract. Phew. */ 00493 if(dbg_lvl > 2){ 00494 for(idx=0;idx<nbr_xtr;idx++) (void)fprintf(stderr,"var[%d]->nm = %s, ->id=[%d]\n",idx,var[idx]->nm,var[idx]->id); 00495 for(idx=0;idx<nbr_var_fix;idx++) (void)fprintf(stderr,"var_fix[%d]->nm = %s, ->id=[%d]\n",idx,var_fix[idx]->nm,var_fix[idx]->id); 00496 for(idx=0;idx<nbr_var_prc;idx++) (void)fprintf(stderr,"var_prc[%d]->nm = %s, ->id=[%d]\n",idx,var_prc[idx]->nm,var_prc[idx]->id); 00497 } /* end if */ 00498 00499 /* Open output file */ 00500 fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&out_id); 00501 if(dbg_lvl > 4) (void)fprintf(stderr,"Input, output file IDs = %d, %d\n",in_id,out_id); 00502 00503 /* Copy global attributes */ 00504 (void)nco_att_cpy(in_id,out_id,NC_GLOBAL,NC_GLOBAL,True); 00505 00506 /* Catenate time-stamped command line to "history" global attribute */ 00507 if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln); 00508 00509 if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr); 00510 00511 /* If re-ordering, then in files with record dimension... */ 00512 if(dmn_rdr_nbr > 0 && rec_dmn_id_in != NCO_REC_DMN_UNDEFINED){ 00513 /* ...which, if any, output dimension structure currently holds record dimension? */ 00514 for(dmn_out_idx=0;dmn_out_idx<nbr_dmn_out;dmn_out_idx++) 00515 if(dmn_out[dmn_out_idx]->is_rec_dmn) break; 00516 if(dmn_out_idx != nbr_dmn_out){ 00517 dmn_out_idx_rec_in=dmn_out_idx; 00518 /* Initialize output record dimension to input record dimension */ 00519 rec_dmn_nm_in=rec_dmn_nm_out=dmn_out[dmn_out_idx_rec_in]->nm; 00520 }else{ 00521 dmn_out_idx_rec_in=NCO_REC_DMN_UNDEFINED; 00522 } /* end else */ 00523 } /* end if file contains record dimension */ 00524 00525 /* If re-ordering, determine and set new dimensionality in metadata of each re-ordered variable */ 00526 if(dmn_rdr_nbr > 0){ 00527 dmn_idx_out_in=(int **)nco_malloc(nbr_var_prc*sizeof(int *)); 00528 dmn_rvr_in=(nco_bool **)nco_malloc(nbr_var_prc*sizeof(nco_bool *)); 00529 for(idx=0;idx<nbr_var_prc;idx++){ 00530 dmn_idx_out_in[idx]=(int *)nco_malloc(var_prc[idx]->nbr_dim*sizeof(int)); 00531 dmn_rvr_in[idx]=(nco_bool *)nco_malloc(var_prc[idx]->nbr_dim*sizeof(nco_bool)); 00532 /* nco_var_dmn_rdr_mtd() does re-order heavy lifting */ 00533 rec_dmn_nm_out_crr=nco_var_dmn_rdr_mtd(var_prc[idx],var_prc_out[idx],dmn_rdr,dmn_rdr_nbr,dmn_idx_out_in[idx],dmn_rvr_rdr,dmn_rvr_in[idx]); 00534 /* If record dimension required by current variable re-order... 00535 ...and variable is multi-dimensional (one dimensional arrays 00536 cannot request record dimension changes)... */ 00537 if(rec_dmn_nm_out_crr && var_prc_out[idx]->nbr_dim > 1){ 00538 /* ...differs from input and current output record dimension(s)... */ 00539 if(strcmp(rec_dmn_nm_out_crr,rec_dmn_nm_in) && strcmp(rec_dmn_nm_out_crr,rec_dmn_nm_out)){ 00540 /* ...and current output record dimension already differs from input record dimension... */ 00541 if(REDEFINED_RECORD_DIMENSION){ 00542 /* ...then requested re-order requires multiple record dimensions... */ 00543 (void)fprintf(fp_stdout,"%s: WARNING Re-order requests multiple record dimensions\n. Only first request will be honored (netCDF allows only one record dimension). Record dimensions involved [original,first change request (honored),latest change request (made by variable %s)]=[%s,%s,%s]\n",prg_nm,var_prc[idx]->nm,rec_dmn_nm_in,rec_dmn_nm_out,rec_dmn_nm_out_crr); 00544 break; 00545 }else{ /* !REDEFINED_RECORD_DIMENSION */ 00546 /* ...otherwise, update output record dimension name... */ 00547 rec_dmn_nm_out=rec_dmn_nm_out_crr; 00548 /* ...and set new and un-set old record dimensions... */ 00549 var_prc_out[idx]->dim[0]->is_rec_dmn=True; 00550 dmn_out[dmn_out_idx_rec_in]->is_rec_dmn=False; 00551 /* ...and set flag that record dimension has been re-defined... */ 00552 REDEFINED_RECORD_DIMENSION=True; 00553 } /* !REDEFINED_RECORD_DIMENSION */ 00554 } /* endif new and old record dimensions differ */ 00555 } /* endif current variable is record variable */ 00556 } /* end loop over var_prc */ 00557 } /* endif dmn_rdr_nbr > 0 */ 00558 00559 /* NB: Much of following logic is required by netCDF constraint that only 00560 one record variable is allowed per file. netCDF4 will relax this constraint. 00561 Hence making following logic prettier or funcionalizing is not high priority. 00562 Logic may need to be simplified/re-written once netCDF4 is released. */ 00563 if(REDEFINED_RECORD_DIMENSION){ 00564 (void)fprintf(fp_stdout,"%s: INFO Requested re-order will change record dimension from %s to %s. netCDF allows only one record dimension. Hence %s will make %s record (least rapidly varying) dimension in all variables that contain it.\n",prg_nm,rec_dmn_nm_in,rec_dmn_nm_out,prg_nm,rec_dmn_nm_out); 00565 /* Changing record dimension may invalidate is_rec_var flag 00566 Updating is_rec_var flag to correct value, even if value is ignored, 00567 helps keep user appraised of unexpected dimension re-orders. 00568 is_rec_var may change both for "fixed" and "processed" variables 00569 When is_rec_var changes for processed variables, may also need to change 00570 ancillary information and to check for duplicate dimensions. 00571 Ancillary information (dmn_idx_out_in) is available only for var_prc! 00572 Hence must update is_rec_var flag for var_fix and var_prc separately */ 00573 00574 /* Update is_rec_var flag for var_fix */ 00575 for(idx=0;idx<nbr_var_fix;idx++){ 00576 /* Search all dimensions in variable for new record dimension */ 00577 for(dmn_out_idx=0;dmn_out_idx<var_fix[idx]->nbr_dim;dmn_out_idx++) 00578 if(!strcmp(var_fix[idx]->dim[dmn_out_idx]->nm,rec_dmn_nm_out)) break; 00579 /* ...Will variable be record variable in output file?... */ 00580 if(dmn_out_idx == var_fix[idx]->nbr_dim){ 00581 /* ...No. Variable will be non-record---does this change its status?... */ 00582 if(dbg_lvl > 2) if(var_fix[idx]->is_rec_var == True) (void)fprintf(fp_stdout,"%s: INFO Requested re-order will change variable %s from record to non-record variable\n",prg_nm,var_fix[idx]->nm); 00583 /* Assign record flag dictated by re-order */ 00584 var_fix[idx]->is_rec_var=False; 00585 }else{ /* ...otherwise variable will be record variable... */ 00586 /* ...Yes. Variable will be record... */ 00587 /* ...Will becoming record variable change its status?... */ 00588 if(var_fix[idx]->is_rec_var == False){ 00589 if(dbg_lvl > 2) (void)fprintf(fp_stdout,"%s: INFO Requested re-order will change variable %s from non-record to record variable\n",prg_nm,var_fix[idx]->nm); 00590 /* Change record flag to status dictated by re-order */ 00591 var_fix[idx]->is_rec_var=True; 00592 } /* endif status changing from non-record to record */ 00593 } /* endif variable will be record variable */ 00594 } /* end loop over var_fix */ 00595 00596 /* Update is_rec_var flag for var_prc */ 00597 for(idx=0;idx<nbr_var_prc;idx++){ 00598 /* Search all dimensions in variable for new record dimension */ 00599 for(dmn_out_idx=0;dmn_out_idx<var_prc_out[idx]->nbr_dim;dmn_out_idx++) 00600 if(!strcmp(var_prc_out[idx]->dim[dmn_out_idx]->nm,rec_dmn_nm_out)) break; 00601 /* ...Will variable be record variable in output file?... */ 00602 if(dmn_out_idx == var_prc_out[idx]->nbr_dim){ 00603 /* ...No. Variable will be non-record---does this change its status?... */ 00604 if(dbg_lvl > 2) if(var_prc_out[idx]->is_rec_var == True) (void)fprintf(fp_stdout,"%s: INFO Requested re-order will change variable %s from record to non-record variable\n",prg_nm,var_prc_out[idx]->nm); 00605 /* Assign record flag dictated by re-order */ 00606 var_prc_out[idx]->is_rec_var=False; 00607 }else{ /* ...otherwise variable will be record variable... */ 00608 /* ...Yes. Variable will be record... */ 00609 /* ...must ensure new record dimension is not duplicate dimension... */ 00610 if(var_prc_out[idx]->has_dpl_dmn){ 00611 int dmn_dpl_idx; 00612 for(dmn_dpl_idx=1;dmn_dpl_idx<var_prc_out[idx]->nbr_dim;dmn_dpl_idx++){ /* NB: loop starts from 1 */ 00613 if(var_prc_out[idx]->dmn_id[0] == var_prc_out[idx]->dmn_id[dmn_dpl_idx]){ 00614 (void)fprintf(stdout,"%s: ERROR Requested re-order turns duplicate non-record dimension %s in variable %s into output record dimension. netCDF does not support duplicate record dimensions in a single variable.\n%s: HINT: Exclude variable %s from extraction list with \"-x -v %s\".\n",prg_nm_get(),rec_dmn_nm_out,var_prc_out[idx]->nm,prg_nm_get(),var_prc_out[idx]->nm,var_prc_out[idx]->nm); 00615 nco_exit(EXIT_FAILURE); 00616 } /* endif err */ 00617 } /* end loop over dmn_out */ 00618 } /* endif has_dpl_dmn */ 00619 /* ...Will becoming record variable change its status?... */ 00620 if(var_prc_out[idx]->is_rec_var == False){ 00621 if(dbg_lvl > 2) (void)fprintf(fp_stdout,"%s: INFO Requested re-order will change variable %s from non-record to record variable\n",prg_nm,var_prc_out[idx]->nm); 00622 /* Change record flag to status dictated by re-order */ 00623 var_prc_out[idx]->is_rec_var=True; 00624 /* ...Swap dimension information for multi-dimensional variables... */ 00625 if(var_prc_out[idx]->nbr_dim > 1){ 00626 /* Swap dimension information when turning multi-dimensional 00627 non-record variable into record variable. 00628 Single dimensional non-record variables that turn into 00629 record variables already have correct dimension information */ 00630 dmn_sct *dmn_swp; /* [sct] Dimension structure for swapping */ 00631 int dmn_idx_rec_in; /* [idx] Record dimension index in input variable */ 00632 int dmn_idx_rec_out; /* [idx] Record dimension index in output variable */ 00633 int dmn_idx_swp; /* [idx] Dimension index for swapping */ 00634 /* If necessary, swap new record dimension to first position */ 00635 /* Label indices with standard names */ 00636 dmn_idx_rec_in=dmn_out_idx; 00637 dmn_idx_rec_out=0; 00638 /* Swap indices in map */ 00639 dmn_idx_swp=dmn_idx_out_in[idx][dmn_idx_rec_out]; 00640 dmn_idx_out_in[idx][dmn_idx_rec_out]=dmn_idx_rec_in; 00641 dmn_idx_out_in[idx][dmn_idx_rec_in]=dmn_idx_swp; 00642 /* Swap dimensions in list */ 00643 dmn_swp=var_prc_out[idx]->dim[dmn_idx_rec_out]; 00644 var_prc_out[idx]->dim[dmn_idx_rec_out]=var_prc_out[idx]->dim[dmn_idx_rec_in]; 00645 var_prc_out[idx]->dim[dmn_idx_rec_in]=dmn_swp; 00646 /* NB: Change dmn_id,cnt,srt,end,srd together to minimize chances of forgetting one */ 00647 /* Correct output variable structure copy of output record dimension information */ 00648 var_prc_out[idx]->dmn_id[dmn_idx_rec_out]=var_prc_out[idx]->dim[dmn_idx_rec_out]->id; 00649 var_prc_out[idx]->cnt[dmn_idx_rec_out]=var_prc_out[idx]->dim[dmn_idx_rec_out]->cnt; 00650 var_prc_out[idx]->srt[dmn_idx_rec_out]=var_prc_out[idx]->dim[dmn_idx_rec_out]->srt; 00651 var_prc_out[idx]->end[dmn_idx_rec_out]=var_prc_out[idx]->dim[dmn_idx_rec_out]->end; 00652 var_prc_out[idx]->srd[dmn_idx_rec_out]=var_prc_out[idx]->dim[dmn_idx_rec_out]->srd; 00653 /* Correct output variable structure copy of input record dimension information */ 00654 var_prc_out[idx]->dmn_id[dmn_idx_rec_in]=var_prc_out[idx]->dim[dmn_idx_rec_in]->id; 00655 var_prc_out[idx]->cnt[dmn_idx_rec_in]=var_prc_out[idx]->dim[dmn_idx_rec_in]->cnt; 00656 var_prc_out[idx]->srt[dmn_idx_rec_in]=var_prc_out[idx]->dim[dmn_idx_rec_in]->srt; 00657 var_prc_out[idx]->end[dmn_idx_rec_in]=var_prc_out[idx]->dim[dmn_idx_rec_in]->end; 00658 var_prc_out[idx]->srd[dmn_idx_rec_in]=var_prc_out[idx]->dim[dmn_idx_rec_in]->srd; 00659 } /* endif multi-dimensional */ 00660 } /* endif status changing from non-record to record */ 00661 } /* endif variable will be record variable */ 00662 } /* end loop over var_prc */ 00663 } /* !REDEFINED_RECORD_DIMENSION */ 00664 00665 /* Once new record dimension, if any, is known, define dimensions in output file */ 00666 (void)nco_dmn_dfn(fl_out,out_id,dmn_out,nbr_dmn_out); 00667 00668 /* Alter metadata for variables that will be packed */ 00669 if(nco_pck_plc != nco_pck_plc_nil){ 00670 if(nco_pck_plc != nco_pck_plc_upk){ 00671 /* Allocate attribute list container for maximum number of entries */ 00672 aed_lst_add_fst=(aed_sct *)nco_malloc(nbr_var_prc*sizeof(aed_sct)); 00673 aed_lst_scl_fct=(aed_sct *)nco_malloc(nbr_var_prc*sizeof(aed_sct)); 00674 } /* endif packing */ 00675 for(idx=0;idx<nbr_var_prc;idx++){ 00676 nco_pck_mtd(var_prc[idx],var_prc_out[idx],nco_pck_map,nco_pck_plc); 00677 if(nco_pck_plc != nco_pck_plc_upk){ 00678 /* Use same copy of attribute name for all edits */ 00679 aed_lst_add_fst[idx].att_nm=add_fst_sng; 00680 aed_lst_scl_fct[idx].att_nm=scl_fct_sng; 00681 } /* endif packing */ 00682 } /* end loop over var_prc */ 00683 } /* nco_pck_plc == nco_pck_plc_nil */ 00684 00685 /* Define variables in output file, copy their attributes */ 00686 (void)nco_var_dfn(in_id,fl_out,out_id,var_out,nbr_xtr,(dmn_sct **)NULL,(int)0,nco_pck_map,nco_pck_plc); 00687 00688 /* Turn off default filling behavior to enhance efficiency */ 00689 rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old); 00690 00691 /* Take output file out of define mode */ 00692 (void)nco_enddef(out_id); 00693 00694 /* Zero start vectors for all output variables */ 00695 (void)nco_var_srt_zero(var_out,nbr_xtr); 00696 00697 /* Copy variable data for non-processed variables */ 00698 (void)nco_var_val_cpy(in_id,out_id,var_fix,nbr_var_fix); 00699 00700 /* Close first input netCDF file */ 00701 nco_close(in_id); 00702 00703 /* Loop over input files (not currently used, fl_nbr == 1) */ 00704 for(fl_idx=0;fl_idx<fl_nbr;fl_idx++){ 00705 /* Parse filename */ 00706 if(fl_idx != 0) fl_in=nco_fl_nm_prs(fl_in,fl_idx,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth); 00707 if(dbg_lvl > 0) (void)fprintf(stderr,"\nInput file %d is %s; ",fl_idx,fl_in); 00708 /* Make sure file is on local system and is readable or die trying */ 00709 if(fl_idx != 0) fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION); 00710 if(dbg_lvl > 0) (void)fprintf(stderr,"local file %s:\n",fl_in); 00711 00712 /* Open file once per thread to improve caching */ 00713 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in,NC_NOWRITE,in_id_arr+thr_idx); 00714 00715 #ifdef _OPENMP 00716 #pragma omp parallel for default(none) private(idx,in_id) shared(aed_lst_add_fst,aed_lst_scl_fct,dbg_lvl,dmn_idx_out_in,dmn_rdr_nbr,dmn_rvr_in,fp_stderr,fp_stdout,in_id_arr,nbr_var_prc,nco_pck_map,nco_pck_plc,out_id,prg_nm,rcd,var_prc,var_prc_out) 00717 #endif /* !_OPENMP */ 00718 for(idx=0;idx<nbr_var_prc;idx++){ /* Process all variables in current file */ 00719 in_id=in_id_arr[omp_get_thread_num()]; 00720 /* fxm TODO nco638 temporary fix? or leave permanantly? */ 00721 var_prc[idx]->nc_id=in_id; 00722 if(dbg_lvl > 1) rcd+=nco_var_prc_crr_prn(idx,var_prc[idx]->nm); 00723 if(dbg_lvl > 0) (void)fflush(fp_stderr); 00724 00725 /* Retrieve variable from disk into memory */ 00726 /* NB: nco_var_get() with same nc_id contains OpenMP critical region */ 00727 (void)nco_var_get(in_id,var_prc[idx]); 00728 00729 if(dmn_rdr_nbr > 0){ 00730 if((var_prc_out[idx]->val.vp=(void *)nco_malloc_flg(var_prc_out[idx]->sz*nco_typ_lng(var_prc_out[idx]->type))) == NULL){ 00731 (void)fprintf(fp_stdout,"%s: ERROR Unable to malloc() %ld*%lu bytes for value buffer for variable %s in main()\n",prg_nm_get(),var_prc_out[idx]->sz,(unsigned long)nco_typ_lng(var_prc_out[idx]->type),var_prc_out[idx]->nm); 00732 nco_exit(EXIT_FAILURE); 00733 } /* endif err */ 00734 00735 /* Change dimensionionality of values */ 00736 rcd=nco_var_dmn_rdr_val(var_prc[idx],var_prc_out[idx],dmn_idx_out_in[idx],dmn_rvr_in[idx]); 00737 /* Re-ordering required two value buffers, time to free input buffer */ 00738 var_prc[idx]->val.vp=nco_free(var_prc[idx]->val.vp); 00739 /* Free current dimension correspondence */ 00740 dmn_idx_out_in[idx]=(int *)nco_free(dmn_idx_out_in[idx]); 00741 dmn_rvr_in[idx]=(nco_bool *)nco_free(dmn_rvr_in[idx]); 00742 } /* endif dmn_rdr_nbr > 0 */ 00743 00744 if(nco_pck_plc != nco_pck_plc_nil){ 00745 /* Copy input variable buffer to processed variable buffer */ 00746 /* fxm: this is dangerous and leads to double free()'ing variable buffer */ 00747 var_prc_out[idx]->val=var_prc[idx]->val; 00748 /* (Un-)Pack variable according to packing specification */ 00749 nco_pck_val(var_prc[idx],var_prc_out[idx],nco_pck_map,nco_pck_plc,aed_lst_add_fst+idx,aed_lst_scl_fct+idx); 00750 } /* endif dmn_rdr_nbr > 0 */ 00751 00752 #ifdef _OPENMP 00753 #pragma omp critical 00754 #endif /* _OPENMP */ 00755 { /* begin OpenMP critical */ 00756 /* Copy variable to output file then free value buffer */ 00757 if(var_prc_out[idx]->nbr_dim == 0){ 00758 (void)nco_put_var1(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->val.vp,var_prc_out[idx]->type); 00759 }else{ /* end if variable is scalar */ 00760 (void)nco_put_vara(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_out[idx]->val.vp,var_prc_out[idx]->type); 00761 } /* end if variable is array */ 00762 } /* end OpenMP critical */ 00763 /* Free current output buffer */ 00764 var_prc_out[idx]->val.vp=nco_free(var_prc_out[idx]->val.vp); 00765 00766 } /* end (OpenMP parallel for) loop over idx */ 00767 00768 if(dbg_lvl > 0) (void)fprintf(fp_stderr,"\n"); 00769 00770 /* Write/overwrite packing attributes for newly packed and re-packed variables 00771 Logic here should nearly mimic logic in nco_var_dfn() */ 00772 if(nco_pck_plc != nco_pck_plc_nil && nco_pck_plc != nco_pck_plc_upk){ 00773 nco_bool nco_pck_plc_alw; /* [flg] Packing policy allows packing nc_typ_in */ 00774 /* ...put file in define mode to allow metadata writing... */ 00775 (void)nco_redef(out_id); 00776 /* ...loop through all variables that may have been packed... */ 00777 for(idx=0;idx<nbr_var_prc;idx++){ 00778 /* nco_var_dfn() pre-defined dummy packing attributes in output file 00779 only for input variables considered "packable" */ 00780 if((nco_pck_plc_alw=nco_pck_plc_typ_get(nco_pck_map,var_prc[idx]->typ_upk,(nc_type *)NULL))){ 00781 /* Verify input variable was newly packed by this operator 00782 Writing pre-existing (non-re-packed) attributes here would fail because 00783 nco_pck_dsk_inq() never fills in var->scl_fct.vp and var->add_fst.vp 00784 Logic is same as in nco_var_dfn() (except var_prc[] instead of var[]) 00785 If operator newly packed this particular variable... */ 00786 if( 00787 /* ...either because operator newly packs all variables... */ 00788 (nco_pck_plc == nco_pck_plc_all_new_att) || 00789 /* ...or because operator newly packs un-packed variables like this one... */ 00790 (nco_pck_plc == nco_pck_plc_all_xst_att && !var_prc[idx]->pck_ram) || 00791 /* ...or because operator re-packs packed variables like this one... */ 00792 (nco_pck_plc == nco_pck_plc_xst_new_att && var_prc[idx]->pck_ram) 00793 ){ 00794 /* Replace dummy packing attributes with final values, or delete them */ 00795 if(dbg_lvl >= 5) (void)fprintf(stderr,"%s: main() replacing dummy packing attribute values for variable %s\n",prg_nm,var_prc[idx]->nm); 00796 (void)nco_aed_prc(out_id,aed_lst_add_fst[idx].id,aed_lst_add_fst[idx]); 00797 (void)nco_aed_prc(out_id,aed_lst_scl_fct[idx].id,aed_lst_scl_fct[idx]); 00798 } /* endif variable is newly packed by this operator */ 00799 } /* endif nco_pck_plc_alw */ 00800 } /* end loop over var_prc */ 00801 (void)nco_enddef(out_id); 00802 } /* nco_pck_plc == nco_pck_plc_nil || nco_pck_plc == nco_pck_plc_upk */ 00803 00804 /* Close input netCDF file */ 00805 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_arr[thr_idx]); 00806 00807 /* Remove local copy of file */ 00808 if(FILE_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in); 00809 00810 } /* end loop over fl_idx */ 00811 00812 /* Close output file and move it from temporary to permanent location */ 00813 (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id); 00814 00815 /* ncpdq-specific memory cleanup */ 00816 if(dmn_rdr_nbr > 0){ 00817 /* Free dimension correspondence list */ 00818 for(idx=0;idx<nbr_var_prc;idx++){ 00819 dmn_idx_out_in[idx]=(int *)nco_free(dmn_idx_out_in[idx]); 00820 dmn_rvr_in[idx]=(nco_bool *)nco_free(dmn_rvr_in[idx]); 00821 } /* end loop over idx */ 00822 if(dmn_idx_out_in != NULL) dmn_idx_out_in=(int **)nco_free(dmn_idx_out_in); 00823 if(dmn_rvr_in != NULL) dmn_rvr_in=(nco_bool **)nco_free(dmn_rvr_in); 00824 if(dmn_rvr_rdr != NULL) dmn_rvr_rdr=(nco_bool *)nco_free(dmn_rvr_rdr); 00825 if(dmn_rdr_nbr_in > 0) dmn_rdr_lst_in=nco_sng_lst_free(dmn_rdr_lst_in,dmn_rdr_nbr_in); 00826 /* Free dimension list pointers */ 00827 dmn_rdr=(dmn_sct **)nco_free(dmn_rdr); 00828 /* Dimension structures in dmn_rdr are owned by dmn and dmn_out, free'd later */ 00829 } /* endif dmn_rdr_nbr > 0 */ 00830 if(nco_pck_plc != nco_pck_plc_nil){ 00831 if(nco_pck_plc_sng != NULL) nco_pck_plc_sng=(char *)nco_free(nco_pck_plc_sng); 00832 if(nco_pck_map_sng != NULL) nco_pck_map_sng=(char *)nco_free(nco_pck_map_sng); 00833 if(nco_pck_plc != nco_pck_plc_upk){ 00834 /* No need for loop over var_prc variables to free attribute values 00835 Variable structures and attribute edit lists share same attribute values 00836 Free them only once, and do it in nco_var_free() */ 00837 aed_lst_add_fst=(aed_sct *)nco_free(aed_lst_add_fst); 00838 aed_lst_scl_fct=(aed_sct *)nco_free(aed_lst_scl_fct); 00839 } /* nco_pck_plc == nco_pck_plc_upk */ 00840 } /* nco_pck_plc == nco_pck_plc_nil */ 00841 00842 /* NCO-generic clean-up */ 00843 /* Free individual strings/arrays */ 00844 if(cmd_ln != NULL) cmd_ln=(char *)nco_free(cmd_ln); 00845 if(fl_in != NULL) fl_in=(char *)nco_free(fl_in); 00846 if(fl_out != NULL) fl_out=(char *)nco_free(fl_out); 00847 if(fl_out_tmp != NULL) fl_out_tmp=(char *)nco_free(fl_out_tmp); 00848 if(fl_pth != NULL) fl_pth=(char *)nco_free(fl_pth); 00849 if(fl_pth_lcl != NULL) fl_pth_lcl=(char *)nco_free(fl_pth_lcl); 00850 if(in_id_arr != NULL) in_id_arr=(int *)nco_free(in_id_arr); 00851 /* Free lists of strings */ 00852 if(fl_lst_in != NULL && fl_lst_abb == NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,fl_nbr); 00853 if(fl_lst_in != NULL && fl_lst_abb != NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,1); 00854 if(fl_lst_abb != NULL) fl_lst_abb=nco_sng_lst_free(fl_lst_abb,abb_arg_nbr); 00855 if(var_lst_in_nbr > 0) var_lst_in=nco_sng_lst_free(var_lst_in,var_lst_in_nbr); 00856 /* Free limits */ 00857 for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]); 00858 if(lmt_nbr > 0) lmt=nco_lmt_lst_free(lmt,lmt_nbr); 00859 /* Free dimension lists */ 00860 if(nbr_dmn_xtr > 0) dim=nco_dmn_lst_free(dim,nbr_dmn_xtr); 00861 if(nbr_dmn_xtr > 0) dmn_out=nco_dmn_lst_free(dmn_out,nbr_dmn_xtr); 00862 /* Free variable lists */ 00863 if(nbr_xtr > 0) var=nco_var_lst_free(var,nbr_xtr); 00864 if(nbr_xtr > 0) var_out=nco_var_lst_free(var_out,nbr_xtr); 00865 var_prc=(var_sct **)nco_free(var_prc); 00866 var_prc_out=(var_sct **)nco_free(var_prc_out); 00867 var_fix=(var_sct **)nco_free(var_fix); 00868 var_fix_out=(var_sct **)nco_free(var_fix_out); 00869 00870 nco_exit_gracefully(); 00871 return EXIT_SUCCESS; 00872 } /* end main() */
|
1.4.4