nco/ncra.c File Reference

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "nco_getopt.h"
#include <netcdf.h>
#include "libnco.h"

Include dependency graph for ncra.c:

Go to the source code of this file.

Defines

#define gettext(foo)   foo
#define MAIN_PROGRAM_FILE

Functions

int main (int argc, char **argv)


Define Documentation

#define gettext foo   )     foo
 

Definition at line 78 of file ncra.c.

#define MAIN_PROGRAM_FILE
 

Definition at line 86 of file ncra.c.


Function Documentation

int main int  argc,
char **  argv
 

Definition at line 90 of file ncra.c.

References arm_base_time_get(), arm_inq(), var_sct_tag::cnt, copyright_prn(), ptr_unn::dp, var_sct_tag::end, lmt_sct::end, EXIT_FAILURE, EXIT_SUCCESS, False, FILE, getopt_long, gettext, var_sct_tag::has_mss_val, int_CEWI, var_sct_tag::is_crd_var, lmt_sct::is_usr_spc_max, lmt_sct::is_usr_spc_min, lmt_dmn_idx, lmt_sct::lmt_typ, lst_prs_2D(), lmt_sct::max_idx, lmt_sct::min_idx, option::name, var_sct_tag::nbr_dim, NC_FORMAT_64BIT, NC_FORMAT_CLASSIC, NC_FORMAT_NETCDF4, NC_GLOBAL, NC_MAX_DIMS, NC_NOERR, NC_NOFILL, NC_NOWRITE, ncea, nco_arm_time_install(), nco_att_cpy(), nco_bool, nco_close(), nco_cmd_ln_sng(), nco_cnv_ccm_ccsm_cf_date(), nco_cnv_ccm_ccsm_cf_inq(), nco_cnv_mss_val_typ(), nco_create_mode_prs(), nco_dmn_dfn(), nco_dmn_dpl(), nco_dmn_fll(), nco_dmn_lmt_mrg(), nco_dmn_lst_ass_var(), nco_dmn_lst_free(), nco_dmn_xrf(), nco_enddef(), nco_exit(), nco_exit_gracefully(), nco_fl_cmp_err_chk(), nco_fl_lst_att_cat(), 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_int_CEWI, nco_lbr_vrs_prn(), nco_lmt_evl(), nco_lmt_free(), nco_lmt_lst_free(), nco_lmt_prs(), nco_lmt_sct_mk(), nco_lst_comma2hash(), nco_lst_srt_nm_id(), nco_malloc(), nco_nm_id_lst_free(), nco_op_avg, nco_op_avgsqr, nco_op_max, nco_op_min, nco_op_rms, nco_op_rmssdn, nco_op_sqravg, nco_op_sqrt, nco_op_ttl, nco_op_typ_get(), nco_open(), nco_openmp_ini(), nco_opr_drv(), nco_pck_map_nil, nco_pck_plc_all_new_att, nco_pck_plc_get(), nco_pck_plc_nil, nco_put_var1(), nco_put_var_pck(), nco_put_vara(), NCO_REC_DMN_UNDEFINED, nco_set_fill(), nco_sng_lst_free(), nco_thr_att_cat(), nco_typ_cnv_rth(), nco_typ_lng(), nco_usg_prn(), nco_var_cnf_typ(), nco_var_dfn(), 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_mlt(), nco_var_mtd_refresh(), nco_var_nrm(), nco_var_nrm_sdn(), nco_var_prc_crr_prn(), nco_var_sqrt(), nco_var_srt_zero(), nco_var_val_cpy(), nco_var_zero(), nco_xrf_dmn(), nco_xrf_var(), nco_zero_long(), ncra, ncrcat, no_argument, NULL_CEWI, omp_get_thread_num(), optarg, optind, prg_nm_get(), prg_prs(), rec_crd_chk(), required_argument, lmt_sct::srd, var_sct_tag::srt, lmt_sct::srt, var_sct_tag::sz, var_sct_tag::sz_rec, var_sct_tag::tally, True, var_sct_tag::typ_upk, var_sct_tag::type, type, option::val, var_sct_tag::val, and ptr_unn::vp.

00091 {
00092   nco_bool CNV_ARM=int_CEWI;
00093   nco_bool CNV_CCM_CCSM_CF=int_CEWI;
00094   nco_bool EXCLUDE_INPUT_LIST=False; /* Option c */
00095   nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */
00096   nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */
00097   nco_bool FILE_RETRIEVED_FROM_REMOTE_LOCATION;
00098   nco_bool FL_LST_IN_APPEND=True; /* Option H */
00099   nco_bool FL_LST_IN_FROM_STDIN=False; /* [flg] fl_lst_in comes from stdin */
00100   nco_bool FORCE_APPEND=False; /* Option A */
00101   nco_bool FORCE_OVERWRITE=False; /* Option O */
00102   nco_bool FORTRAN_IDX_CNV=False; /* Option F */
00103   nco_bool HISTORY_APPEND=True; /* Option h */
00104   nco_bool LAST_RECORD=False;
00105   nco_bool REMOVE_REMOTE_FILES_AFTER_PROCESSING=True; /* Option R */
00106 
00107   char **fl_lst_abb=NULL; /* Option n */
00108   char **fl_lst_in;
00109   char **var_lst_in=NULL_CEWI;
00110   char *cmd_ln;
00111   char *fl_in=NULL;
00112   char *fl_out=NULL; /* Option o */
00113   char *fl_out_tmp=NULL_CEWI;
00114   char *fl_pth=NULL; /* Option p */
00115   char *fl_pth_lcl=NULL; /* Option l */
00116   char *lmt_arg[NC_MAX_DIMS];
00117   char *nco_op_typ_sng=NULL_CEWI; /* [sng] Operation type Option y */
00118   char *nco_pck_plc_sng=NULL_CEWI; /* [sng] Packing policy Option P */
00119   char *opt_crr=NULL; /* [sng] String representation of current long-option name */
00120   char *optarg_lcl=NULL; /* [sng] Local copy of system optarg */
00121   char *time_bfr_srt;
00122   
00123   const char * const CVS_Id="$Id: ncra.c,v 1.176 2006/02/26 07:41:55 zender Exp $"; 
00124   const char * const CVS_Revision="$Revision: 1.176 $";
00125   const char * const opt_sht_lst="4ACcD:d:FHhl:n:Oo:p:P:rRt:v:xY:y:-:";
00126 
00127   dmn_sct **dim;
00128   dmn_sct **dmn_out;
00129   
00130   extern char *optarg;
00131   extern int optind;
00132 
00133   /* Using naked stdin/stdout/stderr in parallel region generates warning
00134      Copy appropriate filehandle to variable scoped shared in parallel clause */
00135   FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */
00136   FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */
00137 
00138   int *in_id_arr;
00139 
00140   int abb_arg_nbr=0;
00141   int fl_idx;
00142   int fl_nbr=0;
00143   int fl_out_fmt=NC_FORMAT_CLASSIC; /* [enm] Output file format */
00144   int fll_md_old; /* [enm] Old fill mode */
00145   int idx=int_CEWI;
00146   int in_id;
00147   int lmt_nbr=0; /* Option d. NB: lmt_nbr gets incremented */
00148   int nbr_dmn_fl;
00149   int nbr_dmn_xtr;
00150   int nbr_var_fix; /* nbr_var_fix gets incremented */
00151   int nbr_var_fl;
00152   int nbr_var_prc; /* nbr_var_prc gets incremented */
00153   int nbr_xtr=0; /* nbr_xtr won't otherwise be set for -c with no -v */
00154   int nco_op_typ=nco_op_avg; /* [enm] Default operation is averaging */
00155   int nco_pck_plc=nco_pck_plc_nil; /* [enm] Default packing is none */
00156   int opt;
00157   int out_id;  
00158   int rcd=NC_NOERR; /* [rcd] Return code */
00159   int rec_dmn_id=NCO_REC_DMN_UNDEFINED;
00160   int thr_idx; /* [idx] Index of current thread */
00161   int thr_nbr=int_CEWI; /* [nbr] Thread number Option t */
00162   int var_lst_in_nbr=0;
00163   
00164   lmt_sct **lmt=NULL_CEWI;
00165   lmt_sct *lmt_rec=NULL_CEWI;
00166   
00167   long idx_rec; /* [idx] Index of current record in current input file */
00168   long idx_rec_out=0L; /* [idx] Index of current record in output file (0 is first, ...) */
00169   
00170   nco_int base_time_srt=nco_int_CEWI;
00171   nco_int base_time_crr=nco_int_CEWI;
00172 
00173   nm_id_sct *dmn_lst;
00174   nm_id_sct *xtr_lst=NULL; /* xtr_lst may be alloc()'d from NULL with -c option */
00175   
00176   time_t time_crr_time_t;
00177   
00178   var_sct **var;
00179   var_sct **var_fix;
00180   var_sct **var_fix_out;
00181   var_sct **var_out=NULL_CEWI;
00182   var_sct **var_prc;
00183   var_sct **var_prc_out;
00184   
00185   static struct option opt_lng[]=
00186     { /* Structure ordered by short option key if possible */
00187       /* Long options with no argument, no short option counterpart */
00188       /* Long options with argument, no short option counterpart */
00189       {"fl_fmt",required_argument,0,0},
00190       {"file_format",required_argument,0,0},
00191       /* Long options with short counterparts */
00192       {"4",no_argument,0,'4'},
00193       {"64bit",no_argument,0,'4'},
00194       {"netcdf4",no_argument,0,'4'},
00195       {"append",no_argument,0,'A'},
00196       {"coords",no_argument,0,'c'},
00197       {"crd",no_argument,0,'c'},
00198       {"no-coords",no_argument,0,'C'},
00199       {"no-crd",no_argument,0,'C'},
00200       {"debug",required_argument,0,'D'},
00201       {"dbg_lvl",required_argument,0,'D'},
00202       {"dimension",required_argument,0,'d'},
00203       {"dmn",required_argument,0,'d'},
00204       {"fortran",no_argument,0,'F'},
00205       {"ftn",no_argument,0,'F'},
00206       {"fl_lst_in",no_argument,0,'H'},
00207       {"file_list",no_argument,0,'H'},
00208       {"history",no_argument,0,'h'},
00209       {"hst",no_argument,0,'h'},
00210       {"local",required_argument,0,'l'},
00211       {"lcl",required_argument,0,'l'},
00212       {"nintap",required_argument,0,'n'},
00213       {"overwrite",no_argument,0,'O'},
00214       {"ovr",no_argument,0,'O'},
00215       {"output",required_argument,0,'o'},
00216       {"fl_out",required_argument,0,'o'},
00217       {"path",required_argument,0,'p'},
00218       {"pack",required_argument,0,'P'},
00219       {"retain",no_argument,0,'R'},
00220       {"rtn",no_argument,0,'R'},
00221       {"revision",no_argument,0,'r'},
00222       {"thr_nbr",required_argument,0,'t'},
00223       {"threads",required_argument,0,'t'},
00224       {"omp_num_threads",required_argument,0,'t'},
00225       {"variable",required_argument,0,'v'},
00226       {"version",no_argument,0,'r'},
00227       {"vrs",no_argument,0,'r'},
00228       {"exclude",no_argument,0,'x'},
00229       {"xcl",no_argument,0,'x'},
00230       {"pseudonym",required_argument,0,'Y'},
00231       {"program",required_argument,0,'Y'},
00232       {"prg_nm",required_argument,0,'Y'},
00233       {"math",required_argument,0,'y'},
00234       {"help",no_argument,0,'?'},
00235       {0,0,0,0}
00236     }; /* end opt_lng */
00237   int opt_idx=0; /* Index of current long option into opt_lng array */
00238 
00239 #ifdef _LIBINTL_H
00240   setlocale(LC_ALL,""); /* LC_ALL sets all localization tokens to same value */
00241   bindtextdomain("nco","/home/zender/share/locale"); /* ${LOCALEDIR} is e.g., /usr/share/locale */
00242   /* MO files should be in ${LOCALEDIR}/es/LC_MESSAGES */
00243   textdomain("nco"); /* PACKAGE is name of program */
00244 #endif /* not _LIBINTL_H */
00245 
00246   /* Start clock and save command line */
00247   cmd_ln=nco_cmd_ln_sng(argc,argv);
00248   time_crr_time_t=time((time_t *)NULL);
00249   time_bfr_srt=ctime(&time_crr_time_t); time_bfr_srt=time_bfr_srt; /* Avoid compiler warning until variable is used for something */
00250 #if 0 /* Solaris version of ctime_r() requires three arguments */
00251   ctime_r(&time_crr_time_t,time_bfr_srt); 
00252   time_bfr_srt[24] = '\0'; /* Remove newline */
00253 #endif /* !0 */
00254 
00255   /* Get program name and set program enum (e.g., prg=ncra) */
00256   prg_nm=prg_prs(argv[0],&prg);
00257 
00258   /* Parse command line arguments */
00259   while(1){
00260     /* getopt_long_only() allows one dash to prefix long options */
00261     opt=getopt_long(argc,argv,opt_sht_lst,opt_lng,&opt_idx);
00262     /* NB: access to opt_crr is only valid when long_opt is detected */
00263     if(opt == EOF) break; /* Parse positional arguments once getopt_long() returns EOF */
00264     opt_crr=(char *)strdup(opt_lng[opt_idx].name);
00265 
00266     /* Process long options without short option counterparts */
00267     if(opt == 0){
00268       if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt);
00269     } /* opt != 0 */
00270     /* Process short options */
00271     switch(opt){
00272     case 0: /* Long options have already been processed, return */
00273       break;
00274     case '4': /* [flg] Catch-all to prescribe output storage format */
00275       if(!strcmp(opt_crr,"64bit")) fl_out_fmt=NC_FORMAT_64BIT; else fl_out_fmt=NC_FORMAT_NETCDF4; 
00276       break;
00277     case 'A': /* Toggle FORCE_APPEND */
00278       FORCE_APPEND=!FORCE_APPEND;
00279       break;
00280     case 'C': /* Extract all coordinates associated with extracted variables? */
00281       EXTRACT_ASSOCIATED_COORDINATES=False;
00282       break;
00283     case 'c':
00284       EXTRACT_ALL_COORDINATES=True;
00285       break;
00286     case 'D': /* Debugging level. Default is 0. */
00287       dbg_lvl=(unsigned short)strtol(optarg,(char **)NULL,10);
00288       break;
00289     case 'd': /* Copy argument for later processing */
00290       lmt_arg[lmt_nbr]=(char *)strdup(optarg);
00291       lmt_nbr++;
00292       break;
00293     case 'F': /* Toggle index convention. Default is 0-based arrays (C-style). */
00294       FORTRAN_IDX_CNV=!FORTRAN_IDX_CNV;
00295       break;
00296     case 'H': /* Toggle writing input file list attribute */
00297       FL_LST_IN_APPEND=!FL_LST_IN_APPEND;
00298       break;
00299     case 'h': /* Toggle appending to history global attribute */
00300       HISTORY_APPEND=!HISTORY_APPEND;
00301       break;
00302     case 'l': /* Local path prefix for files retrieved from remote file system */
00303       fl_pth_lcl=(char *)strdup(optarg);
00304       break;
00305     case 'n': /* NINTAP-style abbreviation of files to average */
00306       fl_lst_abb=lst_prs_2D(optarg,",",&abb_arg_nbr);
00307       if(abb_arg_nbr < 1 || abb_arg_nbr > 5){
00308         (void)fprintf(stdout,gettext("%s: ERROR Incorrect abbreviation for file list\n"),prg_nm_get());
00309         (void)nco_usg_prn();
00310         nco_exit(EXIT_FAILURE);
00311       } /* end if */
00312       break;
00313     case 'O': /* Toggle FORCE_OVERWRITE */
00314       FORCE_OVERWRITE=!FORCE_OVERWRITE;
00315       break;
00316     case 'o': /* Name of output file */
00317       fl_out=(char *)strdup(optarg);
00318       break;
00319     case 'p': /* Common file path */
00320       fl_pth=(char *)strdup(optarg);
00321       break;
00322     case 'P': /* Packing policy */
00323       nco_pck_plc_sng=(char *)strdup(optarg);
00324       nco_pck_plc=nco_pck_plc_get(nco_pck_plc_sng);
00325       break;
00326     case 'R': /* Toggle removal of remotely-retrieved-files. Default is True. */
00327       REMOVE_REMOTE_FILES_AFTER_PROCESSING=!REMOVE_REMOTE_FILES_AFTER_PROCESSING;
00328       break;
00329     case 'r': /* Print CVS program information and copyright notice */
00330       (void)copyright_prn(CVS_Id,CVS_Revision);
00331       (void)nco_lbr_vrs_prn();
00332       nco_exit(EXIT_SUCCESS);
00333       break;
00334     case 't': /* Thread number */
00335       thr_nbr=(int)strtol(optarg,(char **)NULL,10);
00336       break;
00337     case 'v': /* Variables to extract/exclude */
00338       /* Replace commas with hashes when within braces (convert back later) */
00339       optarg_lcl=(char *)strdup(optarg);
00340       (void)nco_lst_comma2hash(optarg_lcl);
00341       var_lst_in=lst_prs_2D(optarg_lcl,",",&var_lst_in_nbr);
00342       optarg_lcl=(char *)nco_free(optarg_lcl);
00343       nbr_xtr=var_lst_in_nbr;
00344       break;
00345     case 'x': /* Exclude rather than extract variables specified with -v */
00346       EXCLUDE_INPUT_LIST=True;
00347       break;
00348     case 'Y': /* Pseudonym */
00349       /* Call prg_prs to reset pseudonym */
00350       optarg_lcl=(char *)strdup(optarg);
00351       if(prg_nm != NULL) prg_nm=(char *)nco_free(prg_nm);
00352       prg_nm=prg_prs(optarg_lcl,&prg);
00353       optarg_lcl=(char *)nco_free(optarg_lcl);
00354       break;
00355     case 'y': /* Operation type */
00356       nco_op_typ_sng=(char *)strdup(optarg);
00357       if(prg == ncra || prg == ncea ) nco_op_typ=nco_op_typ_get(nco_op_typ_sng);
00358       break;
00359     case '?': /* Print proper usage */
00360       (void)nco_usg_prn();
00361       nco_exit(EXIT_SUCCESS);
00362       break;
00363     case '-': /* Long options are not allowed */
00364       (void)fprintf(stderr,"%s: ERROR Long options are not available in this build. Use single letter options instead.\n",prg_nm_get());
00365       nco_exit(EXIT_FAILURE);
00366       break;
00367     default: /* Print proper usage */
00368       (void)nco_usg_prn();
00369       nco_exit(EXIT_FAILURE);
00370       break;
00371     } /* end switch */
00372     if(opt_crr != NULL) opt_crr=(char *)nco_free(opt_crr);
00373   } /* end while loop */
00374   
00375   /* Process positional arguments and fill in filenames */
00376   fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN);
00377 
00378   /* Make uniform list of user-specified dimension limits */
00379   if(lmt_nbr > 0) lmt=nco_lmt_prs(lmt_nbr,lmt_arg);
00380   
00381   /* Initialize thread information */
00382   thr_nbr=nco_openmp_ini(thr_nbr);
00383   in_id_arr=(int *)nco_malloc(thr_nbr*sizeof(int));
00384 
00385   /* Parse filename */
00386   fl_in=nco_fl_nm_prs(fl_in,0,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth);
00387   /* Make sure file is on local system and is readable or die trying */
00388   fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION);
00389   /* Open file for reading */
00390   rcd=nco_open(fl_in,NC_NOWRITE,&in_id);
00391   
00392   /* Get number of variables, dimensions, and record dimension ID of input file */
00393   (void)nco_inq(in_id,&nbr_dmn_fl,&nbr_var_fl,(int *)NULL,&rec_dmn_id);
00394   
00395   /* Form initial extraction list which may include extended regular expressions */
00396   xtr_lst=nco_var_lst_mk(in_id,nbr_var_fl,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr);
00397 
00398   /* Change included variables to excluded variables */
00399   if(EXCLUDE_INPUT_LIST) xtr_lst=nco_var_lst_xcl(in_id,nbr_var_fl,xtr_lst,&nbr_xtr);
00400 
00401   /* Add all coordinate variables to extraction list */
00402   if(EXTRACT_ALL_COORDINATES) xtr_lst=nco_var_lst_add_crd(in_id,nbr_dmn_fl,xtr_lst,&nbr_xtr);
00403 
00404   /* Make sure coordinates associated extracted variables are also on extraction list */
00405   if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst=nco_var_lst_ass_crd_add(in_id,xtr_lst,&nbr_xtr);
00406 
00407   /* Sort extraction list by variable ID for fastest I/O */
00408   if(nbr_xtr > 1) xtr_lst=nco_lst_srt_nm_id(xtr_lst,nbr_xtr,False);
00409   
00410   /* We now have final list of variables to extract. Phew. */
00411   
00412   /* Find coordinate/dimension values associated with user-specified limits
00413      NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */
00414   for(idx=0;idx<lmt_nbr;idx++) (void)nco_lmt_evl(in_id,lmt[idx],0L,FORTRAN_IDX_CNV);
00415 
00416   /* Find dimensions associated with variables to be extracted */
00417   dmn_lst=nco_dmn_lst_ass_var(in_id,xtr_lst,nbr_xtr,&nbr_dmn_xtr);
00418 
00419   /* Fill in dimension structure for all extracted dimensions */
00420   dim=(dmn_sct **)nco_malloc(nbr_dmn_xtr*sizeof(dmn_sct *));
00421   for(idx=0;idx<nbr_dmn_xtr;idx++) dim[idx]=nco_dmn_fll(in_id,dmn_lst[idx].id,dmn_lst[idx].nm);
00422   /* Dimension list no longer needed */
00423   dmn_lst=nco_nm_id_lst_free(dmn_lst,nbr_dmn_xtr);
00424   
00425   /* Merge hyperslab limit information into dimension structures */
00426   if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim,nbr_dmn_xtr,lmt,lmt_nbr);
00427 
00428   /* Duplicate input dimension structures for output dimension structures */
00429   dmn_out=(dmn_sct **)nco_malloc(nbr_dmn_xtr*sizeof(dmn_sct *));
00430   for(idx=0;idx<nbr_dmn_xtr;idx++){
00431     dmn_out[idx]=nco_dmn_dpl(dim[idx]);
00432     (void)nco_dmn_xrf(dim[idx],dmn_out[idx]); 
00433   } /* end loop over idx */
00434 
00435   /* Create stand-alone limit structure just for record dimension */
00436   if(prg == ncra || prg == ncrcat){
00437     if(rec_dmn_id == NCO_REC_DMN_UNDEFINED){
00438       (void)fprintf(stdout,gettext("%s: ERROR input file %s lacks a record dimension\n"),prg_nm_get(),fl_in);
00439       if(fl_nbr == 1)(void)fprintf(stdout,gettext("%s: HINT Use ncks instead of %s\n"),prg_nm_get(),prg_nm_get());
00440       nco_exit(EXIT_FAILURE);
00441     } /* endif */
00442     lmt_rec=nco_lmt_sct_mk(in_id,rec_dmn_id,lmt,lmt_nbr,FORTRAN_IDX_CNV);
00443   } /* endif */
00444 
00445   /* Is this an CCM/CCSM/CF-format history tape? */
00446   CNV_CCM_CCSM_CF=nco_cnv_ccm_ccsm_cf_inq(in_id);
00447 
00448   /* Is this an ARM-format data file? */
00449   CNV_ARM=arm_inq(in_id);
00450   /* NB: arm_base_time_get() with same nc_id contains OpenMP critical region */
00451   if(CNV_ARM) base_time_srt=arm_base_time_get(in_id);
00452 
00453   /* Fill in variable structure list for all extracted variables */
00454   var=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *));
00455   var_out=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *));
00456   for(idx=0;idx<nbr_xtr;idx++){
00457     var[idx]=nco_var_fll(in_id,xtr_lst[idx].id,xtr_lst[idx].nm,dim,nbr_dmn_xtr);
00458     var_out[idx]=nco_var_dpl(var[idx]);
00459     (void)nco_xrf_var(var[idx],var_out[idx]);
00460     (void)nco_xrf_dmn(var_out[idx]);
00461   } /* end loop over idx */
00462   /* Extraction list no longer needed */
00463   xtr_lst=nco_nm_id_lst_free(xtr_lst,nbr_xtr);
00464 
00465   /* Divide variable lists into lists of fixed variables and variables to be processed */
00466   (void)nco_var_lst_dvd(var,var_out,nbr_xtr,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,NULL,0,&var_fix,&var_fix_out,&nbr_var_fix,&var_prc,&var_prc_out,&nbr_var_prc);
00467 
00468   /* Open output file */
00469   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&out_id);
00470 
00471   /* Copy global attributes */
00472   (void)nco_att_cpy(in_id,out_id,NC_GLOBAL,NC_GLOBAL,True);
00473   
00474   /* Catenate time-stamped command line to "history" global attribute */
00475   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
00476 
00477   /* Add input file list global attribute */
00478   if(FL_LST_IN_APPEND && HISTORY_APPEND && FL_LST_IN_FROM_STDIN) (void)nco_fl_lst_att_cat(out_id,fl_lst_in,fl_nbr);
00479 
00480   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
00481   
00482   /* Define dimensions in output file */
00483   (void)nco_dmn_dfn(fl_out,out_id,dmn_out,nbr_dmn_xtr);
00484 
00485   /* Define variables in output file, copy their attributes */
00486   (void)nco_var_dfn(in_id,fl_out,out_id,var_out,nbr_xtr,(dmn_sct **)NULL,(int)0,nco_pck_plc_nil,nco_pck_map_nil);
00487 
00488   /* Turn off default filling behavior to enhance efficiency */
00489   (void)nco_set_fill(out_id,NC_NOFILL,&fll_md_old);
00490   
00491   /* Take output file out of define mode */
00492   (void)nco_enddef(out_id);
00493   
00494   /* Zero start vectors for all output variables */
00495   (void)nco_var_srt_zero(var_out,nbr_xtr);
00496 
00497   /* Copy variable data for non-processed variables */
00498   (void)nco_var_val_cpy(in_id,out_id,var_fix,nbr_var_fix);
00499 
00500   /* Close first input netCDF file */
00501   (void)nco_close(in_id);
00502   
00503   /* Allocate and, if necesssary, initialize accumulation space for processed variables */
00504   for(idx=0;idx<nbr_var_prc;idx++){
00505     if(prg == ncra || prg == ncrcat){
00506       /* Allocate space for only one record */
00507       var_prc_out[idx]->sz=var_prc[idx]->sz=var_prc[idx]->sz_rec;
00508     } /* endif */
00509     if(prg == ncra || prg == ncea){
00510       var_prc_out[idx]->tally=var_prc[idx]->tally=(long *)nco_malloc(var_prc_out[idx]->sz*sizeof(long));
00511       (void)nco_zero_long(var_prc_out[idx]->sz,var_prc_out[idx]->tally);
00512       var_prc_out[idx]->val.vp=(void *)nco_malloc(var_prc_out[idx]->sz*nco_typ_lng(var_prc_out[idx]->type));
00513       (void)nco_var_zero(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->val);
00514     } /* end if */
00515   } /* end loop over idx */
00516   
00517   /* Loop over input files */
00518   for(fl_idx=0;fl_idx<fl_nbr;fl_idx++){
00519     /* Parse filename */
00520     if(fl_idx != 0) fl_in=nco_fl_nm_prs(fl_in,fl_idx,(int *)NULL,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth);
00521     if(dbg_lvl > 0) (void)fprintf(stderr,gettext("\nInput file %d is %s; "),fl_idx,fl_in);
00522     /* Make sure file is on local system and is readable or die trying */
00523     if(fl_idx != 0) fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION);
00524     if(dbg_lvl > 0) (void)fprintf(stderr,gettext("local file %s:\n"),fl_in);
00525 
00526     /* Open file once per thread to improve caching */
00527     for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in,NC_NOWRITE,in_id_arr+thr_idx);
00528     in_id=in_id_arr[0];
00529     
00530     /* Variables may have different ID, missing_value, type, in each file */
00531     for(idx=0;idx<nbr_var_prc;idx++) (void)nco_var_mtd_refresh(in_id,var_prc[idx]);
00532     
00533     /* Each file can have a different number of records to process
00534        NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */
00535     if(prg == ncra || prg == ncrcat) (void)nco_lmt_evl(in_id,lmt_rec,idx_rec_out,FORTRAN_IDX_CNV);
00536     
00537     /* NB: arm_base_time_get() with same nc_id contains OpenMP critical region */
00538     if(CNV_ARM) base_time_crr=arm_base_time_get(in_id);
00539     
00540     /* Perform various error-checks on input file */
00541     if(False) (void)nco_fl_cmp_err_chk();
00542     
00543     if(prg == ncra || prg == ncrcat){ /* ncea jumps to else branch */
00544       /* Loop over each record in current file */
00545         
00546       if(lmt_rec->srt > lmt_rec->end) (void)fprintf(fp_stdout,gettext("%s: WARNING %s (input file %d) is superfluous\n"),prg_nm_get(),fl_in,fl_idx);
00547         
00548       for(idx_rec=lmt_rec->srt;idx_rec<=lmt_rec->end;idx_rec+=lmt_rec->srd){
00549         if(fl_idx == fl_nbr-1 && idx_rec >= 1L+lmt_rec->end-lmt_rec->srd) LAST_RECORD=True;
00550         /* Process all variables in current record */
00551         if(dbg_lvl > 1) (void)fprintf(fp_stderr,gettext("Record %ld of %s is input record %ld\n"),idx_rec,fl_in,idx_rec_out);
00552 #ifdef _OPENMP
00553 #pragma omp parallel for default(none) private(idx,in_id) shared(CNV_ARM,base_time_crr,base_time_srt,dbg_lvl,fl_in,fl_out,fp_stderr,idx_rec,idx_rec_out,in_id_arr,LAST_RECORD,nbr_var_prc,nco_op_typ,out_id,prg,rcd,var_prc,var_prc_out)
00554 #endif /* !_OPENMP */
00555           for(idx=0;idx<nbr_var_prc;idx++){
00556             in_id=in_id_arr[omp_get_thread_num()];
00557             if(dbg_lvl > 2) rcd+=nco_var_prc_crr_prn(idx,var_prc[idx]->nm);
00558             if(dbg_lvl > 0) (void)fflush(fp_stderr);
00559             /* Update hyperslab start indices to current record for each variable */
00560             var_prc[idx]->srt[0]=idx_rec;
00561             var_prc[idx]->end[0]=idx_rec;
00562             var_prc[idx]->cnt[0]=1L;
00563             /* Retrieve variable from disk into memory */
00564             /* NB: nco_var_get() with same nc_id contains OpenMP critical region */
00565             (void)nco_var_get(in_id,var_prc[idx]);
00566             
00567             if(prg == ncra){
00568               /* Convert char, short, long, int types to doubles before arithmetic
00569                  Output variable type is "sticky" so only convert on first record */
00570               if(idx_rec_out == 0) var_prc_out[idx]=nco_typ_cnv_rth(var_prc_out[idx],nco_op_typ);
00571               var_prc[idx]=nco_var_cnf_typ(var_prc_out[idx]->type,var_prc[idx]);
00572               /* Perform arithmetic operations: avg, min, max, ttl, ... */
00573               nco_opr_drv(idx_rec_out,nco_op_typ,var_prc[idx],var_prc_out[idx]);
00574             } /* end if ncra */
00575             
00576             /* Append current record to output file */
00577             if(prg == ncrcat){
00578               var_prc_out[idx]->srt[0]=var_prc_out[idx]->end[0]=idx_rec_out;
00579               var_prc_out[idx]->cnt[0]=1L;
00580               /* Replace this time_offset value with time_offset from initial file base_time */
00581               if(CNV_ARM && !strcmp(var_prc[idx]->nm,"time_offset")) var_prc[idx]->val.dp[0]+=(base_time_crr-base_time_srt);
00582 #ifdef _OPENMP
00583 #pragma omp critical
00584 #endif /* _OPENMP */
00585               if(var_prc_out[idx]->sz_rec > 1) (void)nco_put_vara(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc[idx]->val.vp,var_prc_out[idx]->type); else (void)nco_put_var1(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc[idx]->val.vp,var_prc_out[idx]->type);
00586             } /* end if ncrcat */
00587             
00588             /* Warn if record coordinate, if any, is not monotonic */
00589             if(prg == ncrcat && var_prc[idx]->is_crd_var) (void)rec_crd_chk(var_prc[idx],fl_in,fl_out,idx_rec,idx_rec_out);
00590             /* Convert missing_value, if any, back to unpacked type
00591                Otherwise missing_value will be double-promoted when next record read 
00592                Do not convert after last record otherwise normalization fails 
00593                due to wrong missing_value type (needs promoted type, not unpacked type) */
00594             if(var_prc[idx]->has_mss_val && var_prc[idx]->type != var_prc[idx]->typ_upk && !LAST_RECORD) var_prc[idx]=nco_cnv_mss_val_typ(var_prc[idx],var_prc[idx]->typ_upk);
00595             /* Free current input buffer */
00596             var_prc[idx]->val.vp=nco_free(var_prc[idx]->val.vp);
00597           } /* end (OpenMP parallel for) loop over variables */
00598           idx_rec_out++; /* [idx] Index of current record in output file (0 is first, ...) */
00599           if(dbg_lvl > 2) (void)fprintf(fp_stderr,"\n");
00600         } /* end loop over idx_rec */
00601         /* Warn if fewer than number of requested records were read and final file has been processed */
00602         if(lmt_rec->lmt_typ == lmt_dmn_idx && lmt_rec->is_usr_spc_min && lmt_rec->is_usr_spc_max){
00603           long rec_nbr_rqs; /* Number of records user requested */
00604           rec_nbr_rqs=1L+(lmt_rec->max_idx-lmt_rec->min_idx)/lmt_rec->srd;
00605           if(fl_idx == fl_nbr-1 && rec_nbr_rqs != idx_rec_out) (void)fprintf(fp_stdout,gettext("%s: WARNING User requested %li records but only %li were found\n"),prg_nm_get(),rec_nbr_rqs,idx_rec_out);
00606         } /* end if */
00607         /* Error if no records were read and final file has been processed */
00608         if(idx_rec_out <= 0 && fl_idx == fl_nbr-1){
00609           (void)fprintf(fp_stdout,gettext("%s: ERROR No records lay within specified hyperslab\n"),prg_nm_get());
00610           nco_exit(EXIT_FAILURE);
00611         } /* end if */
00612         /* End of ncra, ncrcat section */
00613       }else{ /* ncea */
00614 #ifdef _OPENMP
00615 #pragma omp parallel for default(none) private(idx,in_id) shared(dbg_lvl,fl_idx,fp_stderr,in_id_arr,nbr_var_prc,nco_op_typ,rcd,var_prc,var_prc_out)
00616 #endif /* !_OPENMP */
00617         for(idx=0;idx<nbr_var_prc;idx++){ /* Process all variables in current file */
00618           in_id=in_id_arr[omp_get_thread_num()];
00619           if(dbg_lvl > 0) rcd+=nco_var_prc_crr_prn(idx,var_prc[idx]->nm);
00620           if(dbg_lvl > 0) (void)fflush(fp_stderr);
00621           /* Retrieve variable from disk into memory */
00622           (void)nco_var_get(in_id,var_prc[idx]);
00623           
00624           /* Convert char, short, long, int types to doubles before arithmetic
00625              Output variable type is "sticky" so only convert on first record */
00626           if(fl_idx == 0) var_prc_out[idx]=nco_typ_cnv_rth(var_prc_out[idx],nco_op_typ);
00627           var_prc[idx]=nco_var_cnf_typ(var_prc_out[idx]->type,var_prc[idx]);
00628           /* Perform arithmetic operations: avg, min, max, ttl, ... */ /* Note: fl_idx not idx_rec_out! */
00629           nco_opr_drv(fl_idx,nco_op_typ,var_prc[idx],var_prc_out[idx]);
00630           
00631           /* Free current input buffer */
00632           var_prc[idx]->val.vp=nco_free(var_prc[idx]->val.vp);
00633         } /* end (OpenMP parallel for) loop over idx */
00634       } /* end else ncea */
00635       
00636       if(dbg_lvl > 1) (void)fprintf(fp_stderr,"\n");
00637       
00638       /* Close input netCDF file */
00639       for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_arr[thr_idx]);
00640 
00641     /* Dispose local copy of file */
00642     if(FILE_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in);
00643     
00644   } /* end loop over fl_idx */
00645   
00646   /* Normalize, multiply, etc where necessary */
00647   if(prg == ncra || prg == ncea){
00648 #ifdef _OPENMP
00649 #pragma omp parallel for default(none) private(idx) shared(nbr_var_prc,nco_op_typ,var_prc,var_prc_out)
00650 #endif /* !_OPENMP */
00651     for(idx=0;idx<nbr_var_prc;idx++){
00652       switch(nco_op_typ) {
00653       case nco_op_avg: /* Normalize sum by tally to create mean */
00654       case nco_op_sqrt: /* Normalize sum by tally to create mean */
00655       case nco_op_sqravg: /* Normalize sum by tally to create mean */
00656       case nco_op_rms: /* Normalize sum of squares by tally to create mean square */
00657       case nco_op_avgsqr: /* Normalize sum of squares by tally to create mean square */
00658         (void)nco_var_nrm(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->tally,var_prc_out[idx]->val);
00659         break;
00660       case nco_op_rmssdn: /* Normalize sum of squares by tally-1 to create mean square for sdn */
00661         (void)nco_var_nrm_sdn(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->tally,var_prc_out[idx]->val);
00662         break;
00663       case nco_op_min: /* Minimum is already in buffer, do nothing */
00664       case nco_op_max: /* Maximum is already in buffer, do nothing */
00665       case nco_op_ttl: /* Total is already in buffer, do nothing */
00666       default:
00667         break;
00668       } /* end switch */
00669       /* Some operations require additional processing */
00670       switch(nco_op_typ) {
00671       case nco_op_rms: /* Take root of mean of sum of squares to create root mean square */
00672       case nco_op_rmssdn: /* Take root of sdn mean of sum of squares to create root mean square for sdn */
00673       case nco_op_sqrt: /* Take root of mean to create root mean */
00674         (void)nco_var_sqrt(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->tally,var_prc_out[idx]->val,var_prc_out[idx]->val);
00675         break;
00676       case nco_op_sqravg: /* Square mean to create square of the mean (for sdn) */
00677         (void)nco_var_mlt(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val,var_prc_out[idx]->val);
00678         break;
00679       default:
00680         break;
00681       } /* end switch */
00682       var_prc_out[idx]->tally=var_prc[idx]->tally=(long *)nco_free(var_prc[idx]->tally);
00683     } /* end (OpenMP parallel for) loop over variables */
00684   } /* end if */
00685   
00686   /* Manually fix YYMMDD date which was mangled by averaging */
00687   if(CNV_CCM_CCSM_CF && prg == ncra) (void)nco_cnv_ccm_ccsm_cf_date(out_id,var_out,nbr_xtr);
00688   
00689   /* Add time variable to output file
00690      NB: arm_time_install() contains OpenMP critical region */
00691   if(CNV_ARM && prg == ncrcat) (void)nco_arm_time_install(out_id,base_time_srt);
00692   
00693   /* Copy averages to output file and free averaging buffers */
00694   if(prg == ncra || prg == ncea){
00695     for(idx=0;idx<nbr_var_prc;idx++){
00696       /* Revert any arithmetic promotion but leave unpacking (for now) */
00697       var_prc_out[idx]=nco_var_cnf_typ(var_prc_out[idx]->typ_upk,var_prc_out[idx]);
00698       /* Packing/Unpacking */
00699       if(nco_pck_plc == nco_pck_plc_all_new_att) var_prc_out[idx]=nco_put_var_pck(out_id,var_prc_out[idx],nco_pck_plc);
00700       if(var_prc_out[idx]->nbr_dim == 0){
00701         (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);
00702       }else{ /* end if variable is a scalar */
00703         /* Size of record dimension is 1 in output file */
00704         if(prg == ncra) var_prc_out[idx]->cnt[0]=1L;
00705         (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);
00706       } /* end if variable is an array */
00707       var_prc_out[idx]->val.vp=nco_free(var_prc_out[idx]->val.vp);
00708     } /* end loop over idx */
00709   } /* end if */
00710   
00711   /* Close output file and move it from temporary to permanent location */
00712   (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id);
00713   
00714   /* ncra-specific memory cleanup */
00715   if(prg == ncra || prg == ncrcat) lmt_rec=nco_lmt_free(lmt_rec);
00716   
00717   /* NCO-generic clean-up */
00718   /* Free individual strings/arrays */
00719   if(cmd_ln != NULL) cmd_ln=(char *)nco_free(cmd_ln);
00720   if(fl_in != NULL) fl_in=(char *)nco_free(fl_in);
00721   if(fl_out != NULL) fl_out=(char *)nco_free(fl_out);
00722   if(fl_out_tmp != NULL) fl_out_tmp=(char *)nco_free(fl_out_tmp);
00723   if(fl_pth != NULL) fl_pth=(char *)nco_free(fl_pth);
00724   if(fl_pth_lcl != NULL) fl_pth_lcl=(char *)nco_free(fl_pth_lcl);
00725   if(in_id_arr != NULL) in_id_arr=(int *)nco_free(in_id_arr);
00726   /* Free lists of strings */
00727   if(fl_lst_in != NULL && fl_lst_abb == NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,fl_nbr); 
00728   if(fl_lst_in != NULL && fl_lst_abb != NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,1);
00729   if(fl_lst_abb != NULL) fl_lst_abb=nco_sng_lst_free(fl_lst_abb,abb_arg_nbr);
00730   if(var_lst_in_nbr > 0) var_lst_in=nco_sng_lst_free(var_lst_in,var_lst_in_nbr);
00731   /* Free limits */
00732   for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]);
00733   if(lmt_nbr > 0) lmt=nco_lmt_lst_free(lmt,lmt_nbr);
00734   /* Free dimension lists */
00735   if(nbr_dmn_xtr > 0) dim=nco_dmn_lst_free(dim,nbr_dmn_xtr);
00736   if(nbr_dmn_xtr > 0) dmn_out=nco_dmn_lst_free(dmn_out,nbr_dmn_xtr);
00737   /* Free variable lists */
00738   if(nbr_xtr > 0) var=nco_var_lst_free(var,nbr_xtr);
00739   if(nbr_xtr > 0) var_out=nco_var_lst_free(var_out,nbr_xtr);
00740   var_prc=(var_sct **)nco_free(var_prc);
00741   var_prc_out=(var_sct **)nco_free(var_prc_out);
00742   var_fix=(var_sct **)nco_free(var_fix);
00743   var_fix_out=(var_sct **)nco_free(var_fix_out);
00744   
00745   nco_exit_gracefully();
00746   return EXIT_SUCCESS;
00747 } /* end main() */


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