#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 mpncbo.c:

Go to the source code of this file.
Defines | |
| #define | MAIN_PROGRAM_FILE |
Functions | |
| int | main (int argc, char **argv) |
|
|
|
|
||||||||||||
|
Definition at line 88 of file mpncbo.c. References dmn_sct_tag::cnt, copyright_prn(), var_sct_tag::dim, EXIT_FAILURE, EXIT_SUCCESS, False, FILE, getopt_long, var_sct_tag::has_mss_val, var_sct_tag::id, idx_all_wrk_ass, int_CEWI, 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, var_sct_tag::nbr_dim, NC_FORMAT_64BIT, NC_FORMAT_CLASSIC, NC_FORMAT_NETCDF4, NC_GLOBAL, NC_MAX_DIMS, NC_NOERR, NC_NOFILL, NC_NOWRITE, NC_SHARE, NC_WRITE, ncap_var_cnf_dmn(), 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_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_mss_val_cnf(), nco_nm_id_lst_free(), nco_op_add, nco_op_dvd, nco_op_mlt, nco_op_nil, nco_op_sbt, nco_op_typ_get(), nco_open(), nco_openmp_ini(), nco_pck_map_nil, nco_pck_plc_nil, nco_put_var1(), nco_put_vara(), nco_set_fill(), nco_sng_lst_free(), nco_spn_lck_brk, nco_spn_lck_us, nco_thr_att_cat(), nco_typ_sng(), nco_usg_prn(), nco_var_add(), nco_var_cnf_typ(), nco_var_dfn(), nco_var_dpl(), nco_var_dvd(), 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_mrg(), nco_var_lst_xcl(), nco_var_mlt(), nco_var_mtd_refresh(), nco_var_sbt(), nco_var_srt_zero(), nco_var_val_cpy(), nco_xrf_dmn(), nco_xrf_var(), no_argument, NULL_CEWI, omp_get_thread_num(), optarg, optind, prg_nm_get(), prg_prs(), required_argument, rnk_mgr, tkn_wrt_rqs_dny, tkn_wrt_rqs_ntv, tkn_wrt_rqs_xcp, True, type, var_sct_tag::type, var_sct_tag::val, option::val, ptr_unn::vp, and wrk_id_bfr_lng. 00089 { 00090 nco_bool EXCLUDE_INPUT_LIST=False; /* Option c */ 00091 nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */ 00092 nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */ 00093 nco_bool FILE_1_RETRIEVED_FROM_REMOTE_LOCATION; 00094 nco_bool FILE_2_RETRIEVED_FROM_REMOTE_LOCATION; 00095 nco_bool FL_LST_IN_FROM_STDIN=False; /* [flg] fl_lst_in comes from stdin */ 00096 nco_bool FORCE_APPEND=False; /* Option A */ 00097 nco_bool FORCE_OVERWRITE=False; /* Option O */ 00098 nco_bool FORTRAN_IDX_CNV=False; /* Option F */ 00099 nco_bool HISTORY_APPEND=True; /* Option h */ 00100 nco_bool CNV_CCM_CCSM_CF; 00101 nco_bool REMOVE_REMOTE_FILES_AFTER_PROCESSING=True; /* Option R */ 00102 00103 char **fl_lst_abb=NULL; /* Option a */ 00104 char **fl_lst_in; 00105 char **var_lst_in=NULL_CEWI; 00106 char *cmd_ln; 00107 char *fl_in_1=NULL; /* fl_in_1 is nco_realloc'd when not NULL */; 00108 char *fl_in_2=NULL; /* fl_in_2 is nco_realloc'd when not NULL */; 00109 char *fl_out=NULL; /* Option o */ 00110 char *fl_out_tmp=NULL; /* MPI 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 *nco_op_typ_sng=NULL; /* [sng] Operation type */ 00115 char *opt_crr=NULL; /* [sng] String representation of current long-option name */ 00116 char *optarg_lcl=NULL; /* [sng] Local copy of system optarg */ 00117 char *time_bfr_srt; 00118 00119 const char * const CVS_Id="$Id: mpncbo.c,v 1.48 2006/02/26 07:41:55 zender Exp $"; 00120 const char * const CVS_Revision="$Revision: 1.48 $"; 00121 const char * const opt_sht_lst="4ACcD:d:Fhl:Oo:p:rRSt:v:xy:-:"; 00122 00123 dmn_sct **dim_1; 00124 dmn_sct **dim_2; 00125 dmn_sct **dmn_out; 00126 00127 extern char *optarg; 00128 extern int optind; 00129 00130 /* Using naked stdin/stdout/stderr in parallel region generates warning 00131 Copy appropriate filehandle to variable scoped shared in parallel clause */ 00132 FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */ 00133 FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */ 00134 00135 int *in_id_1_arr; 00136 int *in_id_2_arr; 00137 00138 int abb_arg_nbr=0; 00139 int fl_idx; 00140 int fl_nbr=0; 00141 int fl_out_fmt=NC_FORMAT_CLASSIC; /* [enm] Output file format */ 00142 int fll_md_old; /* [enm] Old fill mode */ 00143 int idx; 00144 int in_id_1; 00145 int in_id_2; 00146 int lmt_nbr=0; /* Option d. NB: lmt_nbr gets incremented */ 00147 int nbr_dmn_fl_1; 00148 int nbr_dmn_fl_2; 00149 int nbr_dmn_xtr_1; 00150 int nbr_dmn_xtr_2; 00151 int nbr_var_fix_1; /* nbr_var_fix_1 gets incremented */ 00152 int nbr_var_fix_2; /* nbr_var_fix_2 gets incremented */ 00153 int nbr_var_fl_1; 00154 int nbr_var_fl_2; 00155 int nbr_var_prc_1; /* nbr_var_prc_1 gets incremented */ 00156 int nbr_var_prc_2; /* nbr_var_prc_2 gets incremented */ 00157 int nbr_xtr_1=0; /* nbr_xtr_1 won't otherwise be set for -c with no -v */ 00158 int nbr_xtr_2=0; /* nbr_xtr_2 won't otherwise be set for -c with no -v */ 00159 int nco_op_typ=nco_op_nil; /* [enm] Operation type */ 00160 int opt; 00161 int out_id; 00162 int rcd=NC_NOERR; /* [rcd] Return code */ 00163 int thr_idx; /* [idx] Index of current thread */ 00164 int thr_nbr=int_CEWI; /* [nbr] Thread number Option t */ 00165 int var_lst_in_nbr=0; 00166 00167 lmt_sct **lmt; 00168 00169 nm_id_sct *dmn_lst_1; 00170 nm_id_sct *dmn_lst_2; 00171 nm_id_sct *xtr_lst_1=NULL; /* xtr_lst_1 may be alloc()'d from NULL with -c option */ 00172 nm_id_sct *xtr_lst_2=NULL; /* xtr_lst_2 may be alloc()'d from NULL with -c option */ 00173 00174 time_t time_crr_time_t; 00175 00176 var_sct **var_1; 00177 var_sct **var_2; 00178 var_sct **var_fix_1; 00179 var_sct **var_fix_2; 00180 var_sct **var_fix_out; 00181 var_sct **var_out; 00182 var_sct **var_prc_1; 00183 var_sct **var_prc_2; 00184 var_sct **var_prc_out; 00185 00186 #ifdef ENABLE_MPI 00187 /* #if defined(ENABLE_MPI) && !defined(ENABLE_NETCDF4) */ 00188 /* Declare all MPI-specific variables here */ 00189 MPI_Status mpi_stt; /* [enm] Status check to decode msg_tag_typ */ 00190 00191 bool TKN_WRT_FREE=True; /* [flg] Write-access to output file is available */ 00192 00193 int fl_nm_lng; /* [nbr] Output file name length CEWI */ 00194 int msg_bfr[msg_bfr_lng]; /* [bfr] Buffer containing var, idx, tkn_wrt_rsp */ 00195 int msg_tag_typ; /* [enm] MPI message tag type */ 00196 int prc_rnk; /* [idx] Process rank */ 00197 int prc_nbr=0; /* [nbr] Number of MPI processes */ 00198 int tkn_wrt_rsp; /* [enm] Response to request for write token */ 00199 int var_wrt_nbr=0; /* [nbr] Variables written to output file until now */ 00200 int rnk_wrk; /* [idx] Worker rank */ 00201 int wrk_id_bfr[wrk_id_bfr_lng]; /* [bfr] Buffer for rnk_wrk */ 00202 #endif /* !ENABLE_MPI */ 00203 00204 static struct option opt_lng[]= 00205 { /* Structure ordered by short option key if possible */ 00206 /* Long options with no argument, no short option counterpart */ 00207 /* Long options with argument, no short option counterpart */ 00208 {"fl_fmt",required_argument,0,0}, 00209 {"file_format",required_argument,0,0}, 00210 /* Long options with short counterparts */ 00211 {"4",no_argument,0,'4'}, 00212 {"64bit",no_argument,0,'4'}, 00213 {"netcdf4",no_argument,0,'4'}, 00214 {"append",no_argument,0,'A'}, 00215 {"coords",no_argument,0,'c'}, 00216 {"crd",no_argument,0,'c'}, 00217 {"no-coords",no_argument,0,'C'}, 00218 {"no-crd",no_argument,0,'C'}, 00219 {"debug",required_argument,0,'D'}, 00220 {"dbg_lvl",required_argument,0,'D'}, 00221 {"dimension",required_argument,0,'d'}, 00222 {"dmn",required_argument,0,'d'}, 00223 {"fortran",no_argument,0,'F'}, 00224 {"ftn",no_argument,0,'F'}, 00225 {"history",no_argument,0,'h'}, 00226 {"hst",no_argument,0,'h'}, 00227 {"local",required_argument,0,'l'}, 00228 {"lcl",required_argument,0,'l'}, 00229 {"overwrite",no_argument,0,'O'}, 00230 {"ovr",no_argument,0,'O'}, 00231 {"path",required_argument,0,'p'}, 00232 {"retain",no_argument,0,'R'}, 00233 {"rtn",no_argument,0,'R'}, 00234 {"revision",no_argument,0,'r'}, 00235 {"suspend", no_argument,0,'S'}, 00236 {"variable",required_argument,0,'v'}, 00237 {"version",no_argument,0,'r'}, 00238 {"vrs",no_argument,0,'r'}, 00239 {"thr_nbr",required_argument,0,'t'}, 00240 {"exclude",no_argument,0,'x'}, 00241 {"xcl",no_argument,0,'x'}, 00242 {"operation",required_argument,0,'y'}, 00243 {"op_typ",required_argument,0,'y'}, 00244 {"help",no_argument,0,'?'}, 00245 {0,0,0,0} 00246 }; /* end opt_lng */ 00247 int opt_idx=0; /* Index of current long option into opt_lng array */ 00248 00249 #ifdef ENABLE_MPI 00250 /* MPI Initialization */ 00251 MPI_Init(&argc,&argv); 00252 MPI_Comm_size(MPI_COMM_WORLD,&prc_nbr); 00253 MPI_Comm_rank(MPI_COMM_WORLD,&prc_rnk); 00254 #endif /* !ENABLE_MPI */ 00255 00256 /* Start clock and save command line */ 00257 cmd_ln=nco_cmd_ln_sng(argc,argv); 00258 time_crr_time_t=time((time_t *)NULL); 00259 time_bfr_srt=ctime(&time_crr_time_t); time_bfr_srt=time_bfr_srt; /* Avoid compiler warning until variable is used for something */ 00260 00261 /* Get program name and set program enum (e.g., prg=ncra) */ 00262 prg_nm=prg_prs(argv[0],&prg); 00263 00264 /* Parse command line arguments */ 00265 while(1){ 00266 /* getopt_long_only() allows one dash to prefix long options */ 00267 opt=getopt_long(argc,argv,opt_sht_lst,opt_lng,&opt_idx); 00268 /* NB: access to opt_crr is only valid when long_opt is detected */ 00269 if(opt == EOF) break; /* Parse positional arguments once getopt_long() returns EOF */ 00270 opt_crr=(char *)strdup(opt_lng[opt_idx].name); 00271 00272 /* Process long options without short option counterparts */ 00273 if(opt == 0){ 00274 if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt); 00275 } /* opt != 0 */ 00276 /* Process short options */ 00277 switch(opt){ 00278 case 0: /* Long options have already been processed, return */ 00279 break; 00280 case '4': /* [flg] Catch-all to prescribe output storage format */ 00281 if(!strcmp(opt_crr,"64bit")) fl_out_fmt=NC_FORMAT_64BIT; else fl_out_fmt=NC_FORMAT_NETCDF4; 00282 break; 00283 case 'A': /* Toggle FORCE_APPEND */ 00284 FORCE_APPEND=!FORCE_APPEND; 00285 break; 00286 case 'C': /* Extract all coordinates associated with extracted variables? */ 00287 EXTRACT_ASSOCIATED_COORDINATES=False; 00288 break; 00289 case 'c': 00290 EXTRACT_ALL_COORDINATES=True; 00291 break; 00292 case 'D': /* The debugging level. Default is 0. */ 00293 dbg_lvl=(unsigned short)strtol(optarg,(char **)NULL,10); 00294 break; 00295 case 'd': /* Copy argument for later processing */ 00296 lmt_arg[lmt_nbr]=(char *)strdup(optarg); 00297 lmt_nbr++; 00298 break; 00299 case 'F': /* Toggle index convention. Default is 0-based arrays (C-style). */ 00300 FORTRAN_IDX_CNV=!FORTRAN_IDX_CNV; 00301 break; 00302 case 'h': /* Toggle appending to history global attribute */ 00303 HISTORY_APPEND=!HISTORY_APPEND; 00304 break; 00305 case 'l': /* Local path prefix for files retrieved from remote file system */ 00306 fl_pth_lcl=(char *)strdup(optarg); 00307 break; 00308 case 'O': /* Toggle FORCE_OVERWRITE */ 00309 FORCE_OVERWRITE=!FORCE_OVERWRITE; 00310 break; 00311 case 'o': /* Name of output file */ 00312 fl_out=(char *)strdup(optarg); 00313 break; 00314 case 'p': /* Common file path */ 00315 fl_pth=(char *)strdup(optarg); 00316 break; 00317 case 'R': /* Toggle removal of remotely-retrieved-files. Default is True. */ 00318 REMOVE_REMOTE_FILES_AFTER_PROCESSING=!REMOVE_REMOTE_FILES_AFTER_PROCESSING; 00319 break; 00320 case 'r': /* Print CVS program information and copyright notice */ 00321 (void)copyright_prn(CVS_Id,CVS_Revision); 00322 (void)nco_lbr_vrs_prn(); 00323 nco_exit(EXIT_SUCCESS); 00324 break; 00325 #ifdef ENABLE_MPI 00326 case 'S': /* Suspend with signal handler to facilitate debugging */ 00327 if(signal(SIGUSR1,nco_cnt_run) == SIG_ERR) (void)fprintf(fp_stdout,"%s: ERROR Could not install suspend handler.\n",prg_nm); 00328 while(!nco_spn_lck_brk) usleep(nco_spn_lck_us); /* Spinlock. fxm: should probably insert a sched_yield */ 00329 break; 00330 #endif /* !ENABLE_MPI */ 00331 case 't': /* Thread number */ 00332 thr_nbr=(int)strtol(optarg,(char **)NULL,10); 00333 break; 00334 case 'v': /* Variables to extract/exclude */ 00335 /* Replace commas with hashes when within braces (convert back later) */ 00336 optarg_lcl=(char *)strdup(optarg); 00337 (void)nco_lst_comma2hash(optarg_lcl); 00338 var_lst_in=lst_prs_2D(optarg_lcl,",",&var_lst_in_nbr); 00339 optarg_lcl=(char *)nco_free(optarg_lcl); 00340 nbr_xtr_1=nbr_xtr_2=var_lst_in_nbr; 00341 break; 00342 case 'x': /* Exclude rather than extract variables specified with -v */ 00343 EXCLUDE_INPUT_LIST=True; 00344 break; 00345 case 'y': /* User-specified operation type overrides invocation default */ 00346 nco_op_typ_sng=(char *)strdup(optarg); 00347 nco_op_typ=nco_op_typ_get(nco_op_typ_sng); 00348 break; 00349 case '?': /* Print proper usage */ 00350 (void)nco_usg_prn(); 00351 nco_exit(EXIT_SUCCESS); 00352 break; 00353 case '-': /* Long options are not allowed */ 00354 (void)fprintf(stderr,"%s: ERROR Long options are not available in this build. Use single letter options instead.\n",prg_nm_get()); 00355 nco_exit(EXIT_FAILURE); 00356 break; 00357 default: /* Print proper usage */ 00358 (void)nco_usg_prn(); 00359 nco_exit(EXIT_FAILURE); 00360 break; 00361 } /* end switch */ 00362 if(opt_crr != NULL) opt_crr=(char *)nco_free(opt_crr); 00363 } /* end while loop */ 00364 00365 /* Process positional arguments and fill in filenames */ 00366 fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN); 00367 00368 /* Make uniform list of user-specified dimension limits */ 00369 lmt=nco_lmt_prs(lmt_nbr,lmt_arg); 00370 00371 /* Initialize thread information */ 00372 thr_nbr=nco_openmp_ini(thr_nbr); 00373 in_id_1_arr=(int *)nco_malloc(thr_nbr*sizeof(int)); 00374 in_id_2_arr=(int *)nco_malloc(thr_nbr*sizeof(int)); 00375 00376 /* Parse filenames */ 00377 fl_idx=0; /* Input file _1 */ 00378 fl_in_1=nco_fl_nm_prs(fl_in_1,fl_idx,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth); 00379 if(dbg_lvl > 0) (void)fprintf(stderr,"\nInput file %d is %s; ",fl_idx,fl_in_1); 00380 /* Make sure file is on local system and is readable or die trying */ 00381 fl_in_1=nco_fl_mk_lcl(fl_in_1,fl_pth_lcl,&FILE_1_RETRIEVED_FROM_REMOTE_LOCATION); 00382 if(dbg_lvl > 0) (void)fprintf(stderr,"local file %s:\n",fl_in_1); 00383 /* Open file once per thread to improve caching */ 00384 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in_1,NC_NOWRITE,in_id_1_arr+thr_idx); 00385 in_id_1=in_id_1_arr[0]; 00386 00387 fl_idx=1; /* Input file _2 */ 00388 fl_in_2=nco_fl_nm_prs(fl_in_2,fl_idx,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth); 00389 if(dbg_lvl > 0) (void)fprintf(stderr,"\nInput file %d is %s; ",fl_idx,fl_in_2); 00390 /* Make sure file is on local system and is readable or die trying */ 00391 fl_in_2=nco_fl_mk_lcl(fl_in_2,fl_pth_lcl,&FILE_2_RETRIEVED_FROM_REMOTE_LOCATION); 00392 if(dbg_lvl > 0) (void)fprintf(stderr,"local file %s:\n",fl_in_2); 00393 /* Open file once per thread to improve caching */ 00394 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd=nco_open(fl_in_2,NC_NOWRITE,in_id_2_arr+thr_idx); 00395 in_id_2=in_id_2_arr[0]; 00396 00397 /* Get number of variables and dimensions in file */ 00398 (void)nco_inq(in_id_1,&nbr_dmn_fl_1,&nbr_var_fl_1,(int *)NULL,(int *)NULL); 00399 (void)nco_inq(in_id_2,&nbr_dmn_fl_2,&nbr_var_fl_2,(int *)NULL,(int *)NULL); 00400 00401 /* Form initial extraction list which may include extended regular expressions */ 00402 xtr_lst_1=nco_var_lst_mk(in_id_1,nbr_var_fl_1,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr_1); 00403 xtr_lst_2=nco_var_lst_mk(in_id_2,nbr_var_fl_2,var_lst_in,EXTRACT_ALL_COORDINATES,&nbr_xtr_2); 00404 00405 /* Change included variables to excluded variables */ 00406 if(EXCLUDE_INPUT_LIST) xtr_lst_1=nco_var_lst_xcl(in_id_1,nbr_var_fl_1,xtr_lst_1,&nbr_xtr_1); 00407 if(EXCLUDE_INPUT_LIST) xtr_lst_2=nco_var_lst_xcl(in_id_2,nbr_var_fl_2,xtr_lst_2,&nbr_xtr_2); 00408 00409 /* Add all coordinate variables to extraction list */ 00410 if(EXTRACT_ALL_COORDINATES) xtr_lst_1=nco_var_lst_add_crd(in_id_1,nbr_dmn_fl_1,xtr_lst_1,&nbr_xtr_1); 00411 if(EXTRACT_ALL_COORDINATES) xtr_lst_2=nco_var_lst_add_crd(in_id_2,nbr_dmn_fl_2,xtr_lst_2,&nbr_xtr_2); 00412 00413 /* Make sure coordinates associated extracted variables are also on extraction list */ 00414 if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst_1=nco_var_lst_ass_crd_add(in_id_1,xtr_lst_1,&nbr_xtr_1); 00415 if(EXTRACT_ASSOCIATED_COORDINATES) xtr_lst_2=nco_var_lst_ass_crd_add(in_id_2,xtr_lst_2,&nbr_xtr_2); 00416 00417 /* With fully symmetric 1<->2 ordering, may occasionally find nbr_xtr_2 > nbr_xtr_1 00418 This occurs, e.g., when fl_in_1 contains reduced variables and full coordinates 00419 are only in fl_in_2 and so will not appear xtr_lst_1 */ 00420 00421 /* Sort extraction list by variable ID for fastest I/O */ 00422 if(nbr_xtr_1 > 1) xtr_lst_1=nco_lst_srt_nm_id(xtr_lst_1,nbr_xtr_1,False); 00423 if(nbr_xtr_2 > 1) xtr_lst_2=nco_lst_srt_nm_id(xtr_lst_2,nbr_xtr_2,False); 00424 00425 /* We now have final list of variables to extract. Phew. */ 00426 00427 /* Find coordinate/dimension values associated with user-specified limits 00428 NB: nco_lmt_evl() with same nc_id contains OpenMP critical region */ 00429 for(idx=0;idx<lmt_nbr;idx++) (void)nco_lmt_evl(in_id_1,lmt[idx],0L,FORTRAN_IDX_CNV); 00430 00431 /* Find dimensions associated with variables to be extracted */ 00432 dmn_lst_1=nco_dmn_lst_ass_var(in_id_1,xtr_lst_1,nbr_xtr_1,&nbr_dmn_xtr_1); 00433 dmn_lst_2=nco_dmn_lst_ass_var(in_id_2,xtr_lst_2,nbr_xtr_2,&nbr_dmn_xtr_2); 00434 00435 /* Fill in dimension structure for all extracted dimensions */ 00436 dim_1=(dmn_sct **)nco_malloc(nbr_dmn_xtr_1*sizeof(dmn_sct *)); 00437 dim_2=(dmn_sct **)nco_malloc(nbr_dmn_xtr_2*sizeof(dmn_sct *)); 00438 for(idx=0;idx<nbr_dmn_xtr_1;idx++) dim_1[idx]=nco_dmn_fll(in_id_1,dmn_lst_1[idx].id,dmn_lst_1[idx].nm); 00439 for(idx=0;idx<nbr_dmn_xtr_2;idx++) dim_2[idx]=nco_dmn_fll(in_id_2,dmn_lst_2[idx].id,dmn_lst_2[idx].nm); 00440 /* Dimension lists no longer needed */ 00441 dmn_lst_1=nco_nm_id_lst_free(dmn_lst_1,nbr_dmn_xtr_1); 00442 dmn_lst_2=nco_nm_id_lst_free(dmn_lst_2,nbr_dmn_xtr_2); 00443 00444 /* Merge hyperslab limit information into dimension structures */ 00445 if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim_1,nbr_dmn_xtr_1,lmt,lmt_nbr); 00446 if(lmt_nbr > 0) (void)nco_dmn_lmt_mrg(dim_2,nbr_dmn_xtr_2,lmt,lmt_nbr); 00447 00448 /* Duplicate input dimension structures for output dimension structures */ 00449 dmn_out=(dmn_sct **)nco_malloc(nbr_dmn_xtr_1*sizeof(dmn_sct *)); 00450 for(idx=0;idx<nbr_dmn_xtr_1;idx++){ 00451 dmn_out[idx]=nco_dmn_dpl(dim_1[idx]); 00452 (void)nco_dmn_xrf(dim_1[idx],dmn_out[idx]); 00453 } /* end loop over idx */ 00454 00455 if(dbg_lvl > 3){ 00456 for(idx=0;idx<nbr_xtr_1;idx++) (void)fprintf(stderr,"xtr_lst_1[%d].nm = %s, .id= %d\n",idx,xtr_lst_1[idx].nm,xtr_lst_1[idx].id); 00457 } /* end if */ 00458 00459 /* Is this an CCM/CCSM/CF-format history tape? */ 00460 CNV_CCM_CCSM_CF=nco_cnv_ccm_ccsm_cf_inq(in_id_1); 00461 00462 /* Fill in variable structure list for all extracted variables */ 00463 var_1=(var_sct **)nco_malloc(nbr_xtr_1*sizeof(var_sct *)); 00464 var_2=(var_sct **)nco_malloc(nbr_xtr_2*sizeof(var_sct *)); 00465 var_out=(var_sct **)nco_malloc(nbr_xtr_1*sizeof(var_sct *)); 00466 for(idx=0;idx<nbr_xtr_1;idx++){ 00467 var_1[idx]=nco_var_fll(in_id_1,xtr_lst_1[idx].id,xtr_lst_1[idx].nm,dim_1,nbr_dmn_xtr_1); 00468 var_out[idx]=nco_var_dpl(var_1[idx]); 00469 (void)nco_xrf_var(var_1[idx],var_out[idx]); 00470 (void)nco_xrf_dmn(var_out[idx]); 00471 } /* end loop over idx */ 00472 for(idx=0;idx<nbr_xtr_2;idx++){ 00473 var_2[idx]=nco_var_fll(in_id_2,xtr_lst_2[idx].id,xtr_lst_2[idx].nm,dim_2,nbr_dmn_xtr_2); 00474 } /* end loop over idx */ 00475 00476 /* Extraction lists no longer needed */ 00477 xtr_lst_1=nco_nm_id_lst_free(xtr_lst_1,nbr_xtr_1); 00478 xtr_lst_2=nco_nm_id_lst_free(xtr_lst_2,nbr_xtr_2); 00479 00480 /* Divide variable lists into lists of fixed variables and variables to be processed 00481 Create lists from file_1 last so those values remain in *_out arrays */ 00482 (void)nco_var_lst_dvd(var_2,var_out,nbr_xtr_2,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,(dmn_sct **)NULL,0,&var_fix_2,&var_fix_out,&nbr_var_fix_2,&var_prc_2,&var_prc_out,&nbr_var_prc_2); 00483 /* Avoid double-free() condition */ 00484 var_fix_out=(var_sct **)nco_free(var_fix_out); 00485 var_prc_out=(var_sct **)nco_free(var_prc_out); 00486 (void)nco_var_lst_dvd(var_1,var_out,nbr_xtr_1,CNV_CCM_CCSM_CF,nco_pck_plc_nil,nco_pck_map_nil,(dmn_sct **)NULL,0,&var_fix_1,&var_fix_out,&nbr_var_fix_1,&var_prc_1,&var_prc_out,&nbr_var_prc_1); 00487 00488 /* Die gracefully on unsupported features... */ 00489 if(nbr_var_fix_1 < nbr_var_fix_2){ 00490 (void)fprintf(fp_stdout,"%s: ERROR First file has fewer fixed variables than second file (%d < %d). This feature is NCO TODO 581.\n",prg_nm,nbr_var_fix_1,nbr_var_fix_2); 00491 nco_exit(EXIT_FAILURE); 00492 } /* endif */ 00493 00494 /* Merge two variable lists into same order */ 00495 rcd=nco_var_lst_mrg(&var_prc_1,&var_prc_2,&nbr_var_prc_1,&nbr_var_prc_2); 00496 00497 /* Zero start vectors for all output variables */ 00498 (void)nco_var_srt_zero(var_out,nbr_xtr_1); 00499 00500 #ifdef ENABLE_MPI 00501 if(prc_rnk == rnk_mgr){ /* MPI manager code */ 00502 #endif /* !ENABLE_MPI */ 00503 /* Open output file */ 00504 fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&out_id); 00505 00506 /* Copy global attributes */ 00507 (void)nco_att_cpy(in_id_1,out_id,NC_GLOBAL,NC_GLOBAL,True); 00508 00509 /* Catenate time-stamped command line to "history" global attribute */ 00510 if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln); 00511 00512 if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr); 00513 00514 #ifdef ENABLE_MPI 00515 /* Initialize MPI task information */ 00516 if(prc_nbr > 0 && HISTORY_APPEND) (void)nco_mpi_att_cat(out_id,prc_nbr); 00517 #endif /* !ENABLE_MPI */ 00518 00519 /* Define dimensions in output file */ 00520 (void)nco_dmn_dfn(fl_out,out_id,dmn_out,nbr_dmn_xtr_1); 00521 00522 /* fxm: TODO 550 put max_dim_sz/list(var_1,var_2) into var_def(var_out) */ 00523 /* Define variables in output file, copy their attributes */ 00524 (void)nco_var_dfn(in_id_1,fl_out,out_id,var_out,nbr_xtr_1,(dmn_sct **)NULL,(int)0,nco_pck_plc_nil,nco_pck_map_nil); 00525 00526 /* Turn off default filling behavior to enhance efficiency */ 00527 rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old); 00528 00529 /* Take output file out of define mode */ 00530 (void)nco_enddef(out_id); 00531 00532 #ifdef ENABLE_MPI 00533 } /* prc_rnk != rnk_mgr */ 00534 00535 /* Manager obtains output filename and broadcasts to workers */ 00536 if(prc_rnk == rnk_mgr) fl_nm_lng=(int)strlen(fl_out_tmp); 00537 MPI_Bcast(&fl_nm_lng,1,MPI_INT,rnk_mgr,MPI_COMM_WORLD); 00538 if(prc_rnk != rnk_mgr) fl_out_tmp=(char *)malloc((fl_nm_lng+1)*sizeof(char)); 00539 MPI_Bcast(fl_out_tmp,fl_nm_lng+1,MPI_CHAR,rnk_mgr,MPI_COMM_WORLD); 00540 00541 if(prc_rnk == rnk_mgr){ /* MPI manager code */ 00542 TKN_WRT_FREE=False; 00543 #endif /* !ENABLE_MPI */ 00544 /* Copy variable data for non-processed variables */ 00545 (void)nco_var_val_cpy(in_id_1,out_id,var_fix_1,nbr_var_fix_1); 00546 #ifdef ENABLE_MPI 00547 /* Close output file so workers can open it */ 00548 nco_close(out_id); 00549 TKN_WRT_FREE=True; 00550 } /* prc_rnk != rnk_mgr */ 00551 #endif /* !ENABLE_MPI */ 00552 00553 /* ncbo() code has been similar to ncea() (and ncra()) wherever possible 00554 Major differences occur where performance would otherwise suffer 00555 From now on, however, binary-file and binary-operation nature of ncbo() 00556 is too different from ncea() paradigm to justify following ncea() style. 00557 Instead, we adopt symmetric nomenclature (e.g., file_1, file_2), and 00558 perform differences variable-by-variable so peak memory usage goes as 00559 Order(2*maximum variable size) rather than Order(3*maximum record size) or 00560 Order(3*file size) */ 00561 00562 /* Perform various error-checks on input file */ 00563 if(False) (void)nco_fl_cmp_err_chk(); 00564 00565 /* Default operation depends on invocation name */ 00566 if(nco_op_typ_sng == NULL) nco_op_typ=nco_op_typ_get(nco_op_typ_sng); 00567 00568 #ifdef ENABLE_MPI 00569 if(prc_rnk == rnk_mgr){ /* MPI manager code */ 00570 /* Compensate for incrementing on each worker's first message */ 00571 var_wrt_nbr=-prc_nbr+1; 00572 idx=0; 00573 /* While variables remain to be processed or written... */ 00574 while(var_wrt_nbr < nbr_var_prc_1){ 00575 /* Receive message from any worker */ 00576 MPI_Recv(wrk_id_bfr,wrk_id_bfr_lng,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&mpi_stt); 00577 /* Obtain MPI message tag type */ 00578 msg_tag_typ=mpi_stt.MPI_TAG; 00579 /* Get sender's prc_rnk */ 00580 rnk_wrk=wrk_id_bfr[0]; 00581 00582 /* Allocate next variable, if any, to worker */ 00583 if(msg_tag_typ == msg_tag_wrk_rqs){ 00584 var_wrt_nbr++; /* [nbr] Number of variables written */ 00585 /* Worker closed output file before sending msg_tag_wrk_rqs */ 00586 TKN_WRT_FREE=True; 00587 00588 if(idx < nbr_var_prc_1){ 00589 /* Tell requesting worker to allocate space for next variable */ 00590 msg_bfr[0]=idx; /* [idx] Variable to be processed */ 00591 msg_bfr[1]=out_id; /* Output file ID */ 00592 msg_bfr[2]=var_prc_out[idx]->id; /* [id] Variable ID in output file */ 00593 /* Point to next variable on list */ 00594 idx++; 00595 }else{ 00596 msg_bfr[0]=idx_all_wrk_ass; /* [enm] All variables already assigned */ 00597 msg_bfr[1]=out_id; /* Output file ID */ 00598 } /* endif idx */ 00599 MPI_Send(msg_bfr,msg_bfr_lng,MPI_INT,rnk_wrk,msg_tag_wrk_rsp,MPI_COMM_WORLD); 00600 /* msg_tag_typ != msg_tag_wrk_rqs */ 00601 }else if(msg_tag_typ == msg_tag_tkn_wrt_rqs){ 00602 /* Allocate token if free, else ask worker to try later */ 00603 if(TKN_WRT_FREE){ 00604 TKN_WRT_FREE=False; 00605 msg_bfr[0]=tkn_wrt_rqs_xcp; /* Accept request for write token */ 00606 }else{ 00607 msg_bfr[0]=tkn_wrt_rqs_dny; /* Deny request for write token */ 00608 } /* !TKN_WRT_FREE */ 00609 MPI_Send(msg_bfr,msg_bfr_lng,MPI_INT,rnk_wrk,msg_tag_tkn_wrt_rsp,MPI_COMM_WORLD); 00610 } /* msg_tag_typ != msg_tag_tkn_wrt_rqs */ 00611 } /* end while var_wrt_nbr < nbr_var_prc_1 */ 00612 }else{ /* prc_rnk != rnk_mgr, end Manager code begin Worker code */ 00613 wrk_id_bfr[0]=prc_rnk; 00614 while(1){ /* While work remains... */ 00615 /* Send msg_tag_wrk_rqs */ 00616 wrk_id_bfr[0]=prc_rnk; 00617 MPI_Send(wrk_id_bfr,wrk_id_bfr_lng,MPI_INT,rnk_mgr,msg_tag_wrk_rqs,MPI_COMM_WORLD); 00618 /* Receive msg_tag_wrk_rsp */ 00619 MPI_Recv(msg_bfr,msg_bfr_lng,MPI_INT,0,msg_tag_wrk_rsp,MPI_COMM_WORLD,&mpi_stt); 00620 idx=msg_bfr[0]; 00621 out_id=msg_bfr[1]; 00622 if(idx == idx_all_wrk_ass) break; 00623 else{ 00624 var_prc_out[idx]->id=msg_bfr[2]; 00625 /* Process this variable same as UP code */ 00626 #else /* !ENABLE_MPI */ 00627 #ifdef _OPENMP 00628 /* OpenMP notes: 00629 shared(): msk and wgt are not altered within loop 00630 private(): wgt_avg does not need initialization */ 00631 #pragma omp parallel for default(none) private(idx,in_id_1,in_id_2) shared(dbg_lvl,dim_1,fl_in_1,fl_in_2,fl_out,fp_stderr,in_id_1_arr,in_id_2_arr,nbr_dmn_xtr_1,nbr_var_prc_1,nbr_var_prc_2,nco_op_typ,out_id,prg_nm,var_prc_1,var_prc_2,var_prc_out) 00632 #endif /* !_OPENMP */ 00633 /* UP and SMP codes main loop over variables */ 00634 for(idx=0;idx<nbr_var_prc_1;idx++){ 00635 #endif /* ENABLE_MPI */ 00636 /* Common code for UP, SMP, and MPI */ 00637 int has_mss_val=False; 00638 ptr_unn mss_val; 00639 00640 if(dbg_lvl > 0) (void)fprintf(fp_stderr,"%s, ",var_prc_1[idx]->nm); 00641 if(dbg_lvl > 0) (void)fflush(fp_stderr); 00642 00643 in_id_1=in_id_1_arr[omp_get_thread_num()]; 00644 in_id_2=in_id_2_arr[omp_get_thread_num()]; 00645 00646 (void)nco_var_mtd_refresh(in_id_1,var_prc_1[idx]); 00647 has_mss_val=var_prc_1[idx]->has_mss_val; 00648 /* NB: nco_var_get() with same nc_id contains OpenMP critical region */ 00649 (void)nco_var_get(in_id_1,var_prc_1[idx]); 00650 00651 /* Find and set variable dmn_nbr, ID, mss_val, type in second file */ 00652 (void)nco_var_mtd_refresh(in_id_2,var_prc_2[idx]); 00653 00654 /* Read hyperslab from second file */ 00655 /* NB: nco_var_get() with same nc_id contains OpenMP critical region */ 00656 (void)nco_var_get(in_id_2,var_prc_2[idx]); 00657 00658 /* Determine whether var1 and var2 conform */ 00659 if(var_prc_1[idx]->nbr_dim == var_prc_2[idx]->nbr_dim){ 00660 int dmn_idx; 00661 /* Do all dimensions match in sequence? */ 00662 for(dmn_idx=0;dmn_idx<var_prc_1[idx]->nbr_dim;dmn_idx++){ 00663 if( 00664 strcmp(var_prc_1[idx]->dim[dmn_idx]->nm,var_prc_2[idx]->dim[dmn_idx]->nm) || /* Dimension names do not match */ 00665 (var_prc_1[idx]->dim[dmn_idx]->cnt != var_prc_2[idx]->dim[dmn_idx]->cnt) || /* Dimension sizes do not match */ 00666 False){ 00667 (void)fprintf(fp_stdout,"%s: ERROR Variables do not conform:\nFile %s variable %s dimension %d is %s with size %li and count %li\nFile %s variable %s dimension %d is %s with size %li and count %li\n",prg_nm,fl_in_1,var_prc_1[idx]->nm,dmn_idx,var_prc_1[idx]->dim[dmn_idx]->nm,var_prc_1[idx]->dim[dmn_idx]->sz,var_prc_1[idx]->dim[dmn_idx]->cnt,fl_in_2,var_prc_2[idx]->nm,dmn_idx,var_prc_2[idx]->dim[dmn_idx]->nm,var_prc_2[idx]->dim[dmn_idx]->sz,var_prc_2[idx]->dim[dmn_idx]->cnt); 00668 if(var_prc_1[idx]->dim[dmn_idx]->cnt == 1 || var_prc_2[idx]->dim[dmn_idx]->cnt == 1) (void)fprintf(fp_stdout,"%s: HINT If a dimension is present in both files, it must be the same size. %s will not attempt to broadcast a degenerate (i.e., size 1) dimension (e.g., a single timestep) to a non-degenerate size. If one of the dimensions is degenerate, try removing it completely (e.g., by averaging over it with ncwa) before invoking %s\n",prg_nm,prg_nm,prg_nm); 00669 nco_exit(EXIT_FAILURE); 00670 } /* endif */ 00671 } /* end loop over dmn_idx */ 00672 }else{ /* var_prc_out[idx]->nbr_dim != var_prc_1[idx]->nbr_dim) */ 00673 /* Number of dimensions do not match, attempt to broadcast variables 00674 fxm: broadcasting here leads to memory leak later since var_[1,2] does not know */ 00675 00676 /* Die gracefully on unsupported features... */ 00677 if(var_prc_1[idx]->nbr_dim < var_prc_2[idx]->nbr_dim){ 00678 (void)fprintf(fp_stdout,"%s: ERROR Variable %s has lesser rank in first file than in second file (%d < %d). This feature is NCO TODO 552.\n",prg_nm,var_prc_1[idx]->nm,var_prc_1[idx]->nbr_dim,var_prc_2[idx]->nbr_dim); 00679 nco_exit(EXIT_FAILURE); 00680 } /* endif */ 00681 00682 (void)ncap_var_cnf_dmn(&var_prc_1[idx],&var_prc_2[idx]); 00683 } /* end else */ 00684 00685 /* var2 now conforms in size to var1, and is in memory */ 00686 00687 /* fxm: TODO 268 allow var1 or var2 to typecast */ 00688 /* Make sure var2 conforms to type of var1 */ 00689 if(var_prc_1[idx]->type != var_prc_2[idx]->type){ 00690 (void)fprintf(fp_stderr,"%s: WARNING Input variables do not conform in type:\nFile 1 = %s variable %s has type %s\nFile 2 = %s variable %s has type %s\nFile 3 = %s variable %s will have type %s\n",prg_nm,fl_in_1,var_prc_1[idx]->nm,nco_typ_sng(var_prc_1[idx]->type),fl_in_2,var_prc_2[idx]->nm,nco_typ_sng(var_prc_2[idx]->type),fl_out,var_prc_1[idx]->nm,nco_typ_sng(var_prc_1[idx]->type)); 00691 } /* endif different type */ 00692 var_prc_2[idx]=nco_var_cnf_typ(var_prc_1[idx]->type,var_prc_2[idx]); 00693 00694 /* Change missing_value of var_prc_2, if any, to missing_value of var_prc_1, if any */ 00695 has_mss_val=nco_mss_val_cnf(var_prc_1[idx],var_prc_2[idx]); 00696 00697 /* mss_val in fl_1, if any, overrides mss_val in fl_2 */ 00698 if(has_mss_val) mss_val=var_prc_1[idx]->mss_val; 00699 00700 /* Perform specified binary operation */ 00701 switch(nco_op_typ){ 00702 case nco_op_add: /* [enm] Add file_1 to file_2 */ 00703 (void)nco_var_add(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00704 case nco_op_mlt: /* [enm] Multiply file_1 by file_2 */ 00705 (void)nco_var_mlt(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00706 case nco_op_dvd: /* [enm] Divide file_1 by file_2 */ 00707 (void)nco_var_dvd(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00708 case nco_op_sbt: /* [enm] Subtract file_2 from file_1 */ 00709 (void)nco_var_sbt(var_prc_1[idx]->type,var_prc_1[idx]->sz,has_mss_val,mss_val,var_prc_2[idx]->val,var_prc_1[idx]->val); break; 00710 default: /* Other defined nco_op_typ values are valid for ncra(), ncrcat(), ncwa(), not ncbo() */ 00711 (void)fprintf(fp_stdout,"%s: ERROR Illegal nco_op_typ in binary operation\n",prg_nm); 00712 nco_exit(EXIT_FAILURE); 00713 break; 00714 } /* end case */ 00715 00716 var_prc_2[idx]->val.vp=nco_free(var_prc_2[idx]->val.vp); 00717 00718 #ifdef ENABLE_MPI 00719 /* Obtain token and prepare to write */ 00720 while(1){ /* Send msg_tag_tkn_wrt_rqs repeatedly until token obtained */ 00721 wrk_id_bfr[0]=prc_rnk; 00722 MPI_Send(wrk_id_bfr,wrk_id_bfr_lng,MPI_INT,rnk_mgr,msg_tag_tkn_wrt_rqs,MPI_COMM_WORLD); 00723 MPI_Recv(msg_bfr,msg_bfr_lng,MPI_INT,rnk_mgr,msg_tag_tkn_wrt_rsp,MPI_COMM_WORLD,&mpi_stt); 00724 tkn_wrt_rsp=msg_bfr[0]; 00725 /* Wait then re-send request */ 00726 if(tkn_wrt_rsp == tkn_wrt_rqs_dny) sleep(tkn_wrt_rqs_ntv); else break; 00727 } /* end while loop waiting for write token */ 00728 00729 /* Worker has token---prepare to write */ 00730 if(tkn_wrt_rsp == tkn_wrt_rqs_xcp){ 00731 rcd=nco_open(fl_out_tmp,NC_WRITE|NC_SHARE,&out_id); 00732 /* Turn off default filling behavior to enhance efficiency */ 00733 rcd=nco_set_fill(out_id,NC_NOFILL,&fll_md_old); 00734 #else /* !ENABLE_MPI */ 00735 #ifdef _OPENMP 00736 #pragma omp critical 00737 #endif /* !_OPENMP */ 00738 #endif /* !ENABLE_MPI */ 00739 /* Common code for UP, SMP, and MPI */ 00740 { /* begin OpenMP critical */ 00741 /* Copy result to output file and free workspace buffer */ 00742 if(var_prc_1[idx]->nbr_dim == 0){ 00743 (void)nco_put_var1(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_1[idx]->val.vp,var_prc_out[idx]->type); 00744 }else{ /* end if variable is scalar */ 00745 (void)nco_put_vara(out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_1[idx]->val.vp,var_prc_out[idx]->type); 00746 } /* end else */ 00747 } /* end OpenMP critical */ 00748 var_prc_1[idx]->val.vp=nco_free(var_prc_1[idx]->val.vp); 00749 00750 #ifdef ENABLE_MPI 00751 /* Close output file and increment written counter */ 00752 nco_close(out_id); 00753 var_wrt_nbr++; 00754 } /* endif tkn_wrt_rqs_xcp */ 00755 } /* end else !idx_all_wrk_ass */ 00756 } /* end while loop requesting work/token */ 00757 } /* endif Worker */ 00758 #else /* !ENABLE_MPI */ 00759 } /* end (OpenMP parallel for) loop over idx */ 00760 #endif /* !ENABLE_MPI */ 00761 if(dbg_lvl > 0) (void)fprintf(stderr,"\n"); 00762 00763 /* Close input netCDF files */ 00764 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_1_arr[thr_idx]); 00765 for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_2_arr[thr_idx]); 00766 00767 #ifdef ENABLE_MPI 00768 /* Manager moves output file (closed by workers) from temporary to permanent location */ 00769 if(prc_rnk == rnk_mgr) (void)nco_fl_mv(fl_out_tmp,fl_out); 00770 #else /* !ENABLE_MPI */ 00771 /* Close output file and move it from temporary to permanent location */ 00772 (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id); 00773 #endif /* end !ENABLE_MPI */ 00774 00775 /* Remove local copy of file */ 00776 if(FILE_1_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in_1); 00777 if(FILE_2_RETRIEVED_FROM_REMOTE_LOCATION && REMOVE_REMOTE_FILES_AFTER_PROCESSING) (void)nco_fl_rm(fl_in_2); 00778 00779 /* ncbo-unique memory */ 00780 if(fl_in_1 != NULL) fl_in_1=(char *)nco_free(fl_in_1); 00781 if(fl_in_2 != NULL) fl_in_2=(char *)nco_free(fl_in_2); 00782 00783 /* NCO-generic clean-up */ 00784 /* Free individual strings/arrays */ 00785 if(cmd_ln != NULL) cmd_ln=(char *)nco_free(cmd_ln); 00786 if(fl_out != NULL) fl_out=(char *)nco_free(fl_out); 00787 if(fl_out_tmp != NULL) fl_out_tmp=(char *)nco_free(fl_out_tmp); 00788 if(fl_pth != NULL) fl_pth=(char *)nco_free(fl_pth); 00789 if(fl_pth_lcl != NULL) fl_pth_lcl=(char *)nco_free(fl_pth_lcl); 00790 if(in_id_1_arr != NULL) in_id_1_arr=(int *)nco_free(in_id_1_arr); 00791 if(in_id_2_arr != NULL) in_id_2_arr=(int *)nco_free(in_id_2_arr); 00792 /* Free lists of strings */ 00793 if(fl_lst_in != NULL && fl_lst_abb == NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,fl_nbr); 00794 if(fl_lst_in != NULL && fl_lst_abb != NULL) fl_lst_in=nco_sng_lst_free(fl_lst_in,1); 00795 if(fl_lst_abb != NULL) fl_lst_abb=nco_sng_lst_free(fl_lst_abb,abb_arg_nbr); 00796 if(var_lst_in_nbr > 0) var_lst_in=nco_sng_lst_free(var_lst_in,var_lst_in_nbr); 00797 /* Free limits */ 00798 for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]); 00799 if(lmt_nbr > 0) lmt=nco_lmt_lst_free(lmt,lmt_nbr); 00800 /* Free dimension lists */ 00801 if(nbr_dmn_xtr_1 > 0) dim_1=nco_dmn_lst_free(dim_1,nbr_dmn_xtr_1); 00802 if(nbr_dmn_xtr_2 > 0) dim_2=nco_dmn_lst_free(dim_2,nbr_dmn_xtr_2); 00803 if(nbr_dmn_xtr_1 > 0) dmn_out=nco_dmn_lst_free(dmn_out,nbr_dmn_xtr_1); 00804 /* Free variable lists 00805 Using nco_var_lst_free() to free main var_1 and var_2 lists would fail 00806 if ncap_var_prc_dmn() had to broadcast any variables because pointer 00807 var_1 and var_2 still contain dangling pointer to old variable. 00808 Hence, use nco_var_lst_free() to free prc and fix lists and 00809 use nco_free() to free main var_1 and var_2 lists. 00810 Dangling pointers in var_1 and var_2 are unsafe: fxm TODO 578 */ 00811 if(nbr_var_prc_1 > 0) var_prc_1=nco_var_lst_free(var_prc_1,nbr_var_prc_1); 00812 if(nbr_var_fix_1 > 0) var_fix_1=nco_var_lst_free(var_fix_1,nbr_var_fix_1); 00813 if(nbr_var_prc_2 > 0) var_prc_2=nco_var_lst_free(var_prc_2,nbr_var_prc_2); 00814 if(nbr_var_fix_2 > 0) var_fix_2=nco_var_lst_free(var_fix_2,nbr_var_fix_2); 00815 var_1=(var_sct **)nco_free(var_1); 00816 var_2=(var_sct **)nco_free(var_2); 00817 if(nbr_xtr_1 > 0) var_out=nco_var_lst_free(var_out,nbr_xtr_1); 00818 var_prc_out=(var_sct **)nco_free(var_prc_out); 00819 var_fix_out=(var_sct **)nco_free(var_fix_out); 00820 00821 #ifdef ENABLE_MPI 00822 MPI_Finalize(); 00823 #endif /* !ENABLE_MPI */ 00824 00825 if(rcd != NC_NOERR) nco_err_exit(rcd,"main"); 00826 nco_exit_gracefully(); 00827 return EXIT_SUCCESS; 00828 } /* end main() */
|
1.4.4