nco/ncwa.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 "ncap.h"
#include "libnco.h"

Include dependency graph for ncwa.c:

Go to the source code of this file.

Defines

#define MAIN_PROGRAM_FILE

Functions

int main (int argc, char **argv)

Variables

size_t ncap_ncl_dpt_crr = 0UL
size_t * ncap_ln_nbr_crr
char ** ncap_fl_spt_glb


Define Documentation

#define MAIN_PROGRAM_FILE
 

Definition at line 66 of file ncwa.c.


Function Documentation

int main int  argc,
char **  argv
 

Definition at line 76 of file ncwa.c.

References prs_sct::att_lst, ptr_unn::bp, copyright_prn(), ptr_unn::cp, prs_sct::dmn_in, prs_sct::dmn_out, double_CEWI, ptr_unn::dp, EXIT_FAILURE, EXIT_SUCCESS, False, FILE, prs_sct::fl_in, prs_sct::fl_out, ptr_unn::fp, getopt_long, var_sct_tag::has_mss_val, dmn_sct_tag::id, prs_sct::in_id, int_CEWI, var_sct_tag::is_crd_var, ptr_unn::lp, lst_prs_2D(), var_sct_tag::mss_val, option::name, prs_sct::nbr_att, var_sct_tag::nbr_dim, prs_sct::nbr_dmn_in, prs_sct::nbr_dmn_out, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_FORMAT_64BIT, NC_FORMAT_CLASSIC, NC_FORMAT_NETCDF4, NC_GLOBAL, NC_INT, NC_MAX_DIMS, NC_NOERR, NC_NOFILL, NC_NOWRITE, NC_SHORT, ncap_ln_nbr_crr, ncap_ncl_dpt_crr, ncap_ncwa_scn(), nco_att_cpy(), nco_bool, nco_close(), nco_cmd_ln_sng(), nco_cnv_ccm_ccsm_cf_inq(), nco_create_mode_prs(), nco_dfl_case_nc_type_err(), 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_cmp_err_chk(), nco_fl_lst_mk(), nco_fl_mk_lcl(), nco_fl_nm_prs(), nco_fl_out_cls(), nco_fl_out_open(), nco_fl_rm(), nco_free(), nco_hst_att_cat(), nco_inq(), nco_inq_varid(), 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_mss_val_cp(), nco_mss_val_mk(), nco_nm_id_lst_free(), nco_op_avg, nco_op_avgsqr, nco_op_max, nco_op_min, nco_op_ne, nco_op_nil, nco_op_prs_rlt(), nco_op_rms, nco_op_rmssdn, nco_op_sqravg, nco_op_sqrt, nco_op_ttl, prs_sct::nco_op_typ, nco_op_typ_get(), nco_open(), nco_openmp_ini(), nco_pck_map_nil, nco_pck_plc_nil, nco_put_att(), nco_put_var1(), nco_put_vara(), nco_realloc(), 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_avg(), nco_var_cnf_dmn(), nco_var_cnf_typ(), nco_var_dfn(), nco_var_dpl(), nco_var_dvd(), nco_var_fll(), nco_var_free(), 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_msk(), 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(), var_sct_tag::nm, no_argument, prs_sct::ntl_scn, NULL_CEWI, omp_get_thread_num(), optarg, optind, prs_sct::out_id, prg_nm_get(), prg_prs(), required_argument, ptr_unn::sp, prs_sct::sym_tbl, prs_sct::sym_tbl_nbr, var_sct_tag::sz, var_sct_tag::tally, True, var_sct_tag::type, type, option::val, var_sct_tag::val, prs_sct::var_LHS, and ptr_unn::vp.

00077 {
00078   nco_bool DO_CONFORM_MSK=False; /* Did nco_var_cnf_dmn() find truly conforming mask? */
00079   nco_bool DO_CONFORM_WGT=False; /* Did nco_var_cnf_dmn() find truly conforming weight? */
00080   nco_bool EXCLUDE_INPUT_LIST=False; /* Option c */
00081   nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */
00082   nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */
00083   nco_bool FILE_RETRIEVED_FROM_REMOTE_LOCATION;
00084   nco_bool FL_LST_IN_FROM_STDIN=False; /* [flg] fl_lst_in comes from stdin */
00085   nco_bool FORCE_APPEND=False; /* Option A */
00086   nco_bool FORCE_OVERWRITE=False; /* Option O */
00087   nco_bool FORTRAN_IDX_CNV=False; /* Option F */
00088   nco_bool HISTORY_APPEND=True; /* Option h */
00089   nco_bool MULTIPLY_BY_TALLY=False; /* Not currently implemented */
00090   nco_bool MUST_CONFORM=False; /* [flg] Must nco_var_cnf_dmn() find truly conforming variables? */
00091   nco_bool CNV_CCM_CCSM_CF;
00092   nco_bool NORMALIZE_BY_TALLY=True; /* Not currently implemented */
00093   nco_bool NORMALIZE_BY_WEIGHT=True; /* Not currently implemented */
00094   nco_bool NRM_BY_DNM=True; /* Option N Normalize by denominator */
00095   nco_bool REMOVE_REMOTE_FILES_AFTER_PROCESSING=True; /* Option R */
00096   nco_bool WGT_MSK_CRD_VAR=True; /* [flg] Weight and/or mask coordinate variables */
00097   nco_bool opt_a_flg=False; /* Option a */
00098 
00099   char **dmn_avg_lst_in=NULL_CEWI; /* Option a */
00100   char **fl_lst_abb=NULL; /* Option n */
00101   char **fl_lst_in=NULL_CEWI;
00102   char **var_lst_in=NULL_CEWI;
00103   char *cmd_ln;
00104   char *fl_in=NULL;
00105   char *fl_out=NULL; /* Option o */
00106   char *fl_out_tmp=NULL_CEWI;
00107   char *fl_pth=NULL; /* Option p */
00108   char *fl_pth_lcl=NULL; /* Option l */
00109   char *lmt_arg[NC_MAX_DIMS];
00110   char *msk_nm=NULL;
00111   char *msk_sng=NULL; /* Mask string to be "parsed" and values given to msk_nm, msk_val, op_typ_rlt */
00112   char *nco_op_typ_sng; /* Operation type */
00113   char *opt_crr=NULL; /* [sng] String representation of current long-option name */
00114   char *optarg_lcl=NULL; /* [sng] Local copy of system optarg */
00115   char *time_bfr_srt;
00116   char *wgt_nm=NULL;
00117   
00118   const char * const CVS_Id="$Id: ncwa.c,v 1.198 2006/02/26 07:41:55 zender Exp $"; 
00119   const char * const CVS_Revision="$Revision: 1.198 $";
00120   const char * const opt_sht_lst="4Aa:CcD:d:FhIl:M:m:nNOo:p:rRT:t:v:Ww:xy:z:-:";
00121   
00122   dmn_sct **dim=NULL_CEWI;
00123   dmn_sct **dmn_out=NULL_CEWI;
00124   dmn_sct **dmn_avg=NULL_CEWI;
00125   
00126   double msk_val=1.0; /* Option M */
00127 
00128   extern char *optarg;
00129   extern int optind;
00130   
00131   /* Using naked stdin/stdout/stderr in parallel region generates warning
00132      Copy appropriate filehandle to variable scoped shared in parallel clause */
00133   FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */
00134   FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */
00135 
00136   int *in_id_arr;
00137 
00138   int abb_arg_nbr=0;
00139   int dmn_avg_nbr=0;
00140   int fl_idx=int_CEWI;
00141   int fl_nbr=0;
00142   int fl_out_fmt=NC_FORMAT_CLASSIC; /* [enm] Output file format */
00143   int fll_md_old; /* [enm] Old fill mode */
00144   int idx=int_CEWI;
00145   int idx_avg;
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_out=0;
00150   int nbr_dmn_xtr;
00151   int nbr_var_fix; /* nbr_var_fix gets incremented */
00152   int nbr_var_fl;
00153   int nbr_var_prc; /* nbr_var_prc gets incremented */
00154   int nbr_xtr=0; /* nbr_xtr won't otherwise be set for -c with no -v */
00155   int nco_op_typ=nco_op_avg; /* Operation type */
00156   int op_typ_rlt=0; /* Option o */
00157   int opt;
00158   int out_id;  
00159   int rcd=NC_NOERR; /* [rcd] Return code */
00160   int rec_dmn_id=NCO_REC_DMN_UNDEFINED; /* [id] Record dimension ID in input file */
00161   int thr_idx; /* [idx] Index of current thread */
00162   int thr_nbr=int_CEWI; /* [nbr] Thread number Option t */
00163   int var_lst_in_nbr=0;
00164   
00165   lmt_sct **lmt;
00166   
00167   nm_id_sct *dmn_lst;
00168   nm_id_sct *xtr_lst=NULL; /* xtr_lst may be alloc()'d from NULL with -c option */
00169   nm_id_sct *dmn_avg_lst;
00170   
00171   time_t time_crr_time_t;
00172   
00173   var_sct **var;
00174   var_sct **var_fix;
00175   var_sct **var_fix_out;
00176   var_sct **var_out;
00177   var_sct **var_prc;
00178   var_sct **var_prc_out;
00179   var_sct *msk=NULL;
00180   var_sct *msk_out=NULL;
00181   var_sct *wgt=NULL;
00182   var_sct *wgt_avg=NULL;
00183   var_sct *wgt_out=NULL;
00184   
00185   prs_sct prs_arg;  /* I/O [sct] Global information required in ncwa parser */
00186   
00187   static struct option opt_lng[]=
00188     { /* Structure ordered by short option key if possible */
00189       /* Long options with no argument, no short option counterpart */
00190       /* Long options with argument, no short option counterpart */
00191       {"fl_fmt",required_argument,0,0},
00192       {"file_format",required_argument,0,0},
00193       /* Long options with short counterparts */
00194       {"4",no_argument,0,'4'},
00195       {"64bit",no_argument,0,'4'},
00196       {"netcdf4",no_argument,0,'4'},
00197       {"average",required_argument,0,'a'},
00198       {"avg",required_argument,0,'a'},
00199       {"append",no_argument,0,'A'},
00200       {"coords",no_argument,0,'c'},
00201       {"crd",no_argument,0,'c'},
00202       {"no-coords",no_argument,0,'C'},
00203       {"no-crd",no_argument,0,'C'},
00204       {"debug",required_argument,0,'D'},
00205       {"dbg_lvl",required_argument,0,'D'},
00206       {"dimension",required_argument,0,'d'},
00207       {"dmn",required_argument,0,'d'},
00208       {"fortran",no_argument,0,'F'},
00209       {"ftn",no_argument,0,'F'},
00210       {"history",no_argument,0,'h'},
00211       {"hst",no_argument,0,'h'},
00212       {"wgt_msk_crd_var",no_argument,0,'I'},
00213       {"local",required_argument,0,'l'},
00214       {"lcl",required_argument,0,'l'},
00215       {"mask-variable",required_argument,0,'m'},
00216       {"mask_variable",required_argument,0,'m'},
00217       {"mask",required_argument,0,'m'},
00218       {"msk_var",required_argument,0,'m'},
00219       {"msk_nm",required_argument,0,'m'},
00220       {"mask-value",required_argument,0,'M'},
00221       {"mask_value",required_argument,0,'M'},
00222       {"msk_val",required_argument,0,'M'},
00223       {"nintap",required_argument,0,'n'},
00224       {"nmr",no_argument,0,'N'},
00225       {"numerator",no_argument,0,'N'},
00226       {"overwrite",no_argument,0,'O'},
00227       {"ovr",no_argument,0,'O'},
00228       {"output",required_argument,0,'o'},
00229       {"fl_out",required_argument,0,'o'},
00230       {"path",required_argument,0,'p'},
00231       {"retain",no_argument,0,'R'},
00232       {"rtn",no_argument,0,'R'},
00233       {"revision",no_argument,0,'r'},
00234       {"truth_condition",required_argument,0,'T'},
00235       {"msk_cmp_typ",required_argument,0,'T'},
00236       {"op_rlt",required_argument,0,'T'},
00237       {"thr_nbr",required_argument,0,'t'},
00238       {"threads",required_argument,0,'t'},
00239       {"omp_num_threads",required_argument,0,'t'},
00240       {"variable",required_argument,0,'v'},
00241       {"version",no_argument,0,'r'},
00242       {"vrs",no_argument,0,'r'},
00243       {"normalize-by-tally",no_argument,0,'W',},
00244       {"exclude",no_argument,0,'x'},
00245       {"xcl",no_argument,0,'x'},
00246       {"weight",no_argument,0,'w'},
00247       {"wgt",no_argument,0,'w'},
00248       {"wgt_var",no_argument,0,'w'},
00249       {"operation",required_argument,0,'y'},
00250       {"op_typ",required_argument,0,'y'},
00251       {"mask_string",required_argument,0,'z'},
00252       {"msk_sng",required_argument,0,'z'},
00253       {"help",no_argument,0,'?'},
00254       {0,0,0,0}
00255     }; /* end opt_lng */
00256   int opt_idx=0; /* Index of current long option into opt_lng array */
00257 
00258   /* Start clock and save command line */ 
00259   cmd_ln=nco_cmd_ln_sng(argc,argv);
00260   time_crr_time_t=time((time_t *)NULL);
00261   time_bfr_srt=ctime(&time_crr_time_t); time_bfr_srt=time_bfr_srt; /* Avoid compiler warning until variable is used for something */
00262 
00263   time_bfr_srt=time_bfr_srt; /* CEWI: Avert compiler warning that variable is set but never used */
00264   NORMALIZE_BY_TALLY=NORMALIZE_BY_TALLY; /* CEWI: Avert compiler warning that variable is set but never used */
00265   NORMALIZE_BY_WEIGHT=NORMALIZE_BY_WEIGHT; /* CEWI: Avert compiler warning that variable is set but never used */
00266   
00267   /* Get program name and set program enum (e.g., prg=ncra) */
00268   prg_nm=prg_prs(argv[0],&prg);
00269 
00270   /* Parse command line arguments */
00271   while(1){
00272     /* getopt_long_only() allows one dash to prefix long options */
00273     opt=getopt_long(argc,argv,opt_sht_lst,opt_lng,&opt_idx);
00274     /* NB: access to opt_crr is only valid when long_opt is detected */
00275     if(opt == EOF) break; /* Parse positional arguments once getopt_long() returns EOF */
00276     opt_crr=(char *)strdup(opt_lng[opt_idx].name);
00277 
00278     /* Process long options without short option counterparts */
00279     if(opt == 0){
00280       if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt);
00281     } /* opt != 0 */
00282     /* Process short options */
00283     switch(opt){
00284     case 0: /* Long options have already been processed, return */
00285       break;
00286     case '4': /* [flg] Catch-all to prescribe output storage format */
00287       if(!strcmp(opt_crr,"64bit")) fl_out_fmt=NC_FORMAT_64BIT; else fl_out_fmt=NC_FORMAT_NETCDF4; 
00288       break;
00289     case 'A': /* Toggle FORCE_APPEND */
00290       FORCE_APPEND=!FORCE_APPEND;
00291       break;
00292     case 'a': /* Dimensions over which to average hyperslab */
00293       if(opt_a_flg){
00294         (void)fprintf(fp_stdout,"%s: ERROR Option -a appears more than once\n",prg_nm);
00295         (void)fprintf(fp_stdout,"%s: HINT Use -a dim1,dim2,... not -a dim1 -a dim2 ...\n",prg_nm);
00296         (void)nco_usg_prn();
00297         nco_exit(EXIT_FAILURE);
00298       } /* endif */
00299       dmn_avg_lst_in=lst_prs_2D(optarg,",",&dmn_avg_nbr);
00300       opt_a_flg=True;
00301       break;
00302     case 'C': /* Extract all coordinates associated with extracted variables? */
00303       EXTRACT_ASSOCIATED_COORDINATES=False;
00304       break;
00305     case 'c':
00306       EXTRACT_ALL_COORDINATES=True;
00307       break;
00308     case 'D': /* Debugging level. Default is 0. */
00309       dbg_lvl=(unsigned short)strtol(optarg,(char **)NULL,10);
00310       break;
00311     case 'd': /* Copy argument for later processing */
00312       lmt_arg[lmt_nbr]=(char *)strdup(optarg);
00313       lmt_nbr++;
00314       break;
00315     case 'F': /* Toggle index convention. Default is 0-based arrays (C-style). */
00316       FORTRAN_IDX_CNV=!FORTRAN_IDX_CNV;
00317       break;
00318     case 'h': /* Toggle appending to history global attribute */
00319       HISTORY_APPEND=!HISTORY_APPEND;
00320       break;
00321     case 'I': /* [flg] Weight and/or mask coordinate variables */
00322       WGT_MSK_CRD_VAR=!WGT_MSK_CRD_VAR;
00323       break;
00324     case 'l': /* Local path prefix for files retrieved from remote file system */
00325       fl_pth_lcl=(char *)strdup(optarg);
00326       break;
00327     case 'm': /* Name of variable to use as mask in reducing. Default is none */
00328       msk_nm=(char *)strdup(optarg);
00329       break;
00330     case 'M': /* Good data defined by relation to mask value. Default is 1. */
00331       msk_val=strtod(optarg,(char **)NULL);
00332       break;
00333     case 'N':
00334       NRM_BY_DNM=False;
00335       NORMALIZE_BY_TALLY=False;
00336       NORMALIZE_BY_WEIGHT=False;
00337       break;
00338     case 'n':
00339       NORMALIZE_BY_WEIGHT=False;
00340       (void)fprintf(fp_stdout,"%s: ERROR This option has been disabled while I rethink its implementation\n",prg_nm);
00341       nco_exit(EXIT_FAILURE);
00342       break;
00343     case 'O': /* Toggle FORCE_OVERWRITE */
00344       FORCE_OVERWRITE=!FORCE_OVERWRITE;
00345       break;
00346     case 'o': /* Name of output file */
00347       fl_out=(char *)strdup(optarg);
00348       break;
00349     case 'p': /* Common file path */
00350       fl_pth=(char *)strdup(optarg);
00351       break;
00352     case 'R': /* Toggle removal of remotely-retrieved-files. Default is True. */
00353       REMOVE_REMOTE_FILES_AFTER_PROCESSING=!REMOVE_REMOTE_FILES_AFTER_PROCESSING;
00354       break;
00355     case 'r': /* Print CVS program information and copyright notice */
00356       (void)copyright_prn(CVS_Id,CVS_Revision);
00357       (void)nco_lbr_vrs_prn();
00358        nco_exit(EXIT_SUCCESS);
00359       break;
00360     case 'T': /* Relational operator type. Default is 0, eq, equality */
00361       op_typ_rlt=nco_op_prs_rlt(optarg);
00362       break;
00363     case 't': /* Thread number */
00364       thr_nbr=(int)strtol(optarg,(char **)NULL,10);
00365       break;
00366     case 'v': /* Variables to extract/exclude */
00367       /* Replace commas with hashes when within braces (convert back later) */
00368       optarg_lcl=(char *)strdup(optarg);
00369       (void)nco_lst_comma2hash(optarg_lcl);
00370       var_lst_in=lst_prs_2D(optarg_lcl,",",&var_lst_in_nbr);
00371       optarg_lcl=(char *)nco_free(optarg_lcl);
00372       nbr_xtr=var_lst_in_nbr;
00373       break;
00374     case 'W':
00375       NORMALIZE_BY_TALLY=False;
00376       (void)fprintf(fp_stdout,"%s: ERROR This option has been disabled while I rethink its implementation\n",prg_nm);
00377       nco_exit(EXIT_FAILURE);
00378       break;
00379     case 'w': /* Variable to use as weight in reducing.  Default is none */
00380       wgt_nm=(char *)strdup(optarg);
00381       break;
00382     case 'x': /* Exclude rather than extract variables specified with -v */
00383       EXCLUDE_INPUT_LIST=True;
00384       break;
00385     case 'y': /* Operation type */
00386       nco_op_typ_sng=(char *)strdup(optarg);
00387       nco_op_typ=nco_op_typ_get(nco_op_typ_sng);
00388       break;
00389     case 'z': /* Mask string to be parsed */
00390       msk_sng=(char *)strdup(optarg);
00391       break;
00392     case '?': /* Print proper usage */
00393       (void)nco_usg_prn();
00394       nco_exit(EXIT_SUCCESS);
00395       break;
00396     case '-': /* Long options are not allowed */
00397       (void)fprintf(stderr,"%s: ERROR Long options are not available in this build. Use single letter options instead.\n",prg_nm_get());
00398       nco_exit(EXIT_FAILURE);
00399       break;
00400     default: /* Print proper usage */
00401       (void)nco_usg_prn();
00402       nco_exit(EXIT_FAILURE);
00403       break;
00404     } /* end switch */
00405     if(opt_crr != NULL) opt_crr=(char *)nco_free(opt_crr);
00406   } /* end while loop */
00407 
00408   /* Parse mask string */
00409   if(msk_sng){
00410     int zero=0;
00411     /* Set arguments for scan */
00412     prs_arg.fl_in=NULL; /* [sng] Input data file */
00413     prs_arg.in_id=0; /* [id] Input data file ID */
00414     prs_arg.fl_out=NULL; /* [sng] Output data file */
00415     prs_arg.out_id=0; /* [id] Output data file ID */
00416     prs_arg.att_lst=NULL; /* [sct] Attributes in script */
00417     prs_arg.nbr_att=&zero; /* [nbr] Number of attributes in script */
00418     prs_arg.dmn_in=NULL; /* [dmn_in] List of all dimensions in input */
00419     prs_arg.nbr_dmn_in=0; /* [nbr] Number of  dimensions in input */
00420     prs_arg.dmn_out=NULL; /* pointer to list of dims in output */
00421     prs_arg.nbr_dmn_out=&zero; /* number of dims in above list */
00422     prs_arg.sym_tbl=NULL; /* [fnc] Symbol table for functions */
00423     prs_arg.sym_tbl_nbr=0; /* [nbr] Number of functions in table */
00424     prs_arg.ntl_scn=False; /* [flg] Initial scan of script */
00425     prs_arg.var_LHS=NULL; /* [var] LHS cast variable */
00426     prs_arg.nco_op_typ=nco_op_nil; /* [enm] Operation type */
00427   
00428     /* Initialize line counter */
00429     ncap_ln_nbr_crr=(size_t *)nco_realloc(ncap_ln_nbr_crr,ncap_ncl_dpt_crr+1UL); 
00430     ncap_ln_nbr_crr[ncap_ncl_dpt_crr]=1UL; /* [cnt] Line number incremented in ncap.l */
00431     if(ncap_ncwa_scn(&prs_arg,msk_sng,&msk_nm,&msk_val,&op_typ_rlt) == 0) nco_exit(EXIT_FAILURE); 
00432   } /* endif msk_sng */
00433 
00434   /* Ensure we do not attempt to normalize by non-existent weight */
00435   if(wgt_nm == NULL) NORMALIZE_BY_WEIGHT=False;
00436 
00437   /* Process positional arguments and fill in filenames */
00438   fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN);
00439 
00440   /* Make uniform list of user-specified dimension limits */
00441   lmt=nco_lmt_prs(lmt_nbr,lmt_arg);
00442     
00443   /* Initialize thread information */
00444   thr_nbr=nco_openmp_ini(thr_nbr);
00445   in_id_arr=(int *)nco_malloc(thr_nbr*sizeof(int));
00446 
00447   /* Parse filename */
00448   fl_in=nco_fl_nm_prs(fl_in,0,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth);
00449   /* Make sure file is on local system and is readable or die trying */
00450   fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION);
00451   /* Open file for reading */
00452   rcd=nco_open(fl_in,NC_NOWRITE,&in_id);
00453   
00454   /* Get number of variables, dimensions, and record dimension ID of input file */
00455   (void)nco_inq(in_id,&nbr_dmn_fl,&nbr_var_fl,(int *)NULL,&rec_dmn_id);
00456   
00457   /* Form initial extraction list which may include extended regular expressions */
00458   xtr_lst=nco_var_lst_mk(in_id,nbr_var_fl,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr);
00459 
00460   /* Change included variables to excluded variables */
00461   if(EXCLUDE_INPUT_LIST) xtr_lst=nco_var_lst_xcl(in_id,nbr_var_fl,xtr_lst,&nbr_xtr);
00462 
00463   /* Add all coordinate variables to extraction list */
00464   if(EXTRACT_ALL_COORDINATES) xtr_lst=nco_var_lst_add_crd(in_id,nbr_dmn_fl,xtr_lst,&nbr_xtr);
00465 
00466   /* Make sure coordinates associated extracted variables are also on extraction list */
00467   if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst=nco_var_lst_ass_crd_add(in_id,xtr_lst,&nbr_xtr);
00468 
00469   /* Sort extraction list by variable ID for fastest I/O */
00470   if(nbr_xtr > 1) xtr_lst=nco_lst_srt_nm_id(xtr_lst,nbr_xtr,False);
00471     
00472   /* Find coordinate/dimension values associated with user-specified limits
00473      NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */
00474   for(idx=0;idx<lmt_nbr;idx++) (void)nco_lmt_evl(in_id,lmt[idx],0L,FORTRAN_IDX_CNV);
00475   
00476   /* Find dimensions associated with variables to be extracted */
00477   dmn_lst=nco_dmn_lst_ass_var(in_id,xtr_lst,nbr_xtr,&nbr_dmn_xtr);
00478 
00479   /* Fill in dimension structure for all extracted dimensions */
00480   dim=(dmn_sct **)nco_malloc(nbr_dmn_xtr*sizeof(dmn_sct *));
00481   for(idx=0;idx<nbr_dmn_xtr;idx++) dim[idx]=nco_dmn_fll(in_id,dmn_lst[idx].id,dmn_lst[idx].nm);
00482   
00483   /* Merge hyperslab limit information into dimension structures */
00484   if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim,nbr_dmn_xtr,lmt,lmt_nbr);
00485 
00486   /* Not specifying any dimensions is interpreted as specifying all dimensions */
00487   if(dmn_avg_nbr == 0){
00488     dmn_avg_nbr=nbr_dmn_xtr;
00489     dmn_avg_lst_in=(char **)nco_malloc(dmn_avg_nbr*sizeof(char *));
00490     for(idx=0;idx<dmn_avg_nbr;idx++){
00491       dmn_avg_lst_in[idx]=(char *)strdup(dmn_lst[idx].nm);
00492     } /* end loop over idx */
00493     (void)fprintf(stderr,"%s: INFO No dimensions specified with -a, therefore reducing (averaging, taking minimum, etc.) over all dimensions\n",prg_nm);
00494   } /* end if dmn_avg_nbr == 0 */
00495   /* Dimension list no longer needed */
00496   dmn_lst=nco_nm_id_lst_free(dmn_lst,nbr_dmn_xtr);
00497 
00498   if(dmn_avg_nbr > 0){
00499     if(dmn_avg_nbr > nbr_dmn_xtr){
00500       (void)fprintf(fp_stdout,"%s: ERROR More reducing dimensions than extracted dimensions\n",prg_nm);
00501       nco_exit(EXIT_FAILURE);
00502     } /* end if */
00503 
00504     /* Create structured list of reducing dimension names and IDs */
00505     dmn_avg_lst=nco_dmn_lst_mk(in_id,dmn_avg_lst_in,dmn_avg_nbr);
00506     /* Dimension average list no longer needed */
00507     if(dmn_avg_nbr > 0) dmn_avg_lst_in=nco_sng_lst_free(dmn_avg_lst_in,dmn_avg_nbr);
00508 
00509     /* Form list of reducing dimensions from extracted input dimensions */
00510     dmn_avg=(dmn_sct **)nco_malloc(dmn_avg_nbr*sizeof(dmn_sct *));
00511     for(idx_avg=0;idx_avg<dmn_avg_nbr;idx_avg++){
00512       for(idx=0;idx<nbr_dmn_xtr;idx++){
00513         if(!strcmp(dmn_avg_lst[idx_avg].nm,dim[idx]->nm)) break;
00514       } /* end loop over idx_avg */
00515       if(idx != nbr_dmn_xtr){
00516         dmn_avg[idx_avg]=dim[idx];
00517       }else{
00518         (void)fprintf(stderr,"%s: WARNING reducing dimension \"%s\" is not contained in any variable in extraction list\n",prg_nm,dmn_avg_lst[idx_avg].nm);
00519         /* Collapse dimension average list by omitting irrelevent dimension */
00520         (void)memmove(dmn_avg_lst+idx_avg*sizeof(nm_id_sct),dmn_avg_lst+(idx_avg+1)*sizeof(nm_id_sct),(dmn_avg_nbr-idx_avg-1)*sizeof(nm_id_sct));
00521         --dmn_avg_nbr;
00522         dmn_avg_lst=(nm_id_sct *)nco_realloc(dmn_avg_lst,dmn_avg_nbr*sizeof(nm_id_sct));
00523         dmn_avg=(dmn_sct **)nco_realloc(dmn_avg,dmn_avg_nbr*sizeof(dmn_sct *)); 
00524       } /* end else */
00525     } /* end loop over idx_avg */
00526 
00527     /* Make sure no reducing dimension is specified more than once */
00528     for(idx=0;idx<dmn_avg_nbr;idx++){
00529       for(idx_avg=0;idx_avg<dmn_avg_nbr;idx_avg++){
00530         if(idx_avg != idx){
00531           if(dmn_avg[idx]->id == dmn_avg[idx_avg]->id){
00532             (void)fprintf(fp_stdout,"%s: ERROR %s specified more than once in reducing list\n",prg_nm,dmn_avg[idx]->nm);
00533             nco_exit(EXIT_FAILURE);
00534           } /* end if */
00535         } /* end if */
00536       } /* end loop over idx_avg */
00537     } /* end loop over idx */
00538 
00539     /* Dimensions to be averaged will not appear in output file */
00540     dmn_out=(dmn_sct **)nco_malloc((nbr_dmn_xtr-dmn_avg_nbr)*sizeof(dmn_sct *));
00541     nbr_dmn_out=0;
00542     for(idx=0;idx<nbr_dmn_xtr;idx++){
00543       for(idx_avg=0;idx_avg<dmn_avg_nbr;idx_avg++){
00544         if(!strcmp(dmn_avg_lst[idx_avg].nm,dim[idx]->nm)) break;
00545       } /* end loop over idx_avg */
00546       if(idx_avg == dmn_avg_nbr){
00547         dmn_out[nbr_dmn_out]=nco_dmn_dpl(dim[idx]);
00548         (void)nco_dmn_xrf(dim[idx],dmn_out[nbr_dmn_out]);
00549         nbr_dmn_out++;
00550       } /* end if */
00551     } /* end loop over idx_avg */
00552     /* Dimension average list no longer needed */
00553     dmn_avg_lst=nco_nm_id_lst_free(dmn_avg_lst,dmn_avg_nbr);
00554 
00555     if(nbr_dmn_out != nbr_dmn_xtr-dmn_avg_nbr){
00556       (void)fprintf(fp_stdout,"%s: ERROR nbr_dmn_out != nbr_dmn_xtr-dmn_avg_nbr\n",prg_nm);
00557       nco_exit(EXIT_FAILURE);
00558     } /* end if */
00559     
00560   } /* dmn_avg_nbr <= 0 */
00561 
00562   /* Is this an CCM/CCSM/CF-format history tape? */
00563   CNV_CCM_CCSM_CF=nco_cnv_ccm_ccsm_cf_inq(in_id);
00564 
00565   /* Fill in variable structure list for all extracted variables */
00566   var=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *));
00567   var_out=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *));
00568   for(idx=0;idx<nbr_xtr;idx++){
00569     var[idx]=nco_var_fll(in_id,xtr_lst[idx].id,xtr_lst[idx].nm,dim,nbr_dmn_xtr);
00570     var_out[idx]=nco_var_dpl(var[idx]);
00571     (void)nco_xrf_var(var[idx],var_out[idx]);
00572     (void)nco_xrf_dmn(var_out[idx]);
00573   } /* end loop over idx */
00574   /* Extraction list no longer needed */
00575   xtr_lst=nco_nm_id_lst_free(xtr_lst,nbr_xtr);
00576 
00577   /* Divide variable lists into lists of fixed variables and variables to be processed */
00578   (void)nco_var_lst_dvd(var,var_out,nbr_xtr,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,dmn_avg,dmn_avg_nbr,&var_fix,&var_fix_out,&nbr_var_fix,&var_prc,&var_prc_out,&nbr_var_prc);
00579 
00580   /* We now have final list of variables to extract. Phew. */
00581   if(dbg_lvl > 0){
00582     for(idx=0;idx<nbr_xtr;idx++) (void)fprintf(stderr,"var[%d]->nm = %s, ->id=[%d]\n",idx,var[idx]->nm,var[idx]->id);
00583     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);
00584     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);
00585   } /* end if */
00586   
00587   /* Open output file */
00588   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&out_id);
00589   if(dbg_lvl > 4) (void)fprintf(stderr,"Input, output file IDs = %d, %d\n",in_id,out_id);
00590 
00591   /* Copy all global attributes */
00592   (void)nco_att_cpy(in_id,out_id,NC_GLOBAL,NC_GLOBAL,True);
00593   
00594   /* Catenate time-stamped command line to "history" global attribute */
00595   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
00596 
00597   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
00598   
00599   /* Define dimensions in output file */
00600   (void)nco_dmn_dfn(fl_out,out_id,dmn_out,nbr_dmn_out);
00601 
00602   /* Define variables in output file, copy their attributes */
00603   (void)nco_var_dfn(in_id,fl_out,out_id,var_out,nbr_xtr,dmn_out,nbr_dmn_out,nco_pck_plc_nil,nco_pck_map_nil);
00604 
00605   /* Add new missing values to output file while in define mode */
00606   if(msk_nm != NULL){
00607     for(idx=0;idx<nbr_var_prc;idx++){
00608       /* Define for var_prc_out because mss_val for var_prc will be overwritten in nco_var_mtd_refresh() */
00609       if(!var_prc_out[idx]->has_mss_val){
00610         var_prc_out[idx]->has_mss_val=True;
00611         var_prc_out[idx]->mss_val=nco_mss_val_mk(var_prc[idx]->type);
00612         (void)nco_put_att(out_id,var_prc_out[idx]->id,"missing_value",var_prc_out[idx]->type,1,var_prc_out[idx]->mss_val.vp);
00613       } /* end if */
00614     } /* end for */
00615   } /* end if */
00616 
00617   /* Turn off default filling behavior to enhance efficiency */
00618   rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old);
00619   
00620   /* Take output file out of define mode */
00621   (void)nco_enddef(out_id);
00622   
00623   /* Zero start vectors for all output variables */
00624   (void)nco_var_srt_zero(var_out,nbr_xtr);
00625 
00626   /* Copy variable data for non-processed variables */
00627   (void)nco_var_val_cpy(in_id,out_id,var_fix,nbr_var_fix);
00628 
00629   /* Close first input netCDF file */
00630   nco_close(in_id);
00631   
00632   /* Loop over input files (not currently used, fl_nbr == 1) */
00633   for(fl_idx=0;fl_idx<fl_nbr;fl_idx++){
00634     /* Parse filename */
00635     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);
00636     if(dbg_lvl > 0) (void)fprintf(stderr,"\nInput file %d is %s; ",fl_idx,fl_in);
00637     /* Make sure file is on local system and is readable or die trying */
00638     if(fl_idx != 0) fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION);
00639     if(dbg_lvl > 0) (void)fprintf(stderr,"local file %s:\n",fl_in);
00640     
00641     /* Open file once per thread to improve caching */
00642     for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in,NC_NOWRITE,in_id_arr+thr_idx);
00643     in_id=in_id_arr[0];
00644     
00645     /* Perform various error-checks on input file */
00646     if(False) (void)nco_fl_cmp_err_chk();
00647 
00648     /* Find weighting variable in input file */
00649     if(wgt_nm != NULL){
00650       int wgt_id;
00651       
00652       rcd=nco_inq_varid(in_id,wgt_nm,&wgt_id);
00653       /* fxm: TODO #111 core dump if wgt has dimension not in extraction list */
00654       wgt=nco_var_fll(in_id,wgt_id,wgt_nm,dim,nbr_dmn_xtr);
00655       
00656       /* Retrieve weighting variable */
00657       (void)nco_var_get(in_id,wgt);
00658       /* fxm: Perhaps should allocate default tally array for wgt here
00659        That way, when wgt conforms to the first var_prc_out and it therefore
00660        does not get a tally array copied by nco_var_dpl() in nco_var_cnf_dmn(), 
00661        it will at least have space for a tally array. TODO #114. */
00662 
00663     } /* end if */
00664 
00665     /* Find mask variable in input file */
00666     if(msk_nm != NULL){
00667       int msk_id;
00668       
00669       rcd=nco_inq_varid(in_id,msk_nm,&msk_id);
00670       /* fxm: TODO #111 core dump if msk has dimension not in extraction list */
00671       msk=nco_var_fll(in_id,msk_id,msk_nm,dim,nbr_dmn_xtr);
00672       
00673       /* Retrieve mask variable */
00674       /* NB: nco_var_get() with same nc_id contains OpenMP critical region */
00675       (void)nco_var_get(in_id,msk);
00676     } /* end if */
00677 
00678 #ifdef _OPENMP
00679   /* OpenMP notes:
00680      firstprivate(): msk_out and wgt_out must be NULL on first call to nco_var_cnf_dmn()
00681      shared(): msk and wgt are not altered within loop
00682      private(): wgt_avg does not need initialization */
00683 #pragma omp parallel for default(none) firstprivate(DO_CONFORM_MSK,DO_CONFORM_WGT,msk_out,wgt_out) private(idx,in_id,wgt_avg) shared(MULTIPLY_BY_TALLY,MUST_CONFORM,NRM_BY_DNM,WGT_MSK_CRD_VAR,dbg_lvl,dmn_avg,dmn_avg_nbr,fp_stderr,fp_stdout,in_id_arr,msk,msk_nm,msk_val,nbr_var_prc,nco_op_typ,op_typ_rlt,out_id,prg_nm,rcd,var_prc,var_prc_out,wgt,wgt_nm)
00684 #endif /* !_OPENMP */
00685     for(idx=0;idx<nbr_var_prc;idx++){ /* Process all variables in current file */
00686       in_id=in_id_arr[omp_get_thread_num()];
00687       if(dbg_lvl > 0) rcd+=nco_var_prc_crr_prn(idx,var_prc[idx]->nm);
00688       if(dbg_lvl > 0) (void)fflush(fp_stderr);
00689       
00690       /* Allocate and, if necessary, initialize accumulation space for all processed variables */
00691       var_prc_out[idx]->sz=var_prc[idx]->sz;
00692       /*      if((var_prc_out[idx]->tally=var_prc[idx]->tally=(long *)nco_malloc_flg(var_prc_out[idx]->sz*sizeof(long))) == NULL){*/
00693       /* fxm: verify that var_prc->tally is not needed */
00694       if((var_prc_out[idx]->tally=(long *)nco_malloc_flg(var_prc_out[idx]->sz*sizeof(long))) == NULL){
00695         (void)fprintf(fp_stdout,"%s: ERROR Unable to malloc() %ld*%ld bytes for tally buffer for variable %s in main()\n",prg_nm_get(),var_prc_out[idx]->sz,(long)sizeof(long),var_prc_out[idx]->nm);
00696         nco_exit(EXIT_FAILURE); 
00697       } /* end if err */
00698       (void)nco_zero_long(var_prc_out[idx]->sz,var_prc_out[idx]->tally);
00699       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){
00700         (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);
00701         nco_exit(EXIT_FAILURE); 
00702       } /* end if err */
00703       (void)nco_var_zero(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->val);
00704       
00705       (void)nco_var_mtd_refresh(in_id,var_prc[idx]);
00706       /* Retrieve variable from disk into memory */
00707       if(dbg_lvl > 4) (void)fprintf(fp_stdout,"%s: DEBUG: fxm TODO nco354 About to nco_var_get() %s\n",prg_nm,var_prc[idx]->nm);
00708       /* NB: nco_var_get() with same nc_id contains OpenMP critical region */
00709       (void)nco_var_get(in_id,var_prc[idx]);
00710       if(dbg_lvl > 4) (void)fprintf(fp_stdout,"%s: DEBUG: fxm TODO nco354 Finished nco_var_get() %s\n",prg_nm,var_prc[idx]->nm);
00711       
00712       /* Convert char, short, long, int types to doubles before arithmetic */
00713       var_prc[idx]=nco_typ_cnv_rth(var_prc[idx],nco_op_typ);
00714       var_prc_out[idx]=nco_typ_cnv_rth(var_prc_out[idx],nco_op_typ);
00715       
00716       if(msk_nm != NULL && (!var_prc[idx]->is_crd_var || WGT_MSK_CRD_VAR)){
00717         msk_out=nco_var_cnf_dmn(var_prc[idx],msk,msk_out,MUST_CONFORM,&DO_CONFORM_MSK);
00718         /* If msk and var did not conform then do not mask var! */
00719         if(DO_CONFORM_MSK){
00720           msk_out=nco_var_cnf_typ(var_prc[idx]->type,msk_out);
00721           
00722           /* mss_val for var_prc has been overwritten in nco_var_mtd_refresh() */
00723           if(!var_prc[idx]->has_mss_val){
00724             var_prc[idx]->has_mss_val=True;
00725             var_prc[idx]->mss_val=nco_mss_val_mk(var_prc[idx]->type);
00726           } /* end if */
00727           
00728           /* Mask by changing variable to missing value where condition is false */
00729           (void)nco_var_msk(var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,msk_val,op_typ_rlt,msk_out->val,var_prc[idx]->val);
00730         } /* end if */
00731       } /* end if */
00732       /* Perform non-linear transformations before weighting */
00733       switch(nco_op_typ){
00734       case nco_op_avgsqr: /* Square variable before weighting */
00735       case nco_op_rms: /* Square variable before weighting */
00736       case nco_op_rmssdn: /* Square variable before weighting */
00737         (void)nco_var_mlt(var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->val,var_prc[idx]->val);
00738         break;
00739       default: /* All other operations are linear, do nothing to them yet */
00740         break;
00741       } /* end case */
00742       if(wgt_nm != NULL && (!var_prc[idx]->is_crd_var || WGT_MSK_CRD_VAR)){
00743         /* fxm: nco_var_cnf_dmn() has bug where it does not allocate tally array
00744            for weights that do already conform to var_prc. TODO #114. */
00745         wgt_out=nco_var_cnf_dmn(var_prc[idx],wgt,wgt_out,MUST_CONFORM,&DO_CONFORM_WGT);
00746         if(DO_CONFORM_WGT){
00747           wgt_out=nco_var_cnf_typ(var_prc[idx]->type,wgt_out);
00748           /* Weight after any initial non-linear operation so, e.g., variable is squared but not weights */
00749           /* Weight variable by taking product of weight and variable */
00750           (void)nco_var_mlt(var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,wgt_out->val,var_prc[idx]->val);
00751         } /* end if weights conformed */
00752       } /* end if weight was specified and then tested for conformance */
00753       /* Copy (masked) (weighted) values from var_prc to var_prc_out */
00754       (void)memcpy((void *)(var_prc_out[idx]->val.vp),(void *)(var_prc[idx]->val.vp),var_prc_out[idx]->sz*nco_typ_lng(var_prc_out[idx]->type));
00755       /* 20050516: fxm: destruction of var_prc_out in nco_var_avg() leaves dangling pointers in var_out? */
00756       /* Reduce variable over specified dimensions (tally array is set here)
00757          NB: var_prc_out[idx] is new, so corresponding var_out[idx] is dangling */
00758       var_prc_out[idx]=nco_var_avg(var_prc_out[idx],dmn_avg,dmn_avg_nbr,nco_op_typ);
00759       /* var_prc_out[idx]->val now holds numerator of averaging expression documented in NCO User's Guide
00760          Denominator is also tricky due to sundry normalization options
00761          These logical switches are VERY tricky---be careful modifying them */
00762       if(NRM_BY_DNM && DO_CONFORM_WGT && (!var_prc[idx]->is_crd_var || WGT_MSK_CRD_VAR)){
00763         /* Duplicate wgt_out as wgt_avg so that wgt_out is not contaminated by any
00764            averaging operation and may be reused on next variable.
00765            Free wgt_avg after each use but continue to reuse wgt_out */
00766         wgt_avg=nco_var_dpl(wgt_out);
00767         
00768         if(var_prc[idx]->has_mss_val){
00769           double mss_val_dbl=double_CEWI;
00770           /* Set denominator to missing value at all locations where variable is missing value
00771              If this is accomplished by setting weight to missing value wherever variable is missing value
00772              then weight must not be re-used by next variable (which might conform but have missing values in different locations)
00773              This is one good reason to copy wgt_out into disposable wgt_avg for each new variable */
00774           /* First, make sure wgt_avg has same missing value as variable */
00775           (void)nco_mss_val_cp(var_prc[idx],wgt_avg);
00776           /* Copy missing value into double precision variable */
00777           switch(wgt_avg->type){
00778           case NC_FLOAT: mss_val_dbl=wgt_avg->mss_val.fp[0]; break; 
00779           case NC_DOUBLE: mss_val_dbl=wgt_avg->mss_val.dp[0]; break; 
00780           case NC_INT: mss_val_dbl=wgt_avg->mss_val.lp[0]; break;
00781           case NC_SHORT: mss_val_dbl=wgt_avg->mss_val.sp[0]; break;
00782           case NC_CHAR: mss_val_dbl=wgt_avg->mss_val.cp[0]; break;
00783           case NC_BYTE: mss_val_dbl=wgt_avg->mss_val.bp[0]; break;
00784           default: nco_dfl_case_nc_type_err(); break;
00785           } /* end switch */
00786           /* Second, mask wgt_avg where variable is missing value */
00787           (void)nco_var_msk(wgt_avg->type,wgt_avg->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,mss_val_dbl,nco_op_ne,var_prc[idx]->val,wgt_avg->val);
00788         } /* endif weight must be checked for missing values */
00789         
00790         /* Free current input buffer */
00791         var_prc[idx]->val.vp=nco_free(var_prc[idx]->val.vp);
00792 
00793         if(msk_nm != NULL && DO_CONFORM_MSK){
00794           /* Must mask weight in same fashion as variable was masked
00795              If msk and var did not conform then do not mask wgt
00796              Ensure wgt_avg has a missing value */
00797           if(!wgt_avg->has_mss_val){
00798             wgt_avg->has_mss_val=True;
00799             wgt_avg->mss_val=nco_mss_val_mk(wgt_avg->type);
00800           } /* end if */
00801           /* Mask by changing weight to missing value where condition is false */
00802           (void)nco_var_msk(wgt_avg->type,wgt_avg->sz,wgt_avg->has_mss_val,wgt_avg->mss_val,msk_val,op_typ_rlt,msk_out->val,wgt_avg->val);
00803         } /* endif weight must be masked */
00804         
00805         /* fxm: temporary kludge to make sure weight has tally space
00806            wgt_avg may lack valid tally array in ncwa because wgt_avg is created, 
00807            sometimes, before the tally array for var_prc_out[idx] is created. 
00808            When this occurs the nco_var_dpl() call in nco_var_cnf_dmn() does not copy
00809            tally array into wgt_avg. See related note about this above. TODO #114.*/
00810         if(wgt_avg->sz > 0)
00811           if((wgt_avg->tally=(long *)nco_realloc(wgt_avg->tally,wgt_avg->sz*sizeof(long))) == NULL){
00812             (void)fprintf(fp_stdout,"%s: ERROR Unable to realloc() %ld*%ld bytes for tally buffer for weight %s in main()\n",prg_nm_get(),wgt_avg->sz,(long)sizeof(long),wgt_avg->nm);
00813             nco_exit(EXIT_FAILURE); 
00814           } /* end if */
00815         /* Average weight over specified dimensions (tally array is set here) */
00816         wgt_avg=nco_var_avg(wgt_avg,dmn_avg,dmn_avg_nbr,nco_op_avg);
00817         if(MULTIPLY_BY_TALLY){
00818           /* NB: Currently this is not implemented */
00819           /* Multiply numerator (weighted sum of variable) by tally 
00820              We deviously accomplish this by dividing denominator by tally */
00821           (void)nco_var_nrm(wgt_avg->type,wgt_avg->sz,wgt_avg->has_mss_val,wgt_avg->mss_val,wgt_avg->tally,wgt_avg->val);
00822         } /* endif */
00823         /* Divide numerator by denominator */
00824         /* Diagnose common PEBCAK before it causes core dump */
00825         if(var_prc_out[idx]->sz == 1L && var_prc_out[idx]->type == NC_INT && var_prc_out[idx]->val.lp[0] == 0){
00826           (void)fprintf(fp_stdout,"%s: ERROR Weight in denominator weight = 0.0, will cause SIGFPE\n%s: HINT Sum of masked, averaged weights must be non-zero\n%s: HINT A possible workaround is to remove variable \"%s\" from output file using \"%s -x -v %s ...\"\n%s: Expecting core dump...now!\n",prg_nm,prg_nm,prg_nm,var_prc_out[idx]->nm,prg_nm,var_prc_out[idx]->nm,prg_nm);
00827         } /* end if */
00828         /* Divide numerator by masked, averaged, weights */
00829         switch(nco_op_typ){
00830         case nco_op_avg: /* Normalize sum by weighted tally to create mean */
00831         case nco_op_sqravg: /* Normalize sum by weighted tally to create mean */
00832         case nco_op_avgsqr: /* Normalize sum of squares by weighted tally to create mean square */
00833         case nco_op_rms: /* Normalize sum of squares by weighted tally to create mean square */
00834         case nco_op_sqrt: /* Normalize sum by weighted tally to create mean */
00835         case nco_op_rmssdn: /* Normalize sum of squares by weighted tally-1 to create mean square for sdn */
00836           (void)nco_var_dvd(var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,wgt_avg->val,var_prc_out[idx]->val);
00837           break;
00838         case nco_op_min: /* Minimum is already in buffer, do nothing */
00839         case nco_op_max: /* Maximum is already in buffer, do nothing */ 
00840         case nco_op_ttl: /* Total is already in buffer, do nothing */   
00841           break;
00842         default:
00843           (void)fprintf(fp_stdout,"%s: ERROR Illegal nco_op_typ in weighted normalization\n",prg_nm);
00844           nco_exit(EXIT_FAILURE);
00845           break;
00846         } /* end switch */
00847         /* Free wgt_avg, but keep wgt_out, after each use */
00848         if(wgt_avg != NULL) wgt_avg=nco_var_free(wgt_avg);
00849         /* End of branch for normalization when weights were specified */
00850       }else if(NRM_BY_DNM){
00851         /* Branch for normalization when no weights were specified
00852            Normalization is just due to tally */
00853         switch(nco_op_typ){
00854         case nco_op_avg: /* Normalize sum by tally to create mean */
00855         case nco_op_sqravg: /* Normalize sum by tally to create mean */
00856         case nco_op_avgsqr: /* Normalize sum of squares by tally to create mean square */
00857         case nco_op_rms: /* Normalize sum of squares by tally to create mean square */
00858         case nco_op_sqrt: /* Normalize sum by tally to create mean */
00859           (void)nco_var_nrm(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]->tally,var_prc_out[idx]->val);
00860           break;
00861         case nco_op_rmssdn: /* Normalize sum of squares by tally-1 to create mean square for sdn */
00862           (void)nco_var_nrm_sdn(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]->tally,var_prc_out[idx]->val);
00863           break;
00864         case nco_op_min: /* Minimum is already in buffer, do nothing */
00865         case nco_op_max: /* Maximum is already in buffer, do nothing */ 
00866         case nco_op_ttl: /* Total is already in buffer, do nothing */   
00867           break;
00868         default:
00869           (void)fprintf(fp_stdout,"%s: ERROR Illegal nco_op_typ in non-weighted normalization\n",prg_nm);
00870           nco_exit(EXIT_FAILURE);
00871           break;
00872         } /* end switch */
00873       }else if(!NRM_BY_DNM){
00874         /* Normalization has been turned off by user, we are done */
00875         ;
00876       }else{
00877         (void)fprintf(fp_stdout,"%s: ERROR Unforeseen logical branch in main()\n",prg_nm);
00878         nco_exit(EXIT_FAILURE);
00879       } /* end if */
00880       /* Some non-linear operations require additional processing */
00881       switch(nco_op_typ){
00882       case nco_op_sqravg: /* Square mean to create square of the mean (for sdn) */
00883         (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);
00884         break;
00885       case nco_op_sqrt: /* Take root of mean to create root mean */
00886       case nco_op_rms: /* Take root of mean of sum of squares to create root mean square */
00887       case nco_op_rmssdn: /* Take root of sdn mean of sum of squares to create root mean square for sdn */
00888         (void)nco_var_sqrt(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]->tally,var_prc_out[idx]->val,var_prc_out[idx]->val);  
00889         break;
00890       default:
00891         break;
00892       } /* end switch */
00893       /* Free tally buffer */
00894       var_prc_out[idx]->tally=(long *)nco_free(var_prc_out[idx]->tally);
00895       
00896       /* Revert any arithmetic promotion but leave unpacked (for now) */
00897       var_prc_out[idx]=nco_var_cnf_typ(var_prc_out[idx]->typ_upk,var_prc_out[idx]);
00898       
00899 #ifdef _OPENMP
00900 #pragma omp critical
00901 #endif /* _OPENMP */
00902       { /* begin OpenMP critical */
00903         /* Copy average to output file then free averaging buffer */
00904         if(var_prc_out[idx]->nbr_dim == 0){
00905           (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);
00906         }else{ /* end if variable is scalar */
00907           (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);
00908         } /* end if variable is array */
00909       } /* end OpenMP critical */
00910 
00911       /* Free current output buffer */
00912       var_prc_out[idx]->val.vp=nco_free(var_prc_out[idx]->val.vp);
00913       
00914     } /* end (OpenMP parallel for) loop over idx */
00915     
00916     if(dbg_lvl > 0) (void)fprintf(stderr,"\n");
00917     
00918     /* Close input netCDF file */
00919     for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_arr[thr_idx]);
00920     
00921     /* Remove local copy of file */
00922     if(FILE_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in);
00923     
00924   } /* end loop over fl_idx */
00925   
00926   /* Close output file and move it from temporary to permanent location */
00927   (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id);
00928   
00929   /* ncwa-unique memory */
00930   if(dmn_avg_nbr > 0) dmn_avg=(dmn_sct **)nco_free(dmn_avg);
00931   if(msk != NULL) msk=nco_var_free(msk);
00932   if(msk_nm != NULL) msk_nm=(char *)nco_free(msk_nm);
00933   if(msk_out != NULL) msk_out=nco_var_free(msk_out);
00934   if(msk_sng != NULL) msk_sng=(char *)nco_free(msk_sng);
00935   if(wgt != NULL) wgt=nco_var_free(wgt);
00936   if(wgt_avg != NULL) wgt_avg=nco_var_free(wgt_avg);
00937   if(wgt_nm != NULL) wgt_nm=(char *)nco_free(wgt_nm);
00938   if(wgt_out != NULL) wgt_out=nco_var_free(wgt_out);
00939 
00940   /* NCO-generic clean-up */
00941   /* Free individual strings/arrays */
00942   if(cmd_ln != NULL) cmd_ln=(char *)nco_free(cmd_ln);
00943   if(fl_in != NULL) fl_in=(char *)nco_free(fl_in);
00944   if(fl_out != NULL) fl_out=(char *)nco_free(fl_out);
00945   if(fl_out_tmp != NULL) fl_out_tmp=(char *)nco_free(fl_out_tmp);
00946   if(fl_pth != NULL) fl_pth=(char *)nco_free(fl_pth);
00947   if(fl_pth_lcl != NULL) fl_pth_lcl=(char *)nco_free(fl_pth_lcl);
00948   if(in_id_arr != NULL) in_id_arr=(int *)nco_free(in_id_arr);
00949   /* Free lists of strings */
00950   if(fl_lst_in != NULL && fl_lst_abb == NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,fl_nbr); 
00951   if(fl_lst_in != NULL && fl_lst_abb != NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,1);
00952   if(fl_lst_abb != NULL) fl_lst_abb=nco_sng_lst_free(fl_lst_abb,abb_arg_nbr);
00953   if(var_lst_in_nbr > 0) var_lst_in=nco_sng_lst_free(var_lst_in,var_lst_in_nbr);
00954   /* Free limits */
00955   for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]);
00956   if(lmt_nbr > 0) lmt=nco_lmt_lst_free(lmt,lmt_nbr);
00957   /* Free dimension lists */
00958   if(nbr_dmn_xtr > 0) dim=nco_dmn_lst_free(dim,nbr_dmn_xtr);
00959   if(nbr_dmn_out > 0) dmn_out=nco_dmn_lst_free(dmn_out,nbr_dmn_out);
00960   /* Free variable lists */
00961   if(nbr_xtr > 0) var=nco_var_lst_free(var,nbr_xtr); 
00962   /* ncwa uses nco_var_lst_free() on var_prc_out because var_out has dangling pointers */
00963   if(nbr_var_fix > 0) var_fix_out=nco_var_lst_free(var_fix_out,nbr_var_fix);
00964   if(nbr_var_prc > 0) var_prc_out=nco_var_lst_free(var_prc_out,nbr_var_prc);
00965   var_prc=(var_sct **)nco_free(var_prc);
00966   var_fix=(var_sct **)nco_free(var_fix);
00967   var_out=(var_sct **)nco_free(var_out);
00968 
00969   nco_exit_gracefully();
00970   return EXIT_SUCCESS;
00971 } /* end main() */


Variable Documentation

char** ncap_fl_spt_glb
 

Definition at line 73 of file ncwa.c.

size_t* ncap_ln_nbr_crr
 

Definition at line 72 of file ncwa.c.

size_t ncap_ncl_dpt_crr = 0UL
 

Definition at line 71 of file ncwa.c.


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