nco/mpncwa.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 mpncwa.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 70 of file mpncwa.c.


Function Documentation

int main int  argc,
char **  argv
 

Definition at line 80 of file mpncwa.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, var_sct_tag::id, dmn_sct_tag::id, idx_all_wrk_ass, prs_sct::in_id, int_CEWI, var_sct_tag::is_crd_var, ptr_unn::lp, lst_prs_2D(), msg_bfr_lng, msg_tag_tkn_wrt_rqs, msg_tag_tkn_wrt_rsp, msg_tag_wrk_rqs, msg_tag_wrk_rsp, 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_SHARE, NC_SHORT, NC_WRITE, ncap_ln_nbr_crr, ncap_ncl_dpt_crr, ncap_ncwa_scn(), nco_att_cpy(), nco_bool, nco_close(), nco_cmd_ln_sng(), nco_cnt_run(), 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_mv(), 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_mpi_att_cat(), 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_spn_lck_brk, nco_spn_lck_us, 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, rnk_mgr, ptr_unn::sp, prs_sct::sym_tbl, prs_sct::sym_tbl_nbr, var_sct_tag::sz, var_sct_tag::tally, tkn_wrt_rqs_dny, tkn_wrt_rqs_ntv, tkn_wrt_rqs_xcp, True, var_sct_tag::type, type, option::val, var_sct_tag::val, prs_sct::var_LHS, ptr_unn::vp, and wrk_id_bfr_lng.

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


Variable Documentation

char** ncap_fl_spt_glb
 

Definition at line 77 of file mpncwa.c.

size_t* ncap_ln_nbr_crr
 

Definition at line 76 of file mpncwa.c.

size_t ncap_ncl_dpt_crr = 0UL
 

Definition at line 75 of file mpncwa.c.


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