nco/ncpdq.c File Reference

#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)


Define Documentation

#define MAIN_PROGRAM_FILE
 

Definition at line 64 of file ncpdq.c.


Function Documentation

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() */


Generated on Thu Mar 16 18:16:49 2006 for nco by  doxygen 1.4.4