#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) |
|
|
Definition at line 61 of file mpncecat.c. |
|
||||||||||||
|
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() */
|
1.4.4