nco/mpncecat.c File Reference

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

Include dependency graph for mpncecat.c:

Go to the source code of this file.

Defines

#define MAIN_PROGRAM_FILE

Functions

int main (int argc, char **argv)


Define Documentation

#define MAIN_PROGRAM_FILE
 

Definition at line 61 of file mpncecat.c.


Function Documentation

int main int  argc,
char **  argv
 

Definition at line 65 of file mpncecat.c.

References var_sct_tag::cnt, dmn_sct_tag::cnt, copyright_prn(), var_sct_tag::dim, var_sct_tag::dmn_id, var_sct_tag::end, dmn_sct_tag::end, EXIT_FAILURE, EXIT_SUCCESS, False, FILE, getopt_long, var_sct_tag::id, dmn_sct_tag::id, idx_all_wrk_ass, int_CEWI, dmn_sct_tag::is_crd_dmn, dmn_sct_tag::is_rec_dmn, var_sct_tag::is_rec_var, lst_prs_2D(), MPI_Comm, MPI_Info, msg_bfr_lng, msg_tag_tkn_wrt_rqs, msg_tag_tkn_wrt_rsp, msg_tag_wrk_rqs, msg_tag_wrk_rsp, option::name, var_sct_tag::nbr_dim, NC_FORMAT_64BIT, NC_FORMAT_CLASSIC, NC_FORMAT_NETCDF4, NC_GLOBAL, dmn_sct_tag::nc_id, NC_MAX_DIMS, NC_MPIIO, NC_NETCDF4, NC_NOERR, NC_NOFILL, NC_NOWRITE, NC_SHARE, NC_WRITE, 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_dmn_dfn(), nco_dmn_dpl(), nco_dmn_fll(), nco_dmn_lmt_mrg(), nco_dmn_lst_ass_var(), nco_dmn_lst_free(), nco_dmn_xrf(), nco_enddef(), nco_err_exit(), nco_exit(), nco_exit_gracefully(), nco_fl_cmp_err_chk(), nco_fl_lst_att_cat(), nco_fl_lst_mk(), nco_fl_mk_lcl(), nco_fl_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_lbr_vrs_prn(), nco_lmt_evl(), nco_lmt_lst_free(), nco_lmt_prs(), nco_lst_comma2hash(), nco_lst_srt_nm_id(), nco_malloc(), nco_mpi_att_cat(), nco_nm_id_lst_free(), nco_open(), nco_openmp_ini(), nco_pck_map_nil, nco_pck_plc_nil, 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_usg_prn(), nco_var_dfn(), nco_var_dpl(), nco_var_fll(), nco_var_get(), nco_var_lst_add_crd(), nco_var_lst_ass_crd_add(), nco_var_lst_dvd(), nco_var_lst_free(), nco_var_lst_mk(), nco_var_lst_xcl(), nco_var_mtd_refresh(), nco_var_srt_zero(), nco_var_val_cpy(), nco_xrf_dmn(), nco_xrf_var(), dmn_sct_tag::nm, no_argument, NULL_CEWI, omp_get_thread_num(), optarg, optind, prg_nm_get(), prg_prs(), required_argument, rnk_mgr, var_sct_tag::srt, dmn_sct_tag::srt, var_sct_tag::sz, dmn_sct_tag::sz, var_sct_tag::sz_rec, tkn_wrt_rqs_dny, tkn_wrt_rqs_ntv, tkn_wrt_rqs_xcp, True, var_sct_tag::type, var_sct_tag::val, option::val, dmn_sct_tag::val, ptr_unn::vp, wrk_id_bfr_lng, and dmn_sct_tag::xrf.

00066 {
00067   nco_bool EXCLUDE_INPUT_LIST=False; /* Option c */
00068   nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */
00069   nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */
00070   nco_bool FILE_RETRIEVED_FROM_REMOTE_LOCATION;
00071   nco_bool FL_LST_IN_APPEND=True; /* Option H */
00072   nco_bool FL_LST_IN_FROM_STDIN=False; /* [flg] fl_lst_in comes from stdin */
00073   nco_bool FORCE_APPEND=False; /* Option A */
00074   nco_bool FORCE_OVERWRITE=False; /* Option O */
00075   nco_bool FORTRAN_IDX_CNV=False; /* Option F */
00076   nco_bool HISTORY_APPEND=True; /* Option h */
00077   nco_bool CNV_CCM_CCSM_CF;
00078   nco_bool REMOVE_REMOTE_FILES_AFTER_PROCESSING=True; /* Option R */
00079   
00080   char **fl_lst_abb=NULL; /* Option a */
00081   char **fl_lst_in;
00082   char **var_lst_in=NULL_CEWI;
00083   char *cmd_ln;
00084   char *fl_in=NULL;
00085   char *fl_out=NULL; /* Option o */
00086   char *fl_out_tmp=NULL; /* MPI CEWI */
00087   char *fl_pth=NULL; /* Option p */
00088   char *fl_pth_lcl=NULL; /* Option l */
00089   char *lmt_arg[NC_MAX_DIMS];
00090   char *opt_crr=NULL; /* [sng] String representation of current long-option name */
00091   char *optarg_lcl=NULL; /* [sng] Local copy of system optarg */
00092   char *time_bfr_srt;
00093   
00094   const char * const CVS_Id="$Id: mpncecat.c,v 1.35 2006/02/19 00:42:34 zender Exp $"; 
00095   const char * const CVS_Revision="$Revision: 1.35 $";
00096   const char * const opt_sht_lst="4ACcD:d:FHhl:n:Oo:p:rRSt:v:x-:";
00097   
00098   dmn_sct *rec_dmn;
00099   dmn_sct **dim;
00100   dmn_sct **dmn_out;
00101   
00102   extern char *optarg;
00103   extern int optind;
00104   
00105   /* Using naked stdin/stdout/stderr in parallel region generates warning
00106      Copy appropriate filehandle to variable scoped shared in parallel clause */
00107   FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */
00108   FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */
00109 
00110   int *in_id_arr;
00111 
00112   int abb_arg_nbr=0;
00113   int fl_idx;
00114   int fl_nbr=0;
00115   int fl_out_fmt=NC_FORMAT_CLASSIC; /* [enm] Output file format */
00116   int fll_md_old; /* [enm] Old fill mode */
00117   int idx;
00118   int in_id;  
00119   int lmt_nbr=0; /* Option d. NB: lmt_nbr gets incremented */
00120   int nbr_dmn_fl;
00121   int nbr_dmn_xtr;
00122   int nbr_var_fix; /* nbr_var_fix gets incremented */
00123   int nbr_var_fl;
00124   int nbr_var_prc; /* nbr_var_prc gets incremented */
00125   int nbr_xtr=0; /* nbr_xtr won't otherwise be set for -c with no -v */
00126   int opt;
00127   int out_id;
00128   int rcd=NC_NOERR; /* [rcd] Return code */
00129   int rec_dmn_id=NCO_REC_DMN_UNDEFINED;
00130   int thr_idx; /* [idx] Index of current thread */
00131   int thr_nbr=int_CEWI; /* [nbr] Thread number Option t */
00132   int var_lst_in_nbr=0;
00133   
00134   lmt_sct **lmt;
00135   
00136   long idx_rec_out=0L; /* idx_rec_out gets incremented */
00137   
00138   nm_id_sct *dmn_lst;
00139   nm_id_sct *xtr_lst=NULL; /* xtr_lst may be alloc()'d from NULL with -c option */
00140   
00141   time_t time_crr_time_t;
00142   
00143   var_sct **var;
00144   var_sct **var_fix;
00145   var_sct **var_fix_out;
00146   var_sct **var_out;
00147   var_sct **var_prc;
00148   var_sct **var_prc_out;
00149   
00150 #ifdef ENABLE_MPI
00151   /* Declare all MPI-specific variables here */
00152   MPI_Comm mpi_cmm=MPI_COMM_WORLD; /* [prc] Communicator */
00153 #if defined(ENABLE_NETCDF4) || defined(ENABLE_PNETCDF)
00154   MPI_Info mpi_nfo=MPI_INFO_NULL; /* [sct] File geometry hints */
00155 #endif /* !ENABLE_NETCDF4 || !ENABLE_PNETCDF */
00156   MPI_Status mpi_stt; /* [enm] Status check to decode msg_tag_typ */
00157 
00158   bool TKN_WRT_FREE=True; /* [flg] Write-access to output file is available */
00159   
00160   const double tkn_wrt_rqs_ntv=0.04; /* [s] Token request interval */
00161   
00162   const int msg_bfr_lng=3; /* [nbr] Number of elements in msg_bfr */
00163   const int wrk_id_bfr_lng=1; /* [nbr] Number of elements in wrk_id_bfr */
00164 
00165   int fl_nm_lng; /* [nbr] Output file name length */
00166   int msg_bfr[msg_bfr_lng]; /* [bfr] Buffer containing var, idx, tkn_wrt_rsp */
00167   int msg_tag_typ; /* [enm] MPI message tag type */
00168   int prc_rnk; /* [idx] Process rank */
00169   int prc_nbr=0; /* [nbr] Number of MPI processes */
00170   int tkn_wrt_rsp; /* [enm] Response to request for write token */
00171   int var_wrt_nbr=0; /* [nbr] Variables written to output file until now */
00172   int rnk_wrk; /* [idx] Worker rank */
00173   int wrk_id_bfr[wrk_id_bfr_lng]; /* [bfr] Buffer for rnk_wrk */
00174 #endif /* !ENABLE_MPI */
00175 
00176   static struct option opt_lng[]=
00177     { /* Structure ordered by short option key if possible */
00178       /* Long options with no argument, no short option counterpart */
00179       /* Long options with argument, no short option counterpart */
00180       {"fl_fmt",required_argument,0,0},
00181       {"file_format",required_argument,0,0},
00182       /* Long options with short counterparts */
00183       {"4",no_argument,0,'4'},
00184       {"64bit",no_argument,0,'4'},
00185       {"netcdf4",no_argument,0,'4'},
00186       {"append",no_argument,0,'A'},
00187       {"coords",no_argument,0,'c'},
00188       {"crd",no_argument,0,'c'},
00189       {"no-coords",no_argument,0,'C'},
00190       {"no-crd",no_argument,0,'C'},
00191       {"debug",required_argument,0,'D'},
00192       {"dbg_lvl",required_argument,0,'D'},
00193       {"dimension",required_argument,0,'d'},
00194       {"dmn",required_argument,0,'d'},
00195       {"fortran",no_argument,0,'F'},
00196       {"ftn",no_argument,0,'F'},
00197       {"fl_lst_in",no_argument,0,'H'},
00198       {"file_list",no_argument,0,'H'},
00199       {"history",no_argument,0,'h'},
00200       {"hst",no_argument,0,'h'},
00201       {"local",required_argument,0,'l'},
00202       {"lcl",required_argument,0,'l'},
00203       {"nintap",required_argument,0,'n'},
00204       {"overwrite",no_argument,0,'O'},
00205       {"ovr",no_argument,0,'O'},
00206       {"output",required_argument,0,'o'},
00207       {"fl_out",required_argument,0,'o'},
00208       {"path",required_argument,0,'p'},
00209       {"retain",no_argument,0,'R'},
00210       {"rtn",no_argument,0,'R'},
00211       {"revision",no_argument,0,'r'},
00212       {"suspend", no_argument,0,'S'},
00213       {"thr_nbr",required_argument,0,'t'},
00214       {"threads",required_argument,0,'t'},
00215       {"omp_num_threads",required_argument,0,'t'},
00216       {"variable",required_argument,0,'v'},
00217       {"version",no_argument,0,'r'},
00218       {"vrs",no_argument,0,'r'},
00219       {"exclude",no_argument,0,'x'},
00220       {"xcl",no_argument,0,'x'},
00221       {"help",no_argument,0,'?'},
00222       {0,0,0,0}
00223     }; /* end opt_lng */
00224   int opt_idx=0; /* Index of current long option into opt_lng array */
00225   
00226 #ifdef ENABLE_MPI
00227   /* MPI Initialization */
00228   MPI_Init(&argc,&argv);
00229   MPI_Comm_size(mpi_cmm,&prc_nbr);
00230   MPI_Comm_rank(mpi_cmm,&prc_rnk);
00231 #endif /* !ENABLE_MPI */
00232   
00233   /* Start clock and save command line */ 
00234   cmd_ln=nco_cmd_ln_sng(argc,argv);
00235   time_crr_time_t=time((time_t *)NULL);
00236   time_bfr_srt=ctime(&time_crr_time_t); time_bfr_srt=time_bfr_srt; /* Avoid compiler warning until variable is used for something */
00237   
00238   /* Get program name and set program enum (e.g., prg=ncra) */
00239   prg_nm=prg_prs(argv[0],&prg);
00240   
00241   /* Parse command line arguments */
00242   while(1){
00243     /* getopt_long_only() allows one dash to prefix long options */
00244     opt=getopt_long(argc,argv,opt_sht_lst,opt_lng,&opt_idx);
00245     /* NB: access to opt_crr is only valid when long_opt is detected */
00246     if(opt == EOF) break; /* Parse positional arguments once getopt_long() returns EOF */
00247     opt_crr=(char *)strdup(opt_lng[opt_idx].name);
00248 
00249     /* Process long options without short option counterparts */
00250     if(opt == 0){
00251       if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt);
00252     } /* opt != 0 */
00253     /* Process short options */
00254     switch(opt){
00255     case 0: /* Long options have already been processed, return */
00256       break;
00257     case '4': /* [flg] Catch-all to prescribe output storage format */
00258       if(!strcmp(opt_crr,"64bit")) fl_out_fmt=NC_FORMAT_64BIT; else fl_out_fmt=NC_FORMAT_NETCDF4; 
00259       break;
00260     case 'A': /* Toggle FORCE_APPEND */
00261       FORCE_APPEND=!FORCE_APPEND;
00262       break;
00263     case 'C': /* Extract all coordinates associated with extracted variables? */
00264       EXTRACT_ASSOCIATED_COORDINATES=False;
00265       break;
00266     case 'c':
00267       EXTRACT_ALL_COORDINATES=True;
00268       break;
00269     case 'D': /* Debugging level. Default is 0. */
00270       dbg_lvl=(unsigned short)strtol(optarg,(char **)NULL,10);
00271       break;
00272     case 'd': /* Copy argument for later processing */
00273       lmt_arg[lmt_nbr]=(char *)strdup(optarg);
00274       lmt_nbr++;
00275       break;
00276     case 'F': /* Toggle index convention. Default is 0-based arrays (C-style). */
00277       FORTRAN_IDX_CNV=!FORTRAN_IDX_CNV;
00278       break;
00279     case 'H': /* Toggle writing input file list attribute */
00280       FL_LST_IN_APPEND=!FL_LST_IN_APPEND;
00281       break;
00282     case 'h': /* Toggle appending to history global attribute */
00283       HISTORY_APPEND=!HISTORY_APPEND;
00284       break;
00285     case 'l': /* Local path prefix for files retrieved from remote file system */
00286       fl_pth_lcl=(char *)strdup(optarg);
00287       break;
00288     case 'n': /* NINTAP-style abbreviation of files to process */
00289       fl_lst_abb=lst_prs_2D(optarg,",",&abb_arg_nbr);
00290       if(abb_arg_nbr < 1 || abb_arg_nbr > 5){
00291         (void)fprintf(stdout,"%s: ERROR Incorrect abbreviation for file list\n",prg_nm);
00292         (void)nco_usg_prn();
00293         nco_exit(EXIT_FAILURE);
00294       } /* end if */
00295       break;
00296     case 'O': /* Toggle FORCE_OVERWRITE */
00297       FORCE_OVERWRITE=!FORCE_OVERWRITE;
00298       break;
00299     case 'o': /* Name of output file */
00300       fl_out=(char *)strdup(optarg);
00301       break;
00302     case 'p': /* Common file path */
00303       fl_pth=(char *)strdup(optarg);
00304       break;
00305     case 'R': /* Toggle removal of remotely-retrieved-files. Default is True. */
00306       REMOVE_REMOTE_FILES_AFTER_PROCESSING=!REMOVE_REMOTE_FILES_AFTER_PROCESSING;
00307       break;
00308     case 'r': /* Print CVS program information and copyright notice */
00309       (void)copyright_prn(CVS_Id,CVS_Revision);
00310       (void)nco_lbr_vrs_prn();
00311       nco_exit(EXIT_SUCCESS);
00312       break;
00313 #ifdef ENABLE_MPI
00314     case 'S': /* Suspend with signal handler to facilitate debugging */
00315       if(signal(SIGUSR1,nco_cnt_run) == SIG_ERR) (void)fprintf(fp_stdout,"%s: ERROR Could not install suspend handler.\n",prg_nm);
00316       while(!nco_spn_lck_brk) usleep(nco_spn_lck_us); /* Spinlock. fxm: should probably insert a sched_yield */
00317       break;
00318 #endif /* !ENABLE_MPI */
00319     case 't': /* Thread number */
00320       thr_nbr=(int)strtol(optarg,(char **)NULL,10);
00321       break;
00322     case 'v': /* Variables to extract/exclude */
00323       /* Replace commas with hashes when within braces (convert back later) */
00324       optarg_lcl=(char *)strdup(optarg);
00325       (void)nco_lst_comma2hash(optarg_lcl);
00326       var_lst_in=lst_prs_2D(optarg_lcl,",",&var_lst_in_nbr);
00327       optarg_lcl=(char *)nco_free(optarg_lcl);
00328       nbr_xtr=var_lst_in_nbr;
00329       break;
00330     case 'x': /* Exclude rather than extract variables specified with -v */
00331       EXCLUDE_INPUT_LIST=True;
00332       break;
00333     case '?': /* Print proper usage */
00334       (void)nco_usg_prn();
00335       nco_exit(EXIT_SUCCESS);
00336       break;
00337     case '-': /* Long options are not allowed */
00338       (void)fprintf(stderr,"%s: ERROR Long options are not available in this build. Use single letter options instead.\n",prg_nm_get());
00339       nco_exit(EXIT_FAILURE);
00340       break;
00341     default: /* Print proper usage */
00342       (void)nco_usg_prn();
00343       nco_exit(EXIT_FAILURE);
00344       break;
00345     } /* end switch */
00346     if(opt_crr != NULL) opt_crr=(char *)nco_free(opt_crr);
00347   } /* end while loop */
00348   
00349   /* Process positional arguments and fill in filenames */
00350   fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN);
00351   
00352   /* Make uniform list of user-specified dimension limits */
00353   lmt=nco_lmt_prs(lmt_nbr,lmt_arg);
00354     
00355   /* Initialize thread information */
00356   thr_nbr=nco_openmp_ini(thr_nbr);
00357   in_id_arr=(int *)nco_malloc(thr_nbr*sizeof(int));
00358 
00359   /* Parse filename */
00360   fl_in=nco_fl_nm_prs(fl_in,0,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth);
00361   /* Make sure file is on local system and is readable or die trying */
00362   fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION);
00363   /* Open file for reading */
00364   rcd=nco_open(fl_in,NC_NOWRITE,&in_id);
00365   
00366   /* Get number of variables, dimensions, and record dimension ID of input file */
00367   (void)nco_inq(in_id,&nbr_dmn_fl,&nbr_var_fl,(int *)NULL,&rec_dmn_id);
00368   
00369   /* Form initial extraction list which may include extended regular expressions */
00370   xtr_lst=nco_var_lst_mk(in_id,nbr_var_fl,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr);
00371   
00372   /* Change included variables to excluded variables */
00373   if(EXCLUDE_INPUT_LIST) xtr_lst=nco_var_lst_xcl(in_id,nbr_var_fl,xtr_lst,&nbr_xtr);
00374   
00375   /* Add all coordinate variables to extraction list */
00376   if(EXTRACT_ALL_COORDINATES) xtr_lst=nco_var_lst_add_crd(in_id,nbr_dmn_fl,xtr_lst,&nbr_xtr);
00377   
00378   /* Make sure coordinates associated extracted variables are also on extraction list */
00379   if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst=nco_var_lst_ass_crd_add(in_id,xtr_lst,&nbr_xtr);
00380   
00381   /* Sort extraction list by variable ID for fastest I/O */
00382   if(nbr_xtr > 1) xtr_lst=nco_lst_srt_nm_id(xtr_lst,nbr_xtr,False);
00383   
00384   /* We now have final list of variables to extract. Phew. */
00385   
00386   /* Find coordinate/dimension values associated with user-specified limits
00387      NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */
00388   for(idx=0;idx<lmt_nbr;idx++) (void)nco_lmt_evl(in_id,lmt[idx],0L,FORTRAN_IDX_CNV);
00389   
00390   /* Find dimensions associated with variables to be extracted */
00391   dmn_lst=nco_dmn_lst_ass_var(in_id,xtr_lst,nbr_xtr,&nbr_dmn_xtr);
00392   
00393   /* Fill in dimension structure for all extracted dimensions */
00394   dim=(dmn_sct **)nco_malloc(nbr_dmn_xtr*sizeof(dmn_sct *));
00395   for(idx=0;idx<nbr_dmn_xtr;idx++) dim[idx]=nco_dmn_fll(in_id,dmn_lst[idx].id,dmn_lst[idx].nm);
00396   /* Dimension list no longer needed */
00397   dmn_lst=nco_nm_id_lst_free(dmn_lst,nbr_dmn_xtr);
00398   
00399   /* Merge hyperslab limit information into dimension structures */
00400   if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim,nbr_dmn_xtr,lmt,lmt_nbr);
00401   
00402   /* Duplicate input dimension structures for output dimension structures */
00403   dmn_out=(dmn_sct **)nco_malloc(nbr_dmn_xtr*sizeof(dmn_sct *));
00404   for(idx=0;idx<nbr_dmn_xtr;idx++){
00405     dmn_out[idx]=nco_dmn_dpl(dim[idx]);
00406     (void)nco_dmn_xrf(dim[idx],dmn_out[idx]); 
00407   } /* end loop over idx */
00408   
00409   /* Is this an CCM/CCSM/CF-format history tape? */
00410   CNV_CCM_CCSM_CF=nco_cnv_ccm_ccsm_cf_inq(in_id);
00411   
00412   /* Fill in variable structure list for all extracted variables */
00413   var=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *));
00414   var_out=(var_sct **)nco_malloc(nbr_xtr*sizeof(var_sct *));
00415   for(idx=0;idx<nbr_xtr;idx++){
00416     var[idx]=nco_var_fll(in_id,xtr_lst[idx].id,xtr_lst[idx].nm,dim,nbr_dmn_xtr);
00417     var_out[idx]=nco_var_dpl(var[idx]);
00418     (void)nco_xrf_var(var[idx],var_out[idx]);
00419     (void)nco_xrf_dmn(var_out[idx]);
00420   } /* end loop over idx */
00421   /* Extraction list no longer needed */
00422   xtr_lst=nco_nm_id_lst_free(xtr_lst,nbr_xtr);
00423   
00424   /* Divide variable lists into lists of fixed variables and variables to be processed */
00425   (void)nco_var_lst_dvd(var,var_out,nbr_xtr,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,(dmn_sct **)NULL,0,&var_fix,&var_fix_out,&nbr_var_fix,&var_prc,&var_prc_out,&nbr_var_prc);
00426   
00427 #ifdef ENABLE_MPI
00428   if(prc_rnk == rnk_mgr){ /* MPI manager code */
00429 #endif /* !ENABLE_MPI */
00430     /* Open output file */
00431     fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&out_id);
00432     
00433     /* Copy global attributes */
00434     (void)nco_att_cpy(in_id,out_id,NC_GLOBAL,NC_GLOBAL,True);
00435     
00436     /* Catenate time-stamped command line to "history" global attribute */
00437     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
00438     
00439     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
00440     
00441 #ifdef ENABLE_MPI
00442     /* Initialize MPI task information */
00443     if(prc_nbr > 0 && HISTORY_APPEND) (void)nco_mpi_att_cat(out_id,prc_nbr);
00444 #endif /* !ENABLE_MPI */
00445     
00446     /* Add input file list global attribute */
00447     if(FL_LST_IN_APPEND  && HISTORY_APPEND && FL_LST_IN_FROM_STDIN) (void)nco_fl_lst_att_cat(out_id,fl_lst_in,fl_nbr);
00448     
00449 #ifdef ENABLE_MPI
00450   } /* prc_rnk != rnk_mgr */
00451 #endif /* !ENABLE_MPI */
00452   
00453   /* ncecat-specific operations */
00454   if(True){
00455     
00456     /* Always construct new "record" dimension from scratch */
00457     rec_dmn=(dmn_sct *)nco_malloc(sizeof(dmn_sct));
00458     rec_dmn->nm=(char *)strdup("record");
00459     rec_dmn->id=-1;
00460     rec_dmn->nc_id=-1;
00461     rec_dmn->xrf=NULL;
00462     rec_dmn->val.vp=NULL;
00463     rec_dmn->is_crd_dmn=False;
00464     rec_dmn->is_rec_dmn=True;
00465     rec_dmn->sz=0L;
00466     rec_dmn->cnt=0L;
00467     rec_dmn->srt=0L;
00468     rec_dmn->end=rec_dmn->sz-1L;
00469     
00470     /* Change existing record dimension, if any, to regular dimension */
00471     for(idx=0;idx<nbr_dmn_xtr;idx++){
00472       /* Is any input dimension a record dimension? */
00473       if(dmn_out[idx]->is_rec_dmn){
00474         dmn_out[idx]->is_rec_dmn=False;
00475         break;
00476       } /* end if */
00477     } /* end loop over idx */
00478     
00479     /* Add record dimension to end of dimension list */
00480     nbr_dmn_xtr++;
00481     dmn_out=(dmn_sct **)nco_realloc(dmn_out,nbr_dmn_xtr*sizeof(dmn_sct **));
00482     dmn_out[nbr_dmn_xtr-1]=rec_dmn;
00483     
00484   } /* end if */
00485   
00486 #ifdef ENABLE_MPI
00487   if(prc_rnk == rnk_mgr){ /* MPI manager code */
00488 #endif /* !ENABLE_MPI */
00489     /* Define dimensions in output file */
00490     (void)nco_dmn_dfn(fl_out,out_id,dmn_out,nbr_dmn_xtr);
00491 #ifdef ENABLE_MPI
00492   } /* prc_rnk != rnk_mgr */
00493 #endif /* !ENABLE_MPI */
00494   
00495   if(True){
00496     /* Prepend record dimension to beginning of all vectors for processed variables */
00497     for(idx=0;idx<nbr_var_prc;idx++){
00498       var_prc_out[idx]->nbr_dim++;
00499       var_prc_out[idx]->is_rec_var=True;
00500       var_prc_out[idx]->sz_rec=var_prc_out[idx]->sz;
00501       
00502       /* Allocate space to hold dimension IDs */
00503       var_prc_out[idx]->dim=(dmn_sct **)nco_realloc(var_prc_out[idx]->dim,var_prc_out[idx]->nbr_dim*sizeof(dmn_sct *));
00504       var_prc_out[idx]->dmn_id=(int *)nco_realloc(var_prc_out[idx]->dmn_id,var_prc_out[idx]->nbr_dim*sizeof(int));
00505       var_prc_out[idx]->cnt=(long *)nco_realloc(var_prc_out[idx]->cnt,var_prc_out[idx]->nbr_dim*sizeof(long));
00506       var_prc_out[idx]->srt=(long *)nco_realloc(var_prc_out[idx]->srt,var_prc_out[idx]->nbr_dim*sizeof(long));
00507       var_prc_out[idx]->end=(long *)nco_realloc(var_prc_out[idx]->end,var_prc_out[idx]->nbr_dim*sizeof(long));
00508       
00509       /* Move current array by one to make room for new record dimension info */
00510       (void)memmove((void *)(var_prc_out[idx]->dim+1),(void *)(var_prc_out[idx]->dim),(var_prc_out[idx]->nbr_dim-1)*sizeof(dmn_sct *));
00511       (void)memmove((void *)(var_prc_out[idx]->dmn_id+1),(void *)(var_prc_out[idx]->dmn_id),(var_prc_out[idx]->nbr_dim-1)*sizeof(int));
00512       (void)memmove((void *)(var_prc_out[idx]->cnt+1),(void *)(var_prc_out[idx]->cnt),(var_prc_out[idx]->nbr_dim-1)*sizeof(long));
00513       (void)memmove((void *)(var_prc_out[idx]->srt+1),(void *)(var_prc_out[idx]->srt),(var_prc_out[idx]->nbr_dim-1)*sizeof(long));
00514       (void)memmove((void *)(var_prc_out[idx]->end+1),(void *)(var_prc_out[idx]->end),(var_prc_out[idx]->nbr_dim-1)*sizeof(long));
00515       
00516       /* Insert value for new record dimension */
00517       var_prc_out[idx]->dim[0]=rec_dmn;
00518       var_prc_out[idx]->dmn_id[0]=rec_dmn->id;
00519       var_prc_out[idx]->cnt[0]=1L;
00520       var_prc_out[idx]->srt[0]=-1L;
00521       var_prc_out[idx]->end[0]=-1L;
00522       
00523     } /* end loop over idx */
00524     
00525   } /* end if */
00526   
00527 #ifdef ENABLE_MPI
00528   if(prc_rnk == rnk_mgr){ /* MPI manager code */
00529 #endif /* !ENABLE_MPI */
00530     /* Define variables in output file, copy their attributes */
00531     (void)nco_var_dfn(in_id,fl_out,out_id,var_out,nbr_xtr,(dmn_sct **)NULL,(int)0,nco_pck_plc_nil,nco_pck_map_nil);
00532 #ifdef ENABLE_MPI
00533   } /* prc_rnk != rnk_mgr */
00534 #endif /* !ENABLE_MPI */
00535   
00536   /* Zero start vectors for all output variables */
00537   (void)nco_var_srt_zero(var_out,nbr_xtr);
00538   
00539 #ifdef ENABLE_MPI
00540   if(prc_rnk == rnk_mgr){ /* prc_rnk != rnk_mgr */
00541 #endif /* !ENABLE_MPI */
00542     
00543     /* Turn off default filling behavior to enhance efficiency */
00544     rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old);
00545     
00546     /* Take output file out of define mode */
00547     (void)nco_enddef(out_id);
00548     
00549 #ifdef ENABLE_MPI
00550   } /* prc_rnk != rnk_mgr */
00551   
00552   /* Manager obtains output filename and broadcasts to workers */
00553   if(prc_rnk == rnk_mgr) fl_nm_lng=(int)strlen(fl_out_tmp);
00554   MPI_Bcast(&fl_nm_lng,1,MPI_INT,0,mpi_cmm);
00555   if(prc_rnk != rnk_mgr) fl_out_tmp=(char *)malloc((fl_nm_lng+1)*sizeof(char));
00556   MPI_Bcast(fl_out_tmp,fl_nm_lng+1,MPI_CHAR,0,mpi_cmm);
00557   
00558   if(prc_rnk == rnk_mgr){ /* MPI manager code */
00559     TKN_WRT_FREE=False;
00560 #endif /* !ENABLE_MPI */
00561     /* Copy variable data for non-processed variables */
00562     (void)nco_var_val_cpy(in_id,out_id,var_fix,nbr_var_fix);
00563 #ifdef ENABLE_MPI
00564     /* Close output file so workers can open it */
00565     nco_close(out_id);
00566     TKN_WRT_FREE=True;
00567   } /* prc_rnk != rnk_mgr */
00568 #endif /* !ENABLE_MPI */
00569   
00570   /* Close first input netCDF file */
00571   (void)nco_close(in_id);
00572   
00573   /* Loop over input files */
00574   for(fl_idx=0;fl_idx<fl_nbr;fl_idx++){
00575 #ifdef ENABLE_MPI
00576     MPI_Barrier(mpi_cmm);
00577 #endif /* !ENABLE_MPI */
00578     /* Parse filename */
00579     if(fl_idx != 0) fl_in=nco_fl_nm_prs(fl_in,fl_idx,(int *)NULL,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth);
00580     if(dbg_lvl > 0) (void)fprintf(fp_stderr,"\nInput file %d is %s; ",fl_idx,fl_in);
00581     /* Make sure file is on local system and is readable or die trying */
00582     if(fl_idx != 0) fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FILE_RETRIEVED_FROM_REMOTE_LOCATION);
00583     if(dbg_lvl > 0) (void)fprintf(fp_stderr,"local file %s:\n",fl_in);
00584     
00585     /* Open file once per thread to improve caching */
00586     for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in,NC_NOWRITE,in_id_arr+thr_idx);
00587 
00588 #if 0
00589     /* fxm: netCDF4: Change to independent variable reads? */
00590 #ifdef ENABLE_NETCDF4
00591     rcd=nco_open_par(fl_in,NC_MPIIO|NC_NETCDF4,mpi_cmm,mpi_nfo,&in_id);
00592 #endif /* !ENABLE_NETCDF4 */
00593 #ifdef ENABLE_PNETCDF
00594     rcd=ncompi_open(mpi_cmm,fl_in,NC_NOWRITE,mpi_nfo,&in_id);
00595 #endif /* !ENABLE_PNETCDF */
00596 #endif /* !0 */
00597     /* Perform various error-checks on input file */
00598     if(False) (void)nco_fl_cmp_err_chk();
00599     
00600 #ifdef ENABLE_MPI
00601     if(prc_rnk == rnk_mgr){ /* MPI manager code */
00602       /* Compensate for incrementing on each worker's first message */
00603       var_wrt_nbr=-prc_nbr+1;
00604       idx=0;
00605       /* While variables remain to be processed or written... */
00606       while(var_wrt_nbr < nbr_var_prc){
00607         /* Receive message from any worker */
00608         MPI_Recv(wrk_id_bfr,wrk_id_bfr_lng,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,mpi_cmm,&mpi_stt);
00609         /* Obtain MPI message tag type */
00610         msg_tag_typ=mpi_stt.MPI_TAG;
00611         /* Get sender's prc_rnk */
00612         rnk_wrk=wrk_id_bfr[0];
00613         
00614         /* Allocate next variable, if any, to worker */
00615         if(msg_tag_typ == msg_tag_wrk_rqs){
00616           var_wrt_nbr++; /* [nbr] Number of variables written */
00617           /* Worker closed output file before sending msg_tag_wrk_rqs */
00618           TKN_WRT_FREE=True;
00619           
00620           if(idx > nbr_var_prc-1){
00621             msg_bfr[0]=idx_all_wrk_ass; /* [enm] All variables already assigned */
00622             msg_bfr[1]=out_id; /* Output file ID */
00623           }else{
00624             /* Tell requesting worker to allocate space for next variable */
00625             msg_bfr[0]=idx; /* [idx] Variable to be processed */
00626             msg_bfr[1]=out_id; /* Output file ID */
00627             msg_bfr[2]=var_prc_out[idx]->id; /* [id] Variable ID in output file */
00628             /* Point to next variable on list */
00629             idx++;
00630           } /* endif idx */
00631           MPI_Send(msg_bfr,msg_bfr_lng,MPI_INT,rnk_wrk,msg_tag_wrk_rsp,mpi_cmm);
00632           /* msg_tag_typ != msg_tag_wrk_rqs */
00633         }else if(msg_tag_typ == msg_tag_tkn_wrt_rqs){
00634           /* Allocate token if free, else ask worker to try later */
00635           if(TKN_WRT_FREE){
00636             TKN_WRT_FREE=False;
00637             msg_bfr[0]=tkn_wrt_rqs_xcp; /* Accept request for write token */
00638           }else{
00639             msg_bfr[0]=tkn_wrt_rqs_dny; /* Deny request for write token */
00640           } /* !TKN_WRT_FREE */
00641           MPI_Send(msg_bfr,msg_bfr_lng,MPI_INT,rnk_wrk,msg_tag_tkn_wrt_rsp,mpi_cmm);
00642         } /* msg_tag_typ != msg_tag_tkn_wrt_rqs */
00643       } /* end while var_wrt_nbr < nbr_var_prc */
00644     }else{ /* prc_rnk != rnk_mgr, end Manager code begin Worker code */
00645       wrk_id_bfr[0]=prc_rnk;
00646       while(1){ /* While work remains... */
00647         /* Send msg_tag_wrk_rqs */
00648         wrk_id_bfr[0]=prc_rnk;
00649         MPI_Send(wrk_id_bfr,wrk_id_bfr_lng,MPI_INT,rnk_mgr,msg_tag_wrk_rqs,mpi_cmm);
00650         /* Receive msg_tag_wrk_rsp */
00651         MPI_Recv(msg_bfr,msg_bfr_lng,MPI_INT,0,msg_tag_wrk_rsp,mpi_cmm,&mpi_stt);
00652         idx=msg_bfr[0];
00653         out_id=msg_bfr[1];
00654         if(idx == idx_all_wrk_ass) break;
00655         else{
00656           var_prc_out[idx]->id=msg_bfr[2];
00657           /* Process this variable same as UP code */
00658 #else /* !ENABLE_MPI */
00659           /* OpenMP with threading over variables, not files */
00660 #ifdef _OPENMP
00661 #pragma omp parallel for default(none) private(idx,in_id) shared(dbg_lvl,fl_nbr,idx_rec_out,in_id_arr,nbr_var_prc,out_id,var_prc,var_prc_out)
00662 #endif /* !_OPENMP */
00663           /* Process all variables in current file */
00664           for(idx=0;idx<nbr_var_prc;idx++){
00665 #endif /* !ENABLE_MPI */
00666        /* Common code for UP and MPI */ /* fxm: requires C99 as is? */
00667             in_id=in_id_arr[omp_get_thread_num()];
00668             if(dbg_lvl > 1) (void)fprintf(fp_stderr,"%s, ",var_prc[idx]->nm);
00669             if(dbg_lvl > 0) (void)fflush(fp_stderr);
00670             /* Variables may have different ID, missing_value, type, in each file */
00671             (void)nco_var_mtd_refresh(in_id,var_prc[idx]);
00672             /* Retrieve variable from disk into memory */
00673             /* NB: nco_var_get() with same nc_id contains OpenMP critical region */
00674             (void)nco_var_get(in_id,var_prc[idx]);
00675             /* Size of record dimension is 1 in output file */
00676             var_prc_out[idx]->cnt[0]=1L;
00677             var_prc_out[idx]->srt[0]=idx_rec_out;
00678             
00679 #ifdef ENABLE_MPI
00680             /* Obtain token and prepare to write */
00681             while(1){ /* Send msg_tag_tkn_wrt_rqs repeatedly until token obtained */
00682               wrk_id_bfr[0]=prc_rnk;
00683               MPI_Send(wrk_id_bfr,wrk_id_bfr_lng,MPI_INT,rnk_mgr,msg_tag_tkn_wrt_rqs,mpi_cmm);
00684               MPI_Recv(msg_bfr,msg_bfr_lng,MPI_INT,rnk_mgr,msg_tag_tkn_wrt_rsp,mpi_cmm,&mpi_stt);
00685               tkn_wrt_rsp=msg_bfr[0];
00686               /* Wait then re-send request */
00687               if(tkn_wrt_rsp == tkn_wrt_rqs_dny) sleep(tkn_wrt_rqs_ntv); else break;
00688             } /* end while loop waiting for write token */
00689             
00690             /* Worker has token---prepare to write */
00691             if(tkn_wrt_rsp == tkn_wrt_rqs_xcp){
00692               rcd=nco_open(fl_out_tmp,NC_WRITE|NC_SHARE,&out_id);
00693               /* Turn off default filling behavior to enhance efficiency */
00694               rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old);
00695 #else /* !ENABLE_MPI */
00696 #ifdef _OPENMP
00697 #pragma omp critical
00698 #endif /* _OPENMP */
00699 #endif /* !ENABLE_MPI */
00700               { /* begin OpenMP critical */
00701                 /* Write variable into current record in output file */
00702                 if(var_prc[idx]->nbr_dim == 0){
00703                   (void)nco_put_var1(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc[idx]->val.vp,var_prc[idx]->type);
00704                 }else{ /* end if variable is a scalar */
00705                   (void)nco_put_vara(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc[idx]->val.vp,var_prc[idx]->type);
00706                 } /* end if variable is array */
00707                 /* Free current input buffer */
00708                 var_prc[idx]->val.vp=nco_free(var_prc[idx]->val.vp);
00709               } /* end OpenMP critical */
00710 #ifdef ENABLE_MPI
00711               /* Close output file and increment written counter */
00712               nco_close(out_id);
00713               var_wrt_nbr++;
00714             } /* endif tkn_wrt_rqs_xcp */
00715           } /* end else !idx_all_wrk_ass */
00716         } /* end while loop requesting work/token */
00717       } /* endif Worker */
00718 #else /* !ENABLE_MPI */
00719     } /* end (OpenMP parallel for) loop over idx */
00720 #endif /* !ENABLE_MPI */
00721     
00722     idx_rec_out++; /* [idx] Index of current record in output file (0 is first, ...) */
00723     if(dbg_lvl > 1) (void)fprintf(stderr,"\n");
00724     
00725     /* Close input netCDF file */
00726     for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_arr[thr_idx]);
00727 
00728     /* Remove local copy of file */
00729     if(FILE_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in);
00730 #ifdef ENABLE_MPI
00731     MPI_Barrier(mpi_cmm);
00732 #endif /* !ENABLE_MPI */
00733   } /* end loop over fl_idx */
00734   
00735 #ifdef ENABLE_MPI
00736   /* Manager moves output file (closed by workers) from temporary to permanent location */
00737   if(prc_rnk == rnk_mgr) (void)nco_fl_mv(fl_out_tmp,fl_out);
00738 #else /* !ENABLE_MPI */
00739   /* Close output file and move it from temporary to permanent location */
00740   (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id);
00741 #endif /* end !ENABLE_MPI */
00742   
00743   /* ncecat-specific memory cleanup */
00744   
00745   /* NCO-generic clean-up */
00746   /* Free individual strings/arrays */
00747   if(cmd_ln != NULL) cmd_ln=(char *)nco_free(cmd_ln);
00748   if(fl_in != NULL) fl_in=(char *)nco_free(fl_in);
00749   if(fl_out != NULL) fl_out=(char *)nco_free(fl_out);
00750   if(fl_out_tmp != NULL) fl_out_tmp=(char *)nco_free(fl_out_tmp);
00751   if(fl_pth != NULL) fl_pth=(char *)nco_free(fl_pth);
00752   if(fl_pth_lcl != NULL) fl_pth_lcl=(char *)nco_free(fl_pth_lcl);
00753   if(in_id_arr != NULL) in_id_arr=(int *)nco_free(in_id_arr);
00754   /* Free lists of strings */
00755   if(fl_lst_in != NULL && fl_lst_abb == NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,fl_nbr); 
00756   if(fl_lst_in != NULL && fl_lst_abb != NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,1);
00757   if(fl_lst_abb != NULL) fl_lst_abb=nco_sng_lst_free(fl_lst_abb,abb_arg_nbr);
00758   if(var_lst_in_nbr > 0) var_lst_in=nco_sng_lst_free(var_lst_in,var_lst_in_nbr);
00759   /* Free limits */
00760   for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]);
00761   if(lmt_nbr > 0) lmt=nco_lmt_lst_free(lmt,lmt_nbr);
00762   /* Free dimension lists */
00763   if(nbr_dmn_xtr > 0) dim=nco_dmn_lst_free(dim,nbr_dmn_xtr-1); /* NB: ncecat has one fewer input than output dimension */
00764   if(nbr_dmn_xtr > 0) dmn_out=nco_dmn_lst_free(dmn_out,nbr_dmn_xtr); 
00765   /* Free variable lists */
00766   if(nbr_xtr > 0) var=nco_var_lst_free(var,nbr_xtr);
00767   if(nbr_xtr > 0) var_out=nco_var_lst_free(var_out,nbr_xtr);
00768   var_prc=(var_sct **)nco_free(var_prc);
00769   var_prc_out=(var_sct **)nco_free(var_prc_out);
00770   var_fix=(var_sct **)nco_free(var_fix);
00771   var_fix_out=(var_sct **)nco_free(var_fix_out);
00772   
00773 #ifdef ENABLE_MPI
00774   MPI_Finalize();
00775 #endif /* !ENABLE_MPI */
00776   
00777   if(rcd != NC_NOERR) nco_err_exit(rcd,"main");
00778   nco_exit_gracefully();
00779   return EXIT_SUCCESS;
00780 } /* end main() */


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