! module output use params,only: nlev,model_version,spval use input,only: ncfile=>output,istep,nstep,f107,f107a use fields ! field typedef use restart,only: nf_hist use flds_hist,only: mxfhist,f_hist implicit none integer :: ncid ! netcdf file id integer :: nhist=0 ! number of histories on output file ! ! netcdf variable id's: ! (These are defined in first call to writehist, and retained ! for writing subsequent histories) ! integer :: id_time,id_lev,id_nbin_uars,id_nsftrf, | id_nsfdim1,id_nsfdima,id_nsfdimb,id_natm,id_nfatm,idv_time, | idv_lev, idv_year, idv_day, idv_ut, idv_dday, idv_f107d, | idv_f107a integer :: id_wv_low,id_wv_high,id_sminflx,id_smedflx, | id_smaxflx integer :: id_vl1, id_vl2, id_sfx, id_sgry, id_sgo2hz, | id_sgo31, id_sgo32 integer :: id_aij, id_bij integer :: id_ad00,id_ad10,id_bd00,id_bd10, id_atm integer :: idvars(mxfhist) ! #include contains !----------------------------------------------------------------------- subroutine writehist(yrday,iyear,iday,dday,ut,timehist) ! ! Write a history for current day and ut: ! use restart,only: | nbin_uars,natm,nfatm,nsftrf,nsfdim1,nsfdima, | nsfdimb, wv_low, wv_high, sminflx, smedflx, smaxflx, | vl1, vl2, sfx, sgry, sgo2hz, sgo31, sgo32, | aij, bij, ad00, ad10, bd00, bd10, atm use flds_fields use flds_modelz use flds_msisatm use flds_atmos use flds_ionatm use flds_ionzrt use flds_dissoc use flds_heat use flds_sodium implicit none ! ! Args: integer,intent(in) :: iyear,iday real,intent(in) :: ut,dday,yrday ! ! If timehist==.true., then write a time-dependent history. ! Otherwise, write time-independent fields. logical,intent(in) :: timehist ! ! Local: integer :: istat,i,idvar integer :: nnans,nanspval,nanfatal,nanprint character(len=120) :: char120 character(len=80) :: char80 character(len=8) :: curdate,curtime character(len=24) :: date_time,logname,system real :: year,day real :: xne_diag(nlev),xneee_diag(nlev) ! for debug ! write(6,"(/,72('-'))") ! write(6,"('Enter Writehist: iyear=',i4,' iday=',i3,' dday=',f8.2, ! | ' ut=',f8.2,' timehist=',l1)") iyear,iday,dday,ut,timehist ! ! If this is first history, open new file: if (nhist==0) then istat = nf_create(ncfile,NF_CLOBBER,ncid) if (istat /= NF_NOERR) then write(6,"('writehist: Error creating new netcdf file ',a)") | trim(ncfile) call handle_ncerr(istat,char120) else write(6,"('Created netcdf file ',a)") trim(ncfile) endif ! ! Global file attributes: istat = nf_put_att_text(ncid,NF_GLOBAL,"model_version", | len_trim(model_version),trim(model_version)) call datetime(curdate,curtime) ! util.F date_time = trim(curdate)//' '//trim(curtime) istat = nf_put_att_text(ncid,NF_GLOBAL,"file_creation_time", | len_trim(date_time),trim(date_time)) call getenv('LOGNAME',logname) ! get logname from env var istat = nf_put_att_text(ncid,NF_GLOBAL,"logname", | len_trim(logname),trim(logname)) call setosys(system) ! util.F istat = nf_put_att_text(ncid,NF_GLOBAL,"system", | len_trim(system),trim(system)) ! ! Define dimensions: ! ! Time is unlimited dimension: istat = nf_def_dim(ncid,"time",NF_UNLIMITED,id_time) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining time dimension') ! ! Number of levels: istat = nf_def_dim(ncid,"lev",nlev,id_lev) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining lev dimension') ! ! nbin_uars: istat = nf_def_dim(ncid,"nbin_uars",nbin_uars,id_nbin_uars) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining nbin_uars dimension') ! ! nsftrf: istat = nf_def_dim(ncid,"nsftrf",nsftrf,id_nsftrf) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining nsftrf dimension') ! ! nsfdim1,a,b: istat = nf_def_dim(ncid,"nsfdim1",nsfdim1,id_nsfdim1) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining nsfdim1 dimension') istat = nf_def_dim(ncid,"nsfdima",nsfdima,id_nsfdima) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining nsfdima dimension') istat = nf_def_dim(ncid,"nsfdimb",nsfdimb,id_nsfdimb) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining nsfdimb dimension') ! ! natm,nfatm: istat = nf_def_dim(ncid,"natm",natm,id_natm) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining natm dimension') istat = nf_def_dim(ncid,"nfatm",nfatm,id_nfatm) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error defining nfatm dimension') ! ! Define time (unlimited) dimension variable: ! This is total decimal days from year 0 to current model time. ! (See yrday in advance). ! call def1dvar('time','total days from year 0', | 'time','decimal days',id_time,idv_time) ! istat = nf_put_att_text(ncid,idvars(i),"restart", ! | len_trim(f_hist(i)%restart),trim(f_hist(i)%restart)) istat = nf_put_att_text(ncid,idv_time, | "derivation",22,"(year-1)*365+day+ut/24") ! ! Define day and ut variables: call def1dvar('year','calendar year','year',' ', | id_time,idv_year) call def1dvar('day','calendar day','day',' ', | id_time,idv_day) call def1dvar('dday','days from beginning of run', | 'dday','decimal days',id_time,idv_dday) call def1dvar('ut','universal time','UT','hours', | id_time,idv_ut) ! ! Levels coordinate variable: call def1dvar('lev','log pressure levels','LEV','LN(P0/P)', | id_lev,idv_lev) ! ! f107: call def1dvar('f107d','Daily 10.7 cm solar flux', | 'F107D','1.e-22 kg.s-4',id_time,idv_f107d) call def1dvar('f107a','81-day average 10.7 cm solar flux', | 'F107A','1.e-22 kg.s-4',id_time,idv_f107a) ! ! Define uars 1-d variables: ! subroutine def1dvar(name,long_name,short_name,units,id_dim,id_var) call def1dvar('wv_low' ,' ',' ',' ',id_nbin_uars,id_wv_low) call def1dvar('wv_high',' ',' ',' ',id_nbin_uars,id_wv_high) call def1dvar('sminflx',' ',' ',' ',id_nbin_uars,id_sminflx) call def1dvar('smedflx',' ',' ',' ',id_nbin_uars,id_smedflx) call def1dvar('smaxflx',' ',' ',' ',id_nbin_uars,id_smaxflx) ! ! Define nsftrf 1-d variables: call def1dvar('vl1' ,' ',' ',' ',id_nsftrf,id_vl1) call def1dvar('vl2' ,' ',' ',' ',id_nsftrf,id_vl2) call def1dvar('sfx' ,' ',' ',' ',id_nsftrf,id_sfx) call def1dvar('sgry' ,' ',' ',' ',id_nsftrf,id_sgry) call def1dvar('sgo2hz',' ',' ',' ',id_nsftrf,id_sgo2hz) call def1dvar('sgo31' ,' ',' ',' ',id_nsftrf,id_sgo31) call def1dvar('sgo32' ,' ',' ',' ',id_nsftrf,id_sgo32) ! ! Define aij,bij 2-d vars: call def2dvar('aij',' ',' ',' ',id_nsfdim1,id_nsfdima,id_aij) call def2dvar('bij',' ',' ',' ',id_nsfdim1,id_nsfdimb,id_bij) ! ! Define 1-d vars ad00,ad10,bd00,bd10: call def1dvar('ad00' ,' ',' ',' ',id_nsfdima,id_ad00) call def1dvar('ad10' ,' ',' ',' ',id_nsfdima,id_ad10) call def1dvar('bd00' ,' ',' ',' ',id_nsfdimb,id_bd00) call def1dvar('bd10' ,' ',' ',' ',id_nsfdimb,id_bd10) ! ! Define 2-d atm: call def2dvar('atm',' ',' ',' ',id_natm,id_nfatm,id_atm) ! ! Exit define mode: istat = nf_enddef(ncid) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error return from nf_enddef') ! ! Write values for uars variables: call put1dvar('wv_low' ,id_wv_low ,nlev,wv_low) call put1dvar('wv_high',id_wv_high,nlev,wv_high) call put1dvar('sminflx',id_sminflx,nlev,sminflx) call put1dvar('smedflx',id_smedflx,nlev,smedflx) call put1dvar('smaxflx',id_smaxflx,nlev,smaxflx) ! ! Write values for sftrf variables: call put1dvar('vl1' ,id_vl1 ,nsftrf,vl1) call put1dvar('vl2' ,id_vl2 ,nsftrf,vl2) call put1dvar('sfx' ,id_sfx ,nsftrf,sfx) call put1dvar('sgry' ,id_sgry ,nsftrf,sgry) call put1dvar('sgo2hz',id_sgo2hz,nsftrf,sgo2hz) call put1dvar('sgo31' ,id_sgo31 ,nsftrf,sgo31) call put1dvar('sgo32' ,id_sgo32 ,nsftrf,sgo32) ! ! Write values for aij,bij: call put2dvar('aij',id_aij,nsfdima,nsfdim1,aij) call put2dvar('bij',id_bij,nsfdima,nsfdim1,bij) ! ! Write values for ad00,ad10,bd00,bd10: call put1dvar('ad00' ,id_ad00 ,nsfdima,ad00) call put1dvar('ad10' ,id_ad10 ,nsfdima,ad10) call put1dvar('bd00' ,id_bd00 ,nsfdimb,bd00) call put1dvar('bd10' ,id_bd10 ,nsfdimb,bd10) ! ! Write values for atm: call put2dvar('atm',id_atm,nfatm,natm,atm) write(6,"('Writehist: defined netcdf dataset ',a)") | trim(ncfile) ! ! Not first call -> open existing file for appending: else ! nhist > 0 (not first call) istat = nf_open(ncfile,NF_WRITE,ncid) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error opening existing history file for appending.') write(6,"('Opened history file ',a,' for appending.')") | trim(ncfile) endif ! nhist==0 (first call) ! ! Rest is executed at every call: ! ! Define global mean primary history variables: floop: do i=1,nf_hist istat = nf_inq_varid(ncid,f_hist(i)%var_name,idvar) if (istat == NF_NOERR) then ! write(6,"('Writehist: i=',i3,' field ',a, ! | ' already defined: idvar=',i4)") i,f_hist(i)%var_name,idvar cycle floop ! field has already been defined endif ! ! Enter re-define mode: istat = nf_redef(ncid) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error return from nf_redef') ! ! Define new variable (idvars(i) is returned): if (trim(f_hist(i)%timedep)=='time-dependent') then call def2dvar(f_hist(i)%var_name,f_hist(i)%long_name, | f_hist(i)%short_name,f_hist(i)%units,id_lev,id_time, | idvars(i)) else call def1dvar(f_hist(i)%var_name,f_hist(i)%long_name, | f_hist(i)%short_name,f_hist(i)%units,id_lev,idvars(i)) endif ! ! Logplt: istat = nf_put_att_int(ncid,idvars(i),"logplt",NF_INT,1, | f_hist(i)%logplt) if (istat /= NF_NOERR) then write(char120,"('Error writing logplt attribute of ', | '2-d variable ',a,': logplt=',i3)") | f_hist(i)%var_name,f_hist(i)%logplt call handle_ncerr(istat,char120) endif ! ! Time-dependence: istat = nf_put_att_text(ncid,idvars(i),"timedep", | len_trim(f_hist(i)%timedep),trim(f_hist(i)%timedep)) if (istat /= NF_NOERR) then write(char120,"('Error defining timedep attribute for ', | 'field ',a,': timedep=',a)") trim(f_hist(i)%var_name), | trim(f_hist(i)%timedep) call handle_ncerr(istat,char120) endif ! ! Restart status (if restart=='yes', then field must be on the ! hist for model to restart). istat = nf_put_att_text(ncid,idvars(i),"restart", | len_trim(f_hist(i)%restart),trim(f_hist(i)%restart)) if (istat /= NF_NOERR) then write(char120,"('Error defining restart attribute for ', | 'field ',a,': restart=',a)") trim(f_hist(i)%var_name), | trim(f_hist(i)%restart) call handle_ncerr(istat,char120) endif ! write(6,"('Writehist: Defined ',a,' field ',a,' idvar=',i4)") ! | trim(f_hist(i)%timedep),f_hist(i)%var_name,idvars(i) ! ! Exit define mode: istat = nf_enddef(ncid) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error return from nf_enddef') enddo floop ! i=1,nf_hist ! ! Increment number of histories: if (timehist) nhist = nhist+1 ! ! Add to time-dependent variables time,day,ut: istat = nf_put_var1_double(ncid,idv_time,nhist,yrday) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for time variable') ! ! write(6,"('writehist: nhist=',i4,' iyear=',i4,' float(iyear)=', ! | f8.2,' iday=',i4,' float(iday)=',f8.2,' ut=',f8.2)") ! | nhist,iyear,float(iyear),iday,float(iday),ut ! ! netcdf (at least on hao linux) does not like float(iyear) as ! actual arg, so use local float year (same for day): year = float(iyear) istat = nf_put_var1_double(ncid,idv_year,nhist,year) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for year variable') ! day = float(iday) istat = nf_put_var1_double(ncid,idv_day,nhist,day) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for day variable') ! istat = nf_put_var1_double(ncid,idv_dday,nhist,dday) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for dday variable') ! istat = nf_put_var1_double(ncid,idv_ut ,nhist,ut) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for ut variable') ! istat = nf_put_var1_double(ncid,idv_f107d,nhist,f107) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for f107d variable') ! istat = nf_put_var1_double(ncid,idv_f107a,nhist,f107a) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error from nf_put_var1_double for f107a variable') ! ! Give values to global mean time-dependent history variables ! at current time step: ! if (timehist) then do i=1,nf_hist if (trim(f_hist(i)%timedep)=='time-dependent') then call put2dtimevar(f_hist(i)%var_name,idvars(i),nhist,nlev, | f_hist(i)%data) ! ! Check for NaNs in time-dependent output field: ! subroutine check_nans(f,id1,id2,id3,name,n_total,ispval,spval,iprint,ifatal) ! If nanfatal==1, sub check_nans (util.F) will stop if nans are found. ! If nanspval==1 (and nanfatal==0), NaNs are replaced with spval. nanfatal = 1 nanspval = 0 nanprint = 1 call check_nans(f_hist(i)%data,nlev,1,1,f_hist(i)%var_name, | nnans,nanspval,spval,nanprint,nanfatal) ! if (istep==nstep) then write(6,"('Wrote 2-d field ',i4,' ',a,': ', | ' istep=',i4,' min,max=',2e12.4)") | idvars(i),f_hist(i)%var_name(1:9),istep, | minval(f_hist(i)%data),maxval(f_hist(i)%data) elseif (istep==1) then write(6,"('Wrote 2-d field ',i4,' ',a,': ', | ' istep=',i4,' min,max=',2e12.4)") | idvars(i),f_hist(i)%var_name(1:9),istep, | minval(f_hist(i)%data),maxval(f_hist(i)%data) endif endif enddo ! i=1,nf_hist else ! timehist==.false. ! ! Write values for non-time-dependent variables: call put1dvar('lev',idv_lev,nlev,zp) do i=1,nf_hist if (trim(f_hist(i)%timedep)=='time-independent') then call put1dvar(f_hist(i)%var_name,idvars(i),nlev, | f_hist(i)%data) if (istep==nstep) then write(6,"('Wrote 1-d field ',i4,' ',a,': ', | ' istep=',i4,' min,max=',2e12.4)") | idvars(i),f_hist(i)%var_name(1:9),istep, | minval(f_hist(i)%data),maxval(f_hist(i)%data) elseif (istep==1) then write(6,"('Wrote 1-d field ',i4,' ',a,': ', | ' istep=',i4,' min,max=',2e12.4)") | idvars(i),f_hist(i)%var_name(1:9),istep, | minval(f_hist(i)%data),maxval(f_hist(i)%data) ! if (trim(f_hist(i)%var_name)=='TE') ! | write(6,"('TE(1)=',/,(4e16.8))") f_hist(i)%data endif endif enddo endif ! ! Close file: istat = nf_close(ncid) if (istat /= NF_NOERR) call handle_ncerr(istat, | 'Error return from nf_close') ! ! Report to stdout: if (timehist) then write(6,"('Writehist: Wrote history ',i4,': year=',i4, | ' day=',i3,' ut=',f8.2,' istep=',i4)") | nhist,iyear,iday,ut,istep else write(6,"('Writehist: Added time-independent fields to ', | 'history file ',a)") trim(ncfile) endif write(6,"(72('-')/)") end subroutine writehist !----------------------------------------------------------------------- subroutine def1dvar(name,long_name,short_name,units,id_dim,id_var) ! ! Define 1-d variable (type double) on netcdf file: ! implicit none ! ! Args: character(len=*),intent(in) :: name,long_name,short_name,units integer,intent(in) :: id_dim integer,intent(out) :: id_var ! ! Local: integer :: istat,ids1(1) character(len=120) :: char120 ! ids1(1) = id_dim istat = nf_def_var(ncid,name,NF_DOUBLE,1,ids1,id_var) if (istat /= NF_NOERR) then write(char120,"('Error defining 1-d variable ',a)") | trim(name) call handle_ncerr(istat,char120) endif ! ! Long name: if (len_trim(long_name) > 0) then istat = nf_put_att_text(ncid,id_var,"long_name", | len_trim(long_name),trim(long_name)) if (istat /= NF_NOERR) then write(char120,"('Error defining long_name of 1-d variable ', | a,': long_name=',a)") trim(name),trim(long_name) call handle_ncerr(istat,char120) endif endif ! ! Short name: if (len_trim(short_name) > 0) then istat = nf_put_att_text(ncid,id_var,"short_name", | len_trim(short_name),trim(short_name)) if (istat /= NF_NOERR) then write(char120,"('Error defining short_name of 1-d variable ', | a,': short_name=',a)") trim(name),trim(short_name) call handle_ncerr(istat,char120) endif endif ! ! Units: if (len_trim(units) > 0) then istat = nf_put_att_text(ncid,id_var,"units",len_trim(units), | trim(units)) if (istat /= NF_NOERR) then write(char120,"('Error defining units of 1-d variable ', | a,': units=',a)") trim(name),trim(units) call handle_ncerr(istat,char120) endif endif end subroutine def1dvar !----------------------------------------------------------------------- subroutine def2dvar(name,long_name,short_name,units, | id_dim1,id_dim2,id_var) ! ! Define 2-d variable (type double) on netcdf file: ! implicit none ! ! Args: character(len=*),intent(in) :: name,long_name,short_name,units integer,intent(in) :: id_dim1,id_dim2 integer,intent(out) :: id_var ! ! Local: integer :: istat,ids2(2) character(len=120) :: char120 ! ids2(1) = id_dim1 ids2(2) = id_dim2 istat = nf_def_var(ncid,name,NF_DOUBLE,2,ids2,id_var) if (istat /= NF_NOERR) then write(char120,"('Error defining 2-d variable ',a)") | trim(name) call handle_ncerr(istat,char120) endif ! ! Long name: if (len_trim(long_name) > 0) then istat = nf_put_att_text(ncid,id_var,"long_name", | len_trim(long_name),trim(long_name)) if (istat /= NF_NOERR) then write(char120,"('Error defining long_name of 2-d variable ', | a,': long_name=',a)") trim(name),trim(long_name) call handle_ncerr(istat,char120) endif endif ! ! Short name: if (len_trim(short_name) > 0) then istat = nf_put_att_text(ncid,id_var,"short_name", | len_trim(short_name),trim(short_name)) if (istat /= NF_NOERR) then write(char120,"('Error defining short_name of 2-d variable ', | a,': short_name=',a)") trim(name),trim(short_name) call handle_ncerr(istat,char120) endif endif ! ! Units: if (len_trim(units) > 0) then istat = nf_put_att_text(ncid,id_var,"units",len_trim(units), | trim(units)) if (istat /= NF_NOERR) then write(char120,"('Error defining units of 2-d variable ', | a,': units=',a)") trim(name),trim(units) call handle_ncerr(istat,char120) endif endif end subroutine def2dvar !----------------------------------------------------------------------- subroutine put1dvar(name,idv,idim,f) ! ! Write 1-d field f(idim) to current history file. ! implicit none ! ! Args: character(len=*),intent(in) :: name integer,intent(in) :: idv,idim real,intent(in) :: f(idim) ! ! Local: integer :: istat character(len=120) :: char120 ! istat = nf_put_var_double(ncid,idv,f) if (istat /= NF_NOERR) then write(char120,"('Error return from nf_put_var_double ', | ' to assign values to var ',a)") trim(name) call handle_ncerr(istat,char120) else ! write(6,"('put1dvar: Field ',a,' idv=',i3,' min,max=',2e12.4)") ! | name,idv,minval(f),maxval(f) endif end subroutine put1dvar !----------------------------------------------------------------------- subroutine put2dvar(name,idv,idim1,idim2,f) ! ! Write 2-d field f(idim1,idim2) to current history file. ! implicit none ! ! Args: character(len=*),intent(in) :: name integer,intent(in) :: idv,idim1,idim2 real,intent(in) :: f(idim1,idim2) ! ! Local: integer :: istat character(len=120) :: char120 ! istat = nf_put_var_double(ncid,idv,f) if (istat /= NF_NOERR) then write(char120,"('Error return from nf_put_var_double ', | ' to assign values to 2-d var ',a)") trim(name) call handle_ncerr(istat,char120) else ! write(6,"('put2dvar: Field ',a,' idv=',i3,' idim1,2=',2i4, ! | ' min,max=',2e12.4)") name,idv,idim1,idim2,minval(f),maxval(f) endif end subroutine put2dvar !----------------------------------------------------------------------- subroutine put2dtimevar(name,idv,itime,idim,f) ! ! Write time-dependent variable f(idim) to history file at time index ! itime (var should be dimensioned (time,idim) on the netcdf file, ! where idim is normally nlev). ! implicit none ! ! Args: character(len=*),intent(in) :: name integer,intent(in) :: idv,itime,idim real,intent(in) :: f(idim) ! ! Local: integer :: istat integer :: start_2d(2), count_2d(2) character(len=120) :: char120 ! start_2d(1) = 1 start_2d(2) = itime count_2d(1) = idim count_2d(2) = 1 istat = nf_put_vara_double(ncid,idv,start_2d,count_2d,f) if (istat /= NF_NOERR) then write(char120,"('Error return from nf_put_vara_double ', | ' to assign values to 2-d var ',a)") trim(name) call handle_ncerr(istat,char120) else ! write(6,"('put2dtimevar: Field ',a,' idv=',i3,' itime=',i3, ! | ' idim=',i4,' min,max=',2e12.4)") name,idv,itime,idim, ! | minval(f),maxval(f) endif end subroutine put2dtimevar !----------------------------------------------------------------------- subroutine handle_ncerr(istat,msg) implicit none ! ! Handle a netcdf lib error: ! integer,intent(in) :: istat character(len=*),intent(in) :: msg ! write(6,"(/72('-'))") write(6,"('>>> Error from netcdf library:')") write(6,"(a)") trim(msg) write(6,"('istat=',i5)") istat write(6,"(a)") nf_strerror(istat) write(6,"(72('-')/)") end subroutine handle_ncerr !----------------------------------------------------------------------- end module output