#include ! module input_module use params_module,only: mxhvols,mxseries,mxseries_sech,mxfsech, | nlat,nlon,nlev,glat1,dlat,glon1,dlon,tgcm_version,tgcm_name, | spval,ispval,mxday,nlonp4,mxind_time use mk_hvols,only: mkhvols implicit none ! ! Read and validate user inputs via namelist. ! Principle interface to the model is via a single call to sub input ! (which makes calls to the input module subroutines), and via ! "use input_module" statements in model subprograms. ! This module is dependent on the model header file "params.h" ! ! Procedure to add new input parameters: ! 0. Add any necessary parameter declarations in params.h ! (these are generally for dimensioning input variables) ! 1. Declare new module variables in proper category below ! (e.g., model-wide, primary histories, secondary histories, etc) ! 2. Add variables to namelist/tgcm_input/ ! 3. Initialize variables in inp_init ! 4. Add to stdout print in inp_print ! 5. Validate values read in appropriate routine (e.g., inp_hist, etc) ! (validation may include setting non-input variables related ! to the input values. These may be referenced from included ! header files or other modules). ! ! Namelist user input variables: ! character(len=1024) :: | label, ! optional generic text label for this run | tempdir, ! temporary directory | amievol, ! absolute or relative path to amie data file (optional) | hpss_path ! hpss directory for dispose of output history files ! ! date and calday are no longer supported, and are replaced by start_day, ! start_year, and calendar_advance. Date and calday are retained here so ! error usage statements can be issued if user sets one of them. ! integer :: | start_day, ! starting day of year (integer 0->365) | start_year, ! starting year (4-digit integer yyyy) | calendar_advance,! if > 0, advance calendar day from start_day | date(3), ! old: model starting year, day ( 2 ints yyyy,dd) | calday, ! old: starting calendar day (0-mxday) | step, ! model time step (integer seconds) | step_compqrj, ! qrj and composition time step (integer seconds) | step_ch4, ! comp_ch4 time step (integer seconds) | dispose, ! deprecated | difhor, ! horizontal eddy diffusion flag 0/1 | iuivi, ! ion drifts in momentum flag (replaced by dynamo flag) | dynamo, ! 0/1 flag for dynamo (only "new" dynamo is available) | tideann, ! 0/1 flag for annual tide | aurora, ! 0/1 flag for aurora | magphr, ! 0/1 flag for magnetosphere | solar_protons, ! 0/1 flag for high-energy solar protons (Jackman) | planetary, ! 0/1 flag to add planetary waves to lbc of Z | kelvin, ! 0/1 flag to add kelvin waves to lbc of Z | ntask_lat, ! number of tasks in latitude dimension | ntask_lon, ! number of tasks in longitude dimension | wacxg5_nlev, ! number of levels from lower boundary to nudge with wacxg5 | wacxg5_daily, ! 0/1 to daily average wacxg5 lower boundary data | wacxg5_zm ! 0/1 to use zonal mean wacxg5 lower boundary data real :: | tide(10), ! semidiurnal tide amplitudes and phases | tide2(2), ! diurnal tide amplitude and phase | tide3m3(2), ! 2-day wave amplitude and phase | f107, ! 10.7 cm daily solar flux | f107a, ! 10.7 cm average (81-day) solar flux | power, ! hemispheric power (gw) (hpower on histories) | ctpoten, ! cross-cap potential (volts) | f107_time (4,mxind_time), ! time-dependent daily f10.7 flux | f107a_time(4,mxind_time), ! time-dependent 81-day average f10.7 flux | power_time(4,mxind_time), ! time-dependent hemispheric power input | ctpoten_time(4,mxind_time), ! time-dependent cross tail potential input | kp_time(4,mxind_time), ! time-dependent Kp | byimf, ! BY component of IMF | bzimf, ! Bz component of IMF in nT | swvel, ! Solar wind velocity in km/s | swden, ! Solar wind density in #/cm3 | AL, ! AL lower magnetic auroral activity index in nT ! if present, ALUSE=true; if absent, AL=-20, ALUSE=false | colfac, ! collision factor | kp ! Kp index logical :: aluse ! logical to use AL in Weimer model or not ! ! Parameters as read from namelist: real :: rd_power,rd_ctpoten,rd_f107,rd_f107a,rd_bximf,rd_byimf, | rd_bzimf,rd_swvel,rd_swden,rd_kp ! ! Import data file names: integer,parameter :: mxlen_filename=1024 character(len=mxlen_filename) :: | potential_model, ! electric potential model used ! Values can be 'HEELIS', 'WEIMER', or 'NONE' ! If absent, the default value is set to 'HEELIS' | weimer_ncfile, ! absolute or relative path to netcdf weimer coef file ! see comments in weimer_mod.f | weimer_ncfiledef, ! default path to weimer coef data file ! hrindices_ncfile NOT MADE YET! 11/15/02: | hrindices_ncfile, ! absolute or relative path to netcdf hourly geophysical ! data indices file. see comments in hrindices_mod.f | hrindices_ncfiledef, ! default path to hrly indices data file ! | gpi_ncfile, ! absolute or relative path to netcdf gpi data file | ncep_ncfile, ! absolute or relative path to netcdf ncep data file | ncep_reanalysis, ! path to ncep reanalysis nc data file for T,Z lbc | ecmwf_ncfile, ! path to ECMWF ERA-40 nc data file for T,Z lbc | wacxg5_ncfiles(mxhvols), ! waccmx-goes5 files for lbc nudging | gswm_mi_di_ncfile, ! gswm migrating diurnal data file | gswm_mi_sdi_ncfile, ! gswm migrating semi-diurnal data file | gswm_nm_di_ncfile, ! gswm non-migrating diurnal data file | gswm_nm_sdi_ncfile, ! gswm non-migrating semi-diurnal data file | solgar_bndry_file, ! solgar boundary file | solgar_import_file, ! solgar import file | zatmos_ncfile, ! zatmos data file | meped_file, ! MEPED data (see meped.F) ! ! Non-input gpi variables: | gpi_ncfiledef, ! default path to gpi data file | ncep_ncfiledef ! default path to ncep data file integer :: | ntimes_f107, ! number of times provided in f107_time | ntimes_f107a, ! number of times provided in f107a_time | ntimes_ctpoten, ! number of times provided in ctpoten_time | ntimes_power, ! number of times provided in power_time | ntimes_kp ! number of times provided in kp ! ! Primary history user input (dimension parameters are in params.h): character(len=1024) :: | source, ! file containing source history (optional) | output(mxhvols) ! output file(s) (required) integer :: | source_start(3), ! source history model time | start(3,mxseries), ! primary history model start time(s) | stop(3,mxseries), ! primary history model stop time(s) | hist(3,mxseries), ! primary history disk write frequency | save(3,mxseries), ! deprecated | mxhist_prim, ! max number of histories per primary file | noutput ! number of output files given ! ! Secondary history user input (dimension parameters are in params.h): character(len=1024) :: | secsource, ! file containing source sec_history (for mhd) | secout(mxhvols) ! secondary history output file(s) character(len=16) :: | secflds(mxfsech), ! secondary history output fields | secfmag(mxfsech), ! secondary output fields on magnetic grid | secfgeo2d(mxfsech), ! secondary output fields on geographic 2d grid | secfmag2d(mxfsech), ! secondary output fields on magnetic 2d grid | secfmagphr(mxfsech) ! secondary output fields on magnetospheric 2d grid integer :: | secstart(3,mxseries), ! secondary history model start time(s) | secstop(3,mxseries), ! secondary history model stop time(s) | sechist(3,mxseries), ! secondary history disk write frequency | secsave(3,mxseries), ! deprecated | mxhist_sech, ! max number of histories per secondary file | sech_nbyte ! 4 or 8: write real or double values to secondary file ! ! Namelist for read: namelist/tgcm_input/ | label,tempdir,amievol,date,calday,step,dispose, | source,source_start,output,start,stop,hist,save, | secout,secstart,secstop,sechist,secsave,secflds, | secfmag,secfgeo2d,secfmag2d,secfmagphr,potential_model, | difhor,iuivi,dynamo,tide,tide2,tide3m3,f107,f107a, | power,ctpoten,byimf,bzimf,swvel,swden,al,colfac,tideann,aurora, | magphr,solar_protons,gpi_ncfile,ncep_ncfile, gswm_mi_di_ncfile, | ncep_reanalysis,ecmwf_ncfile,step_compqrj,step_ch4, | gswm_mi_sdi_ncfile, gswm_nm_di_ncfile, gswm_nm_sdi_ncfile, | solgar_bndry_file,solgar_import_file,zatmos_ncfile,mxhist_prim, | mxhist_sech,ntask_lat,ntask_lon,start_day,start_year, | calendar_advance,ctpoten_time,power_time,f107_time,f107a_time, | meped_file,weimer_ncfile,planetary,kelvin,sech_nbyte,hpss_path, | wacxg5_ncfiles,wacxg5_nlev,wacxg5_daily,wacxg5_zm,kp,kp_time ! ! List of fields that are always written to secondary histories: character(len=16) :: secflds_mandatory(4) = | (/'TN ', | 'O2 ', | 'O1 ', | 'Z '/) character(len=16) :: secfmag_mandatory(1) = | (/'ZMAG '/) ! ! Current working (execution) directory (set by tgcm.F): character(len=120) :: cwd ! current working directory integer :: pid ! current process id integer :: wacxg5_nfiles contains !------------------------------------------------------------------- subroutine input(mytid,ntask) ! ! Read and validate user namelist input (called from main tgcm.F). ! ! Args: integer,intent(in) :: mytid,ntask ! ! Initialize: call inp_init ! ! Do namelist read (see inp_read.F): call inp_read(mytid) ! ! Validate model-wide input: ! (this can be split out into separate routines later) call inp_model(ntask) ! ! Validate history input: call inp_primhist call inp_sechist ! ! Validate lower boundary options: call inp_lbc ! ! Print type(input_typ) inp: call inp_print(ntask) ! end subroutine input !------------------------------------------------------------------- subroutine inp_init ! ! Initialize input variables: ! label = ' ' tempdir = ' ' amievol = ' ' hpss_path = ' ' ! gpi_ncfile = ' ' ! user input gpi file path gpi_ncfiledef = ' ' ! default gpi file path write(gpi_ncfiledef,"('/TGCM/data/gpi_1979001-2004060.nc')") ! ncep_ncfile = ' ' ! user input ncep file path ncep_ncfiledef = ' ' ! default ncep file path write(ncep_ncfiledef,"('/TGCM/data/ncep_1979001-2003059.nc')") ncep_reanalysis = ' ' ! ncep reanalysis file path ecmwf_ncfile = ' ' ! ECMWF ERA-40 nc data file for T,Z lbc wacxg5_ncfiles(:) = ' '! WACCM-X GOES5 files for lb nudging wacxg5_nlev = ispval ! number of levels to nudge with wacxg5 wacxg5_daily = ispval ! 0/1 for whether or not to daily-average wacxg5 data wacxg5_daily = ispval ! 0/1 for whether or not to zonal-mean wacxg5 data ! weimer_ncfile = ' ' ! user input weimer coef file path weimer_ncfiledef = ' ' ! default weimer coef file path write(weimer_ncfiledef,"('/hao/tgcm/data/weimer2001_coeffs.nc')") ! hrindices_ncfile = ' ' ! user input hrly indices data file path hrindices_ncfiledef = ' ' ! default hrly indices data file path ! write(hrindices_ncfiledef, ! | "('/TGCM/data/hrindices_1988001-2002181.nc')") ! gswm_mi_di_ncfile = ' ' ! diurnal tide: user input gswm file gswm_mi_sdi_ncfile= ' ' ! semidiurnal tide: user input gswm file gswm_nm_di_ncfile = ' ' ! nonmigrating diurnal tide: user input gswm file gswm_nm_sdi_ncfile= ' ' ! nonmigrating semidiurnal tide: user input gswm file ! solgar_bndry_file = ' ' solgar_import_file = ' ' zatmos_ncfile = ' ' meped_file = ' ' ! date(:) = ispval ! old calday = ispval ! old ! start_day = ispval start_year = ispval calendar_advance = ispval ! step = ispval step_compqrj= ispval step_ch4= ispval dispose = ispval difhor = ispval iuivi = ispval dynamo = ispval tide(:) = spval tide2(:)= spval tide3m3(:) = spval tideann = ispval aurora = ispval magphr = ispval solar_protons = ispval planetary = ispval kelvin = ispval ntask_lat = ispval ntask_lon = ispval f107 = spval f107a = spval power = spval ctpoten = spval f107_time (:,:) = spval f107a_time (:,:) = spval power_time (:,:) = spval ctpoten_time(:,:) = spval kp_time (:,:) = spval byimf = spval bzimf = spval swvel = spval swden = spval al = spval colfac = spval kp = spval ! potential_model = ' ' source = ' ' output = ' ' source_start(:) = ispval start(:,:) = ispval stop(:,:) = ispval hist(:,:) = ispval save(:,:) = ispval mxhist_prim = 10 ! default max number of histories per primary file if (dlat == 2.5) mxhist_prim = 5 ! 2.5 degree horizontal resolution ! secout(:) = ' ' secsource = ' ' secflds(:) = ' ' secfmag(:) = ' ' secfgeo2d(:) = ' ' secfmag2d(:) = ' ' secfmagphr(:) = ' ' secstart(:,:) = ispval secstop(:,:) = ispval sechist(:,:) = ispval secsave(:,:) = ispval mxhist_sech = 24 ! default max number of histories per sech file if (dlat == 2.5) mxhist_sech = 12 ! 2.5 degree horizontal resolution sech_nbyte = ispval end subroutine inp_init !------------------------------------------------------------------- subroutine inp_model(ntask) ! ! Args: integer,intent(in) :: ntask ! ! Local: integer :: i,n,ier,l1,l2,l3 character(len=16) :: logname real :: rday,rhour,rmin,rval ! ! Set temporary directory (settmpdir is in util.F): ! ! Get login name: logname = ' ' call getenv('LOGNAME',logname) if (len_trim(logname)==0) then write(6,"(/,'>>> INPUT inp_model: Cannot get LOGNAME', | ' environment variable.',/)") call shutdown('LOGNAME') endif ! ! Temporary scratch directory: ! if (len_trim(tempdir)==0) ! | call settmpdir(logname,tgcm_version,tempdir) ! ! If tempdir is same as execution directory (cwd), turn off tempdir: if (trim(tempdir)=='.'.or.trim(tempdir)==trim(cwd)) then write(6,"(/,'NOTE: Temporary scratch directory tempdir (', | a,')')") trim(cwd) write(6,"(' is same as execution directory -- will', | ' use only cwd.')") tempdir = ' ' endif ! ! Model time step (secs): ! If step < 60, it is assumed to be in minutes (enforce step <= 10 ! minutes), otherwise is in seconds (must be multiple of 60, i.e., ! even number of minutes). ! if (step==ispval) then write(6,"(/,'>>> INPUT: need model time step STEP ', | '(integer seconds)',/)") call shutdown('STEP') endif if (step <= 0) then write(6,"(/,'>>> INPUT: bad time step STEP: ',i5, | ' (must be > 0)',/)") step call shutdown('STEP') endif ! ! step_compqrj: Default is step. step_compqrj must be multiple of step. if (step_compqrj==ispval) then write(6,"('input: setting step_compqrj = step = ',i4)") step step_compqrj = step endif if (step_compqrj <= 0) then write(6,"(/,'>>> INPUT: bad time step STEP_COMPQRJ: ',i5, | ' (must be > 0)',/)") step_compqrj call shutdown('STEP_COMPQRJ') endif if (mod(step_compqrj,step) /= 0.or.step_compqrj < step) then write(6,"('>>> INPUT: step_compqrj must be a multiple of ', | 'time step. STEP=',i4,' STEP_COMPQRJ=',i4)") | step,step_compqrj call shutdown('STEP_COMPQRJ') endif ! ! step_ch4: Default is step. step_ch4 must be multiple of step. if (step_ch4==ispval) then write(6,"('input: setting step_ch4 = step = ',i4)") step step_ch4 = step endif if (step_ch4 <= 0) then write(6,"(/,'>>> INPUT: bad time step STEP_CH4: ',i5, | ' (must be > 0)',/)") step_ch4 call shutdown('STEP_CH4') endif if (mod(step_ch4,step) /= 0.or.step_ch4 < step) then write(6,"('>>> INPUT: step_ch4 must be a multiple of ', | 'time step. STEP=',i4,' STEP_CH4=',i4)") step,step_ch4 call shutdown('STEP_CH4') endif ! ! Old starting date and calday (no longer supported): if (any(date/=ispval)) then write(6,"(/,'>>> INPUT: DATE is no longer supported as an ', | 'input parameter.')") call usage_calendar call shutdown('date') endif if (calday /= ispval) then write(6,"(/,'>>> INPUT: CALDAY is no longer supported ', | 'as an input parameter.')") call usage_calendar call shutdown('calday') endif ! ! Verify start_year, start_day, calendar_advance: ! start_day is starting day of the year (1-365) ! start_year is starting year (4-digit yyyy) ! calendar_advance is 0/1 for whether or not to advance calendar time. ! if (start_year==ispval) then write(6,"(/,'>>> INPUT: need START_YEAR (4-digit integer ', | 'starting year.')") call usage_calendar call shutdown('start_year') endif if (start_year <= 0) then write(6,"(/,'>>> INPUT: bad START_YEAR=',i4,' (must be > 0)')") | start_year call shutdown('start_year') endif if (start_day==ispval) then write(6,"(/,'>>> INPUT: need START_DAY (integer calendar ', | 'starting day of year (0->365))')") call usage_calendar call shutdown('start_day') endif if (start_day <= 0.or.start_day > 365) then write(6,"(/,'>>> INPUT: bad START_DAY=',i4,' (must be between', | ' 1 and 365)')") start_day call shutdown('start_day') endif if (calendar_advance==ispval) then write(6,"(/,'INPUT NOTE: CALENDAR_ADVANCE was not provided', | ' by input.')") write(6,"('Will default to 1 (WILL advance calendar day)',/)") calendar_advance = 1 endif ! ! Tide: n = size(tide)-count(tide==spval) if (n /= 10) then write(6,"(/'>>> INPUT: must have 10 entries for TIDE,', | ' got ',i3)") n call shutdown('TIDE') endif do i=1,5 if (tide(i) < 0.) then write(6,"(/,'>>> INPUT: amplitudes for TIDE(1:5) must ', | 'be > 0.: tide=',/,(5e12.4))") tide call shutdown('TIDE') endif enddo ! ! Tide2: n = size(tide2)-count(tide2==spval) if (n /= 2) then write(6,"(/,'>>> INPUT: must have 2 entries for TIDE2,', | ' got ',i3)") n call shutdown('TIDE2') endif if (tide2(1) < 0.) then write(6,"(/,'>>> INPUT: amplitude for TIDE2(1) must ', | 'be > 0.: tide2=',e12.4)") tide2 call shutdown('TIDE2') endif ! ! Tide3m3 (in time-gcm only, not in tiegcm): n = size(tide3m3)-count(tide3m3==spval) if (n > 0) then if (tgcm_name /= "time-gcm") then write(6,"(/,'>>> INPUT: there is no 2-day wave in ',a)") | trim(tgcm_name) write(6,"( ' (tide3m3 is ignored)')") else if (n /= 2) then write(6,"(/,'>>> INPUT: need 2 real values for TIDE3M3')") write(6,"(' (amplitude and phase of 2-day wave)')") call shutdown('TIDE3M3') endif endif endif if (n <= 0 .and. tgcm_name=="time-gcm") then write(6,"(/,'>>> WARNING INPUT: did not read input parameter', | 'TIDE3M3 -- am setting TIDE3M3 = 0. (no 2-day wave)')") tide3m3(:) = 0. endif if (any(tide3m3==spval)) tide3m3(:) = 0. ! ! Annual tide flag: if (tideann==ispval) then tideann = 0 ! default is off unless zatmos is specified if (len_trim(zatmos_ncfile) > 0) tideann = 1 elseif (tideann /= 0 .and. tideann /= 1) then write(6,"(/,'>>> INPUT: TIDEANN must be either 0 or 1:', | ' tideann=',i5)") tideann call shutdown('TIDEANN') endif ! ! Must include annual tide if using zatmos lbc: if (len_trim(zatmos_ncfile) > 0.and.tideann <= 0) then write(6,"('>>> Input: must have TIDEANN=1 if setting ', | 'ZATMOS_NCFILE (Annual tide must be on if using Zatmos', | 'lbc.')") call shutdown('TIDEANN') endif ! ! Aurora flag: if (aurora==ispval) then write(6,"(/,'Input: setting default AURORA = 0')") aurora = 0 endif ! ! Magnetospheric flag: if (magphr==ispval) then write(6,"(/,'Input: setting default MAGPHR = 0')") magphr = 0 endif ! ! Solar protons flag: if (solar_protons==ispval) then write(6,"(/,'Input: setting default SOLAR_PROTONS = 0')") solar_protons = 0 endif ! ! Planetary and kelvin waves in Z lbc (see subs in lbc.F): if (planetary==ispval) then write(6,"(/,'Input: setting default PLANETARY = 0')") planetary = 0 endif if (kelvin==ispval) then write(6,"(/,'Input: setting default KELVIN = 0')") kelvin = 0 endif ! ! Number of tasks in lat,lon dimensions (ntask_lat*ntask_lon must == ntask): #ifdef MPI if (ntask_lat==ispval.or.ntask_lon==ispval) then call mkntask(ntask,ntask_lat,ntask_lon,ier) if (ier /= 0) then write(6,"(/,'>>> INPUT: error from mkntask. ntask_lat=', | i3,' ntask_lon=',i3,' ntask=',i3)") ntask_lat,ntask_lon, | ntask call shutdown('MKNTASK') else write(6,"('Input: mkntask chose ntask_lon=',i3, | ' ntask_lat=',i3,' (ntask=',i3,')')") | ntask_lon,ntask_lat,ntask endif ! write(6,"(/,'>>> INPUT: for MPI runs, you must specify ', ! | 'NTASK_LAT as the number of',/,4x,'MPI tasks in the ', ! | 'latitude dimension, and NTASK_LON as the number of', ! | /,4x,'MPI tasks in the longitude dimension.',/)") ! call shutdown("NTASK_LAT|LON") endif if (ntask_lat*ntask_lon /= ntask) then write(6,"(/,'>>> INPUT: NTASK_LAT * NTASK_LON must ', | 'equal the total number of tasks for the run.')") write(6,"(4x,'ntask_lat=',i3,' ntask_lon=',i3, | ' ntask=',i4,/)") ntask_lat,ntask_lon,ntask call shutdown("NTASK_LAT|LON") endif #endif ! ! Geophysical indices: ! ! Daily f10.7 cm flux: if (f107 /= spval .and. f107 <= 0.) then write(6,"(/'>>> INPUT: f107 must be positive: f107=', | e12.4)") f107 call shutdown('F107') endif ! c(61) is replaced by f107 from input_mod. ! c(61) = f107 ! this may get reset later by getgpi or tail ! ! 80-day mean f10.7 flux: if (f107a /= spval .and. f107a <= 0.) then write(6,"(/'>>> INPUT: f107a must be positive: f107a=', | e12.4)") f107a call shutdown('F107A') endif ! ! There are 3 input options for gpi indices ctpoten, power, f107, f107a: ! 1) Constants are provided by the user (ctpoten, power, etc) ! 2) Time series are provided by the user (ctpoten_time, power_time, etc) ! 3) GPI database (neither constans nor time series were provided) ! ! Cannot provide both constant and time series: if (ctpoten /= spval .and. any(ctpoten_time /= spval)) then write(6,"(/,'>>> INPUT: you cannot provide both a constant', | '(CTPOTEN) and a time-series (CTPOTEN_TIME) for cross-', | 'tail potential.')") call shutdown('CTPOTEN') endif if (power /= spval .and. any(power_time /= spval)) then write(6,"(/,'>>> INPUT: you cannot provide both a constant', | ' (POWER) and a time-series (POWER_TIME) for hemispheric', | ' power.')") call shutdown('POWER') endif if (f107 /= spval .and. any(f107_time /= spval)) then write(6,"(/,'>>> INPUT: you cannot provide both a constant', | ' (F107) and a time-series (F107_TIME) for hemispheric', | ' f107.')") call shutdown('F107') endif if (f107a /= spval .and. any(f107a_time /= spval)) then write(6,"(/,'>>> INPUT: you cannot provide both a constant', | ' (F107A) and a time-series (F107A_TIME) for hemispheric', | ' f107a.')") call shutdown('F107A') endif if (kp /= spval .and. any(kp_time /= spval)) then write(6,"(/,'>>> INPUT: you cannot provide both a constant', | ' (KP) and a time-series (KP_TIME) for Kp')") call shutdown('KP') endif ! ! User-provided gpi constants must be positive: if (ctpoten /= spval .and. ctpoten <= 0.) then write(6,"(/'>>> INPUT: ctpoten must be positive: ctpoten=', | e12.4)") ctpoten call shutdown('CTPOTEN') endif if (power /= spval .and. power <= 0.) then write(6,"(/'>>> INPUT: power must be positive: power=', | e12.4)") power call shutdown('POWER') endif if (f107 /= spval .and. f107 <= 0.) then write(6,"(/'>>> INPUT: f107 must be positive: f107=', | e12.4)") f107 call shutdown('F107') endif if (f107a /= spval .and. f107a <= 0.) then write(6,"(/'>>> INPUT: f107a must be positive: f107a=', | e12.4)") f107a call shutdown('F107A') endif if (kp /= spval .and. kp <= 0.) then write(6,"(/'>>> INPUT: kp must be positive: kp=', | e12.4)") kp call shutdown('KP') endif ! ! Validate times and values in user-provided time series for ! crosstail potential and hemispheric power: call validate_indices_time(ctpoten_time,ntimes_ctpoten, | 'CTPOTEN_TIME') call validate_indices_time(power_time,ntimes_power, | 'POWER_TIME') call validate_indices_time(f107_time,ntimes_f107, | 'F107_TIME') call validate_indices_time(f107a_time,ntimes_f107a, | 'F107A_TIME') call validate_indices_time(kp_time,ntimes_kp, | 'KP_TIME') ! ! Model must advance in calendar time for GPI database to be used: ! (see calday verification above) ! if (calendar_advance <= 0) then write(6,"(/,'>>> INPUT: Model must advance in calendar', | ' time if GPI database is to be used.')") write(6,"(' To make a GPI run, you must set ', | 'CALENDAR_ADVANCE = 1')") call shutdown('GPI') endif ! if (len_trim(gpi_ncfile)==0) then if (power==spval.and.ntimes_power==0.and. | kp==spval.and.ntimes_kp==0) then write(6,"(/,'>>> INPUT: POWER or POWER_TIME must be ', | 'provided for non-GPI run with Heelis potential model.')") call shutdown('POWER') endif if (ctpoten==spval.and.ntimes_ctpoten==0.and. | kp==spval.and.ntimes_kp==0) then write(6,"(/,'>>> INPUT: CTPOTEN or CTPOTEN_TIME must be ', | 'provided for non-GPI run with Heelis potential model.')") call shutdown('CTPOTEN') endif if (f107==spval.and.ntimes_f107==0) then write(6,"(/,'>>> INPUT: F107 must be provided for non-GPI', | ' run with Heelis potential model.')") call shutdown('F107') endif if (f107a==spval.and.ntimes_f107a==0) then write(6,"(/,'>>> INPUT: F107a must be provided for non-GPI', | ' run with Heelis potential model.')") call shutdown('F107a') endif ! ! Heelis gpi run: ! else ! gpi run ! ! At least one of the gpi params must NOT be provided: ! (i.e., at least one parameter will come from the gpi data file) ! if ((power /= spval.or.ntimes_power > 0).and. | (ctpoten/= spval.or.ntimes_ctpoten > 0).and. | (f107 /= spval.and.f107a /= spval)) then write(6,"(/,'>>> INPUT: At least one of power, ctpoten,', | ' f107 or f107a must NOT be provided for a gpi run.')") call shutdown('GPI params') endif endif ! gpi data run ! ! zatmos data file: if (len_trim(zatmos_ncfile) > 0) call expand_path(zatmos_ncfile) ! ! Jan, 2007: ! T,Z lbc data files can be 0 or 1 of the following 3 choices: ! ncep_ncfile: Original ncep data via Bill Randell and /home/tgcm/mkncep) ! ncep_reanalysis: NCAR/NCEP re-analysis data (see /home/tgcm/ncep_reanalysis) ! ecmwf_ncfile: ECMWF ERA-40 data (see /home/tgcm/ecmwf_era40) ! l1 = 0 ; l2 = 0 ; l3 = 0 if (len_trim(ncep_ncfile) > 0) l1 = 1 if (len_trim(ncep_reanalysis) > 0) l2 = 1 if (len_trim(ecmwf_ncfile) > 0) l3 = 1 n = l1+l2+l3 if (n > 1) then write(6,"(/,'>>> INPUT: Cannot set more than one of the ', | 'following file specifications for T,Z lbc:')") write(6,"(' ncep_ncfile = ',a)") trim(ncep_ncfile) write(6,"(' ncep_reanalysis = ',a)") trim(ncep_reanalysis) write(6,"(' ecmwf_ncfile = ',a)") trim(ecmwf_ncfile) call shutdown('T,Z lbc data files') endif if (len_trim(ncep_ncfile) > 0) call expand_path(ncep_ncfile) if (len_trim(ncep_reanalysis) > 0) | call expand_path(ncep_reanalysis) if (len_trim(ecmwf_ncfile) > 0) Call expand_path(ecmwf_ncfile) ! ! Nudging with waccm-x wacxg5: ! wacxg5_nfiles=0 do n=1,mxhvols if (len_trim(wacxg5_ncfiles(n)) > 0) then wacxg5_nfiles = wacxg5_nfiles+1 call expand_path(wacxg5_ncfiles(n)) endif enddo if (wacxg5_nfiles > 0) then if (wacxg5_nlev == ispval) then write(6,"('>>> INPUT: if wacxg5 files are provided, then', | ' you must set number of nudging levels wacxg5_nlev >= 1')") call shutdown('input wacxg5_nlev') endif if (wacxg5_daily == ispval) then write(6,"('>>> INPUT: if wacxg5 files are provided, then', | ' you must set wacxg5_daily to 0 or 1')") call shutdown('input wacxg5_daily') endif if (wacxg5_zm == ispval) then write(6,"('>>> INPUT: if wacxg5 files are provided, then', | ' you must set wacxg5_zm to 0 or 1')") call shutdown('input wacxg5_zm') endif if (wacxg5_daily > 0.and.wacxg5_zm > 0) then write(6,"('>>> INPUT: if wacxg5 files are provided, then', | ' you cannot set both wacxg5_daily and wacxg5_zm: ', | 'wacxg5_daily=',i3,' wacxg5_zm=',i3)") wacxg5_daily, | wacxg5_zm call shutdown('input: wacxg5_zm and wacxg5_daily') endif if (wacxg5_nlev <= 0 .or. wacxg5_nlev > nlev) then write(6,"('>>> INPUT: bad wacxg5_nlev=',i4,' must be ', | '> 0 and <= nlev (nlev=',i4,')')") wacxg5_nlev,nlev call shutdown('bad wacxg5_nlev') endif write(6,"('Input: wacxg5_nfiles=',i4,' wacxg5_nlev=',i4, | ' wacxg5_daily=',i3,' wacxg5_zm=',i3)") | wacxg5_nfiles,wacxg5_nlev,wacxg5_daily,wacxg5_zm endif ! ! GSWM data files: if (len_trim(gswm_mi_di_ncfile) > 0) | call expand_path(gswm_mi_di_ncfile) if (len_trim(gswm_mi_sdi_ncfile) > 0) | call expand_path(gswm_mi_sdi_ncfile) if (len_trim(gswm_nm_di_ncfile) > 0) | call expand_path(gswm_nm_di_ncfile) if (len_trim(gswm_nm_sdi_ncfile) > 0) | call expand_path(gswm_nm_sdi_ncfile) ! ! Check to see if have hrindices_ncfile (when avail! 11/15/02) ! ! Check electric potential model: if (potential_model == 'WEIMER') then write (6,"('Input: will use the Weimer 2001 electric potential', | ' model')") if (len_trim(weimer_ncfile)==0) then write(6,"('Input: will use default WEIMER_NCFILE: ',a)") | trim(weimer_ncfiledef) weimer_ncfile = weimer_ncfiledef else write(6,"('Input: will use user-provided path to Weimer ', | 'coefs Weimer_NCFILE = ',a)") trim(weimer_ncfile) endif elseif (potential_model == 'HEELIS') then write (6,"('Input: will use the Heelis electric potential', | ' model')") elseif (potential_model == 'NONE') then write (6,"('Input: will use NONE (ie zero) electric potential', | ' model')") endif if (len_trim(potential_model)==0) then write (6,"('Input: will use default Heelis elecric potential', | ' model')") potential_model='HEELIS' endif ! ! BY component of solar IMF magnetic field: if (byimf==spval) then write(6,"(/'>>> INPUT: need 1 value for byimf', | ' e.g.: BYIMF=0.')") write(6,"('NOTE: multiple (time-dependent) values for BYIMF', | ' not yet supported')") call shutdown('BYIMF') endif ! ! Limits on By NOT necessary for Weimer (or for NONE) if (potential_model == 'HEELIS') then if (byimf > 7.) then write(6,"(/'>>> INPUT: byimf too big (must be <= 7.):', | ' byimf=',e12.4)") byimf call shutdown('BYIMF') endif if (byimf < -11.) then write(6,"(/,'>>> INPUT: byimf too small (must be >= -11.):', | ' byimf=',e12.4)") byimf call shutdown('BYIMF') endif endif ! ! Bz component of solar IMF magnetic field: if (bzimf==spval) then write(6,"(/,'>>> INPUT: need 1 value for bzimf', | ' e.g.: BZIMF=0.')") write(6,"('NOTE: multiple (time-dependent) values for BZIMF', | ' not yet supported')") call shutdown('BZIMF') endif ! ! Solar wind velocity: if (swvel==spval) then write(6,"('Input: Will use default swvel = 400 km/s')") swvel = 400. endif ! ! Solar wind density: if (swden==spval) then write(6,"('Input: Will use default swden = 4 #/cm3')") swden = 4. endif ! ! AL, lower auroral magnetic activity index: if (AL==spval) then write(6,"('Input: Will use default AL = -20. ALUSE=FALSE')") AL = -20. ALUSE = .FALSE. else write(6,"('Input: AL given, setting ALUSE=TRUE')") ALUSE = .TRUE. endif ! ! Collision factor: if (colfac==spval) then write(6,"(/,'Input: no value read for colfac. Using default', | ' colfac = 1.5')") colfac = 1.5 endif ! ! iuivi and dynamo flags: ! iuivi is no longer used -- is replaced by dynamo flag: if (iuivi /= ispval) then write(6,"(/,'Input: IUIVI flag is no longer used.')") write(6,"('Please use DYNAMO flag to turn dynamo on or off.')") write(6,"('If DYNAMO=0, then dynamo is NOT called, and ', | 'electric potential and ion drifts will be zero.')") write(6,"('If DYNAMO=1, then dynamo IS called, and ', | 'electric potential and ion drifts are calculated.')") write(6,"('Default is DYNAMO=1')") call shutdown('IUIVI') endif ! ! dynamo = 0 -> no dynamo (dynamo routines are not called, poten==0) ! dynamo = 1 -> run dynamo (equivalent to "new" dynamo of tiegcm1) ! (default dynamo = 1) ! if (dynamo==spval) then dynamo = 1 else if (dynamo <= 0) then write(6,"('Input: dynamo=',i3,' --> dynamo will NOT be ', | 'called.')") dynamo else write(6,"('Input: dynamo=',i3,' --> dynamo will be ', | 'called.')") dynamo endif endif ! ! Set default solomon-garcia data files: ! if (len_trim(solgar_bndry_file)==0) then solgar_bndry_file = '/TGCM/data/solgar_bndry.nc' endif if (len_trim(solgar_import_file)==0) then #if (NLEV==44) ! Import file at zp -17 to +5 by 0.5: solgar_import_file = '/TGCM/data/solgar_import.nc' #elif (NLEV==88) ! Import file at zp -17 to +5 by 0.25: solgar_import_file = '/TGCM/data/solgar_import_dblzp5.nc' #elif (NLEV==96) ! Import file at zp -17 to +7 by 0.25: solgar_import_file = '/TGCM/data/solgar_import_dblz.nc' #endif endif ! ! Zatmos file (see zatmos.F): ! 8/7/09: commented out so zatmos file is opened only if zatmos_ncfile is set ! if (len_trim(zatmos_ncfile)==0) then ! zatmos_ncfile = '/TGCM/data/zatmos_bndry.nc' ! endif ! ! Save certain params as originally read by namelist read: rd_ctpoten = ctpoten rd_power = power rd_f107 = f107 rd_f107a = f107a ! rd_bximf = bximf ! rd_byimf = byimf ! rd_bzimf = bzimf ! rd_swvel = swvel ! rd_swden = swden rd_kp = kp if (rd_kp /= spval) then if (rd_kp < 0..or.rd_kp > 9.0) then write(6,"('>>> INPUT: Bad KP = ',e12.4,' (must be between', | ' 0 and 7)')") rd_kp call shutdown('namelist input KP') endif endif end subroutine inp_model !----------------------------------------------------------------------- subroutine mkntask(ntask,ntask_lat,ntask_lon,ier) integer,intent(in) :: ntask integer,intent(out) :: ntask_lat,ntask_lon,ier integer :: i,j,ntlat(nlonp4),ntlon(nlonp4),nchoice,ngap, | ngap_prev,ii ntask_lat = 0 ntask_lon = 0 nchoice=0 do i=1,nlonp4 do j=1,nlat if (i*j==ntask) then nchoice = nchoice+1 write(6,"('mkntask: i=',i2,' j=',i2,' i*j=',i5,' ntask=', | i5)") i,j,i*j,ntask ntlat(nchoice)=j ntlon(nchoice)=i endif enddo enddo ! ! Choose combinations of ntlat*ntlon==ntask in which ntlon==ntlat, ! or if that does not exist, use combination with smallest delta ! ntlon-ntlat. ! do i=1,nchoice if (ntlon(i) == ntlat(i)) then ntask_lat = ntlat(i) ntask_lon = ntlon(i) endif enddo if (ntask_lat==0.or.ntask_lon==0) then ngap_prev = nlonp4*nlat do i=1,nchoice ngap = ntlon(i)-ntlat(i) if (abs(ngap) < ngap_prev) then ngap = ntlon(i)-ntlat(i) ngap_prev = abs(ngap) ii = i endif enddo ntask_lat = ntlat(ii) ntask_lon = ntlon(ii) ! ! If they are not equal, ntlon should be > ntlat because nlon > nlat. if (ntask_lon < ntask_lat) then i = ntask_lat ntask_lat = ntask_lon ntask_lon = i endif endif ier =0 if (ntask_lat==0.or.ntask_lon==0.or.ntask_lat*ntask_lon /= ntask) | ier = 1 end subroutine mkntask !----------------------------------------------------------------------- subroutine inp_primhist ! ! Validate primary history inputs: ! ! Local: integer :: n,i,ii,nhists,nsteps,nsteps_hist(mxseries), | nstarts,nstops,nstep_total,nsrc,nhist_output1, | nout,nhists_total,modeltime(4),nfiles_prim integer(kind=8) :: step8, | nsec_start(mxseries),nsec_stop(mxseries), | nsec_hist (mxseries),nsec_save(mxseries), | nsec_index,nsec0 character(len=1024) :: ch1024 character(len=1024) :: hvols(mxhvols) ! ! External: integer,external :: numfiles integer(kind=8),external :: mtime_to_nsec ! ! 8-byte integer step: step8 = step ! ! Dispose flag is deprecated: if (dispose==ispval) then dispose = 0 else write(6,"(/,72('-'),/,'>>> WARNING: DISPOSE namelist read', | ' parameter is deprecated.',/,' For dispose to', | ' the NCAR hpss, a csh script named dispose_xxxxx.hsi', | ' will',/,'be written to the exec directory, and will', | ' contain necessary hsi commands',/,'to dispose history', | ' files to the hpss.',/,72('-'))") if (dispose > 0) | call shutdown('namelist DISPOSE is deprecated') dispose = 0 endif ! ! Model start time(s): n = size(start)-count(start==ispval) if (mod(n,3) /= 0) then write(6,"(/,'>>> INPUT: START must be given as series of ', | '3-integer triplet times',/,11x,'(day,hr,min).',/)") call shutdown('START') endif nstarts = n/3 ! number of start times given if (nstarts < 1 .or. nstarts > mxseries) then write(6,"(/,'>>> INPUT: At least one and a maximum of ',i3, | ' 3-integer START times are allowed.',/)") mxseries call shutdown('START') endif do i=1,nstarts call validate_mtime(start(:,i),mxday,'START') enddo ! ! Start time(s) must be multiple of step, and must increase: nsec_start(:) = 0 do i=1,nstarts nsec_start(i) = mtime_to_nsec(start(:,i)) if (mod(nsec_start(i),step8) /= 0) then write(6,"(/,'>>> INPUT: START time ',i1,' must be a ', | 'multiple of step:',/,11x,'START=',3i4,' STEP=',i4,/)") | i,start(:,i),step call shutdown('START') endif if (i > 1) then if (nsec_start(i-1) > nsec_start(i)) then write(6,"(/,'>>> INPUT: START times must increase.',/, | 11x,'START ',i2,' = ',3i4,' START ',i2,' = ',3i4, | /)") i-1,start(:,i-1),i,start(:,i) call shutdown('START') endif endif enddo ! ! If advancing in calendar time (calday > 0), then the starting model ! day must be the same as the starting calendar day (calday): ! ! if (calday /= 0) then if (calendar_advance > 0) then if (start(1,1) /= start_day) then write(6,"(/,'>>> INPUT: Starting calendar day START_DAY =', | i4)") start_day write(6,"(11x,'Starting model day START(1)=',i4)") | start(1,1) write(6,"(11x,'CALENDAR_ADVANCE = ',i2)") calendar_advance write(6,"('If the model is to be advanced in calendar time,', | ' the starting model day',/,' must be equal to the ', | 'starting calendar day.',/)") call shutdown('START') endif endif ! ! Stop time(s): n = size(stop)-count(stop==ispval) if (mod(n,3) /= 0) then write(6,"(/,'>>> INPUT: STOP must be given as series of ', | '3-integer triplet times (day,hr,min).',/)") call shutdown('STOP') endif nstops = n/3 ! number of stop times given if (nstops < 1 .or. nstops > mxseries) then write(6,"(/,'>>> INPUT: At least one and a maximum of ',i2, | ' 3-integer STOP times are allowed.',/)") mxseries call shutdown('STOP') endif do i=1,nstops call validate_mtime(stop(:,i),mxday,'STOP') enddo ! ! Stop time(s) must be multiple of step, and must increase: nsec_stop(:) = 0 do i=1,nstops nsec_stop(i) = mtime_to_nsec(stop(:,i)) if (mod(nsec_stop(i),step8) /= 0) then write(6,"(/,'>>> INPUT: STOP time ',i1,' must be a ', | 'multiple of step:',/,11x,'STOP=',3i4,' STEP=',i4,/)") | i,stop(:,i),step call shutdown('STOP') endif if (i > 1) then if (nsec_stop(i-1) > nsec_stop(i)) then write(6,"(/,'>>> INPUT: STOP times must increase.',/, | 11x,'STOP 1 =',3i4,' STOP 2 =',3i4,/)") stop call shutdown('STOP') endif endif enddo ! ! Stop time(s) must be > start times: ! Note: this module does not cross year boundaries in a single run. ! To cross a year boundary, make a run up to day 365 or 366, ! then use that file as the source (source_start=365 or 366), ! for a new run with START=1,0,0. (note mxday==366) ! if (nsec_start(1)==nsec_stop(1)) then write(6,"(/,'NOTE input: start(1)==stop(1): no time steps', | ' will be taken this run.')") else do i=1,nstops if (nsec_start(i) >= nsec_stop(i)) then write(6,"(/,'>>> INPUT: STOP time ',i1,' must be > ', | 'START time',/,11x,'STOP time ',i1,' = ',3i4, | ' START =',3i4,/)") i,i,stop(:,i),start(:,i) call shutdown('START/STOP') endif enddo endif ! ! History write frequencies: n = size(hist)-count(hist==ispval) if (mod(n,3) /= 0) then write(6,"(/,'>>> INPUT: HIST must be given as series of ', | '3-integer triplet times (day,hr,min).',/)") call shutdown('HIST') endif nhists = n/3 ! number of hist times given if (nhists < 1 .or. nhists > mxseries) then write(6,"(/,'>>> INPUT: At least one and a maximum of ',i2, | ' 3-integer HIST times are allowed.',/)") mxseries call shutdown('HIST') endif do i=1,nhists call validate_mtime(hist(:,i),mxday,'HIST') enddo ! ! History write frequencies must be multiple of step: nsec_hist(:) = 0 do i=1,nhists nsec_hist(i) = mtime_to_nsec(hist(:,i)) if (nsec_hist(i)==0) then write(6,"(/,'>>> INPUT: HIST write frequency ',i1, | ' must be > 0',/)") i call shutdown('HIST') endif if (mod(nsec_hist(i),step8) /= 0) then write(6,"(/,'>>> INPUT: HIST time ',i1,' must be a ', | 'multiple of step:',/,11x,'HIST=',3i4,' STEP=',i4,/)") | i,hist(:,i),step call shutdown('HIST') endif enddo ! ! History save frequencies SAVE is deprecated: n = size(save)-count(save==ispval) if (n > 0) then write(6,"(/,'>>> Input parameter SAVE has been deprecated.')") write(6,"(' Please remove it from the namelist input file')") ! call shutdown('namelist SAVE is deprecated') endif ! ! Must have same number of time sequences: if (nstarts /= nstops .or. nstarts /= nhists .or. | nstops /= nhists) then write(6,"(/,'>>> INPUT: must provide same number of times ', | 'for',/,11x,'START, STOP, and HIST.')") write(6,"(11x,'nstarts=',i3,' nstops=',i3,' nhists=',i3)") | nstarts,nstops,nhists call shutdown('ntimes') endif ! ! Number of steps in each time series must be a multiple of HIST ! and SAVE frequencies for that series: do i=1,nstarts if (i==1) then nsteps = (nsec_stop(i)-nsec_start(i))/step else nsteps = (nsec_stop(i)-nsec_stop(1))/step endif nsteps_hist(i) = nsec_hist(i)/step if (mod(nsteps,nsteps_hist(i)) /= 0) then write(6,"(/,'>>> INPUT: number of steps in time series ', | i1,' must be multiple of the ',/,11x,'number of steps', | ' in HIST ',i1,'.')") i,i write(6,"(11x,'nsteps ',i1,' = ',i6,' nsteps_hist ',i1, | ' = ',i3)") i,nsteps,i,nsteps_hist(i) write(6,"(11x,'START',i1,' = ',3i4,' STOP',i1,' = ',3i4, | ' HIST',i1,' = ',3i4,/)") i,start(:,i),i,stop(:,i), | i,hist(:,i) call shutdown('HIST') endif enddo ! ! Time series cannot overlap (However, they can touch, front-to-back): if (nstarts > 1) then do i=2,nstarts if (nsec_start(i) < nsec_stop(i-1)) then write(6,"(/,'>>> INPUT: primary history time series', | ' cannot overlap.')") write(6,"(11x,'For series ',i2,': START=',3i4, | ' STOP=',3i4)") i-1,start(:,i-1),start(:,i-1) write(6,"(11x,'For series ',i2,': START=',3i4, | ' STOP=',3i4,/)") i,start(:,i),stop(:,i) call shutdown('START/STOP') endif enddo endif ! ! Total steps this run (nstep is in hist_module.F) nstep_total = (nsec_stop(nstarts)-nsec_start(1))/step8 ! ! Source history file (optional): nsrc = len_trim(source) ! ! Source start time (must be given if SOURCE file was provided): n = size(source_start)-count(source_start==ispval) if (nsrc > 0 .and. n <= 0) then write(6,"(/,'>>> INPUT: If SOURCE is provided, must also', | ' provide SOURCE_START time.',/,11x,'SOURCE=',a,/)") | trim(source) call shutdown('SOURCE_START') endif if (nsrc > 0) then if (n /= 3) then write(6,"(/,'>>> INPUT: need 3 values for SOURCE_START ', | 'time (day,hour,minute),',/,11x, | 'e.g.: SOURCE_START=1,0,0',/)") call shutdown('START') endif call validate_mtime(source_start,mxday,'SOURCE_START') ! ! Model start time hr,min must be same as source_start hr,min: ! (days can be different) if (start(2,1) /= source_start(2) .or. | start(3,1) /= source_start(3)) then write(6,"(/,'>>> INPUT: START time (hr,min) ', | 'must be the same as SOURCE_START time.')") write(6,"(' START = ',3i4)") start(:,1) write(6,"(' SOURCE_START = ',3i4)") source_start(:) write(6,"(' (START and SOURCE_START days can be ', | 'different)',/)") call shutdown('START') endif endif ! ! Validate that times given by ctpoten_time and/or power_time are ! within start and stop times (the times themselves were validated ! in inp_model). Note user must provide a value for each start time. ! if (ntimes_ctpoten > 0) then nsec0 = mtime_to_nsec(int(ctpoten_time(1:3,1))) if (nsec0 /= nsec_start(1)) then write(6,"(/,'>>> INPUT: Please provide first CTPOTEN_TIME', | ' time equal to first START time.')") call shutdown('starting ctpoten_time') endif do i=1,ntimes_ctpoten nsec_index = mtime_to_nsec(int(ctpoten_time(1:3,i))) if (nsec_index < nsec_start(1) .or. | nsec_index > nsec_stop(1)) then write(6,"(/,'>>> INPUT: CTPOTEN_TIME ',3i4,' is outside ', | 'model START/STOP times: START=',3i4,' STOP=',3i4)") | int(ctpoten_time(1:3,i)),start(:,1),stop(:,1) call shutdown('ctpoten_time') endif enddo ctpoten = ctpoten_time(4,1) endif ! ntimes_ctpoten ! if (ntimes_power > 0) then nsec0 = mtime_to_nsec(int(power_time(1:3,1))) if (nsec0 /= nsec_start(1)) then write(6,"(/,'>>> INPUT: Please provide first POWER_TIME', | ' time equal to first START time.')") call shutdown('starting power_time') endif do i=1,ntimes_power nsec_index = mtime_to_nsec(int(power_time(1:3,i))) if (nsec_index < nsec_start(1) .or. | nsec_index > nsec_stop(1)) then write(6,"(/,'>>> INPUT: POWER_TIME ',3i4,' is outside ', | 'model START/STOP times: START=',3i4,' STOP=',3i4)") | int(power_time(1:3,i)),start(:,1),stop(:,1) call shutdown('power_time') endif enddo power = power_time(4,1) endif ! ntimes_power ! if (ntimes_f107 > 0) then nsec0 = mtime_to_nsec(int(f107_time(1:3,1))) if (nsec0 /= nsec_start(1)) then write(6,"(/,'>>> INPUT: Please provide first F107_TIME', | ' time equal to first START time.')") call shutdown('starting f107_time') endif do i=1,ntimes_f107 nsec_index = mtime_to_nsec(int(f107_time(1:3,i))) if (nsec_index < nsec_start(1) .or. | nsec_index > nsec_stop(1)) then write(6,"(/,'>>> INPUT: F107_TIME ',3i4,' is outside ', | 'model START/STOP times: START=',3i4,' STOP=',3i4)") | int(f107_time(1:3,i)),start(:,1),stop(:,1) call shutdown('f107_time') endif enddo f107 = f107_time(4,1) endif ! ntimes_f107 ! if (ntimes_f107a > 0) then nsec0 = mtime_to_nsec(int(f107a_time(1:3,1))) if (nsec0 /= nsec_start(1)) then write(6,"(/,'>>> INPUT: Please provide first F107A_TIME', | ' time equal to first START time.')") call shutdown('starting f107a_time') endif do i=1,ntimes_f107a nsec_index = mtime_to_nsec(int(f107a_time(1:3,i))) if (nsec_index < nsec_start(1) .or. | nsec_index > nsec_stop(1)) then write(6,"(/,'>>> INPUT: F107A_TIME ',3i4,' is outside ', | 'model START/STOP times: START=',3i4,' STOP=',3i4)") | int(f107a_time(1:3,i)),start(:,1),stop(:,1) call shutdown('f107a_time') endif enddo f107a = f107a_time(4,1) endif ! ntimes_f107a ! if (ntimes_kp > 0) then nsec0 = mtime_to_nsec(int(kp_time(1:3,1))) if (nsec0 /= nsec_start(1)) then write(6,"(/,'>>> INPUT: Please provide first F107A_TIME', | ' time equal to first START time.')") call shutdown('starting kp_time') endif do i=1,ntimes_kp nsec_index = mtime_to_nsec(int(kp_time(1:3,i))) if (nsec_index < nsec_start(1) .or. | nsec_index > nsec_stop(1)) then write(6,"(/,'>>> INPUT: F107A_TIME ',3i4,' is outside ', | 'model START/STOP times: START=',3i4,' STOP=',3i4)") | int(kp_time(1:3,i)),start(:,1),stop(:,1) call shutdown('kp_time') endif enddo kp = kp_time(4,1) endif ! ntimes_kp ! ! Primary output volumes: ! (integer function mkhvols either echoes histvols to hvols, or if ! histvols(2)=='to',then it expands histvols from 'volfirst','to', ! 'vollast','by','n' to hvols) ! hvols = ' ' nout = mkhvols(output,hvols,mxhvols) if (nout==0) then write(6,"(/,'>>> INPUT: need at least one output volume',/)") call shutdown('OUTPUT') endif output = hvols ! ! Max number of histories per primary file: ! (mxhist_prim is an input parameter with default = 13). if (mxhist_prim < 0) then write(6,"('>>> INPUT: maximum number of histories per ', | 'primary file must be > 0: mxhist_prim=',i4)") mxhist_prim call shutdown('MXHIST_PRIM') endif ! ! No dups of file names allowed: ch1024 = ' ' do i=1,nout ch1024 = output(i) output(i) = 'dummy' if (any(output==ch1024)) then write(6,"(/,'>>> INPUT: Duplicate OUTPUT file names = ', | a,/)") trim(ch1024) call shutdown('OUTPUT') endif output(i) = ch1024 enddo ! ! Check that sufficient primary output files have been provided: ! Func numfiles returns number of files that will be needed, and ! also returns total histories to be written: ! nfiles_prim = numfiles('prim',nstarts,nsrc,0,nhists_total) if (nout < nfiles_prim) then write(6,"(/,'>>> INPUT: Will need ',i3,' OUTPUT files, but', | ' read only ',i3)") nfiles_prim,nout write(6,"(11x,'Total number of steps this run = ',i6)") | nstep_total write(6,"(11x,'Total number of primary histories this run = ', | i5)") nhists_total write(6,"(11x,'Maximum number of primary histories per file = ', | i3,/)") mxhist_prim call shutdown('OUTPUT') endif end subroutine inp_primhist !------------------------------------------------------------------- subroutine inp_sechist ! ! Validate secondary history inputs: ! ! Local: integer :: n,i,nstarts,nstops,nhists,nout,nsteps, | nsteps_hist(mxseries_sech),nsechs_total,nseriesp, | nflds_sech,nhists_total,nfiles_sech,nonblank integer(kind=8) :: step8, | nsec_start(mxseries_sech),nsec_stop(mxseries_sech), | nsec_hist (mxseries_sech) character(len=1024) :: ch1024 character(len=1024) :: hvols(mxhvols) character(len=16) :: | secflds_tmp(mxfsech) ! ! External: integer,external :: numfiles integer(kind=8),external :: mtime_to_nsec ! ! 8-byte integer step: step8 = step ! ! n = total number of secondary history inputs read: n = size(secstart)-count(secstart==ispval) + | size(secstop) -count(secstop==ispval) + | size(sechist) -count(sechist==ispval) + | size(secflds) -count(len_trim(secflds)==0) + | size(secfmag) -count(len_trim(secfmag)==0) + | size(secfgeo2d) -count(len_trim(secfgeo2d)==0)+ | size(secfmag2d) -count(len_trim(secfmag2d)==0)+ | size(secfmagphr)-count(len_trim(secfmagphr)==0) ! ! Secondary output volumes: ! (integer function mkhvols either echoes histvols to hvols, or if ! histvols(2)=='to',then it expands histvols from 'volfirst','to', ! 'vollast','by','n' to hvols) ! hvols = ' ' nout = mkhvols(secout,hvols,mxhvols) if (nout==0.and.n > 0) then write(6,"(/,'>>> INPUT: need at least one secondary ', | 'history output volume',/)") call shutdown('SECOUT') endif secout = hvols n = n+nout if (n <= 0) return ! ! Secondary history start time(s): n = size(secstart)-count(secstart==ispval) if (mod(n,3) /= 0) then write(6,"(/,'>>> INPUT: SECSTART must be given as series of ', | '3-integer triplet times',/,11x,'(day,hr,min).',/,11x, | 'A maximum of ',i3,' secstart times are allowed.',/)") | mxseries_sech call shutdown('SECSTART') endif nstarts = n/3 ! number of start times given if (nstarts < 1 .or. nstarts > mxseries_sech) then write(6,"(/,'>>> INPUT: At least one and a maximum of ',i3, | ' 3-integer SECSTART times are allowed.',/)") mxseries_sech call shutdown('SECSTART') endif do i=1,nstarts call validate_mtime(secstart(:,i),mxday,'SECSTART') enddo ! ! Secondary start time(s) must be multiple of step, and must increase: nsec_start(:) = 0 do i=1,nstarts nsec_start(i) = mtime_to_nsec(secstart(:,i)) if (mod(nsec_start(i),step8) /= 0) then write(6,"(/,'>>> INPUT: SECSTART time ',i1,' must be a ', | 'multiple of step:',/,11x,'SECSTART=',3i4,' STEP=',i4,/)") | i,secstart(:,i),step call shutdown('SECSTART') endif if (i > 1) then if (nsec_start(i-1) > nsec_start(i)) then write(6,"(/,'>>> INPUT: SECSTART times must increase.',/, | 11x,'SECSTART ',i2,' = ',3i4,' SECSTART ',i2,' = ',3i4, | /)") i-1,secstart(:,i-1),i,secstart(:,i) call shutdown('SECSTART') endif endif enddo ! ! Secondary start times must be >= first primary start times and ! <= last primary stop time: nseriesp = (size(start)-count(start==ispval))/3 do i=1,nstarts if (nsec_start(i) < mtime_to_nsec(start(:,1))) then write(6,"(/,'>>> INPUT: all secondary start times SECSTART', | ' must be >= first model START time.')") write(6,"(11x,'First model START = ',3i4,' SECSTART ',i2, | ' = ',3i4,/)") start(:,1),i,secstart(:,i) call shutdown('SECSTART') endif if (nsec_start(i) > mtime_to_nsec(stop(:,nseriesp))) then write(6,"(/,'>>> INPUT: all secondary start times SECSTART', | ' must be <= last model STOP time.')") write(6,"(11x,' SECSTART ',i2,' = ',3i4,' last STOP=', | 3i4)") secstart(:,1),i,stop(:,nseriesp) call shutdown('SECSTART') endif enddo ! ! Secondary history stop time(s): n = size(secstop)-count(secstop==ispval) if (mod(n,3) /= 0) then write(6,"(/,'>>> INPUT: SECSTOP must be given as series of ', | '3-integer triplet times',/,11x,'(day,hr,min).',/,11x, | 'A maximum of ',i3,' secstop times are allowed.',/)") | mxseries_sech call shutdown('SECSTOP') endif nstops = n/3 ! number of stop times given if (nstops < 1 .or. nstops > mxseries_sech) then write(6,"(/,'>>> INPUT: At least one and a maximum of ',i3, | ' 3-integer SECSTOP times are allowed.',/)") mxseries_sech call shutdown('SECSTOP') endif do i=1,nstops call validate_mtime(secstop(:,i),mxday,'SECSTOP') enddo ! ! Stop time(s) must be multiple of step, and must increase: nsec_stop(:) = 0 do i=1,nstops nsec_stop(i) = mtime_to_nsec(secstop(:,i)) if (mod(nsec_stop(i),step8) /= 0) then write(6,"(/,'>>> INPUT: SECSTOP time ',i1,' must be a ', | 'multiple of step:',/,11x,'SECSTOP=',3i4,' STEP=',i4,/)") | i,secstop(:,i),step call shutdown('SECSTOP') endif if (i > 1) then if (nsec_stop(i-1) > nsec_stop(i)) then write(6,"(/,'>>> INPUT: SECSTOP times must increase.',/, | 11x,'SECSTOP ',i2,' = ',3i4,' SECSTOP ',i2,' = ',3i4, | /)") i-1,secstop(:,i-1),i,secstop(:,i) call shutdown('SECSTOP') endif endif enddo ! ! Secondary stop times must be > secondary start times: do i=1,nstops if (nsec_stop(i) <= nsec_start(i)) then write(6,"(/,'>>> INPUT: SECSTART must be < SECSTOP for ', | 'all time series.')") write(6,"('For time series ',i2,': SECSTART=',3i4,' SECSTOP=', | 3i4,/)") i,secstart(:,i),secstop(:,i) call shutdown('SECSTART/SECSTOP') endif enddo ! ! Secondary stop times must be <= last primary stop time: nstarts = n/3 ! number of start times given do i=1,nstarts if (nsec_stop(i) > mtime_to_nsec(stop(:,nseriesp))) then write(6,"(/,'>>> INPUT: all secondary stop times must be', | ' <= final model stop time.')") write(6,"('For sech time series ',i2,': SECSTOP=',3i4, | ' Model STOP = ',3i4,/)") i,secstop(:,i),stop(:,nseriesp) call shutdown('SECSTOP') endif enddo ! ! Secondary history write frequencies: n = size(sechist)-count(sechist==ispval) if (mod(n,3) /= 0) then write(6,"(/,'>>> INPUT: SECHIST must be given as series of ', | '3-integer triplet times (day,hr,min).',/,11x,'A maximum', | ' of ',i3,' SECHIST times are allowed.',/)") mxseries_sech call shutdown('SECHIST') endif nhists = n/3 ! number of hist times given if (nhists < 1 .or. nhists > mxseries_sech) then write(6,"(/,'>>> INPUT: At least one and a maximum of ',i3, | ' 3-integer SECHIST times are allowed.',/)") call shutdown('SECHIST') endif do i=1,nhists call validate_mtime(sechist(:,i),mxday,'SECHIST') enddo ! ! Secondary history write frequencies must be multiples of step: nsec_hist(:) = 0 do i=1,nhists nsec_hist(i) = mtime_to_nsec(sechist(:,i)) if (nsec_hist(i)==0) then write(6,"(/,'>>> INPUT: SECHIST write frequency ',i1, | ' must be > 0',/)") i call shutdown('SECHIST') endif if (mod(nsec_hist(i),step8) /= 0) then write(6,"(/,'>>> INPUT: SECHIST time ',i1,' must be a ', | 'multiple of step:',/,11x,'SECHIST=',3i4,' STEP=',i4,/)") | i,sechist(:,i),step call shutdown('SECHIST') endif enddo ! ! Secondary history save frequencies: n = size(secsave)-count(secsave==ispval) if (n > 0) then write(6,"(/,'>>> Input parameter SECSAVE has been', | ' deprecated.')") write(6,"(' Please remove it from the namelist input file')") ! call shutdown('namelist SECSAVE is deprecated') endif ! ! Must have same number of time sequences: if (nstarts /= nstops .or. nstarts /= nhists .or. | nstops /= nhists) then write(6,"(/,'>>> INPUT: must provide same number of times ', | 'for',/,11x,'SECSTART, SECSTOP, and SECHIST.')") write(6,"(11x,'nstarts=',i3,' nstops=',i3,' nhists=',i3)") | nstarts,nstops,nhists call shutdown('nsechtimes') endif ! nseries_sech = nstarts ! ! Number of steps in each time series must be a multiple of SECHIST ! and SECSAVE frequencies for that series: do i=1,nstarts nsteps = (nsec_stop(i)-nsec_start(i))/step nsteps_hist(i) = nsec_hist(i)/step if (mod(nsteps,nsteps_hist(i)) /= 0) then write(6,"(/,'>>> INPUT: number of steps in time series ', | i1,' must be multiple of the ',/,11x,'number of steps', | ' in SECHIST ',i1,'.')") i,i write(6,"(11x,'nsteps ',i1,' = ',i6,' nsteps_hist ',i1, | ' = ',i3)") i,nsteps,i,nsteps_hist(i) write(6,"(11x,'Time series ',i2,': SECSTART = ',3i4, | ' SECSTOP = ',3i4,' SECHIST = ',3i4,/)") i,secstart(:,i), | secstop(:,i),sechist(:,i) call shutdown('SECHIST') endif enddo ! ! Time series cannot overlap (However, they can touch, front-to-back): if (nstarts > 1) then do i=2,nstarts if (nsec_start(i) < nsec_stop(i-1)) then write(6,"(/,'>>> INPUT: secondary history time series', | ' cannot overlap.')") write(6,"(11x,'For series ',i2,': SECSTART=',3i4, | ' SECSTOP=',3i4)") i-1,secstart(:,i-1),secstop(:,i-1) write(6,"(11x,'For series ',i2,': SECSTART=',3i4, | ' SECSTOP=',3i4,/)") i,secstart(:,i),secstop(:,i) call shutdown('SECSTART/SECSTOP') endif enddo endif ! ! Max number of histories per secondary file (optional input): if (mxhist_sech < 0) then write(6,"('>>> INPUT: maximum number of histories per ', | 'secondary file must be > 0: mxhist_sech=',i4)") mxhist_sech call shutdown('MXHIST_SECH') endif ! ! No dups of secout file names allowed: ch1024 = ' ' do i=1,nout ch1024 = secout(i) secout(i) = 'dummy' if (any(secout==ch1024)) then write(6,"(/,'>>> INPUT: Duplicate SECOUT file names = ', | a,/)") trim(ch1024) call shutdown('SECOUT') endif secout(i) = ch1024 enddo ! ! Check that sufficient secondary output files have been provided: ! Func numfiles returns number of files that will be needed, and ! also returns total histories to be written: ! nfiles_sech = numfiles('sech',nstarts,1,0,nhists_total) if (nout < nfiles_sech) then write(6,"(/,'>>> INPUT: Will need ',i3,' SECOUT files, but', | ' read only ',i3)") nfiles_sech,nout write(6,"(11x,'Total number of secondary histories this ', | 'run = ',i5)") nhists_total write(6,"(11x,'Maximum number of secondary histories per ', | 'file = ',i3,/)") mxhist_sech call shutdown('SECOUT') endif ! ! Pack names so no blank names occur from 1->nflds_sech nflds_sech = count(len_trim(secflds) > 0) call packstr(secflds,mxfsech,nonblank) if (nonblank /= nflds_sech) then write(6,"('>>> WARNING: Input after packstr(secflds): ', | 'nonblank /= nflds_sech: nonblank=',i3,' nflds_sech=',i3)") | nonblank,nflds_sech write(6,"('secflds(mxfsech=',i3,')=')") mxfsech do i=1,mxfsech write(6,"('secflds(',i2,')=',a)") i,secflds(i) enddo endif ! ! Secondary history fields: ! Fields that are forced on the secondary histories are listed ! in string array secflds_mandatory(). ! If user does not provide secflds fields, these mandatory fields ! are written by default. Any mandatory fields NOT listed by ! the user are added to the end of the user's list. ! if (nflds_sech==0) then write(6,"(/,'INPUT NOTE: no secondary history fields were ', | 'requested (SECFLDS).')") write(6,"('I will write the default minimum set of ', | 'fields to secondary histories:')") write(6,"(4a12)") secflds_mandatory do i=1,size(secflds_mandatory) secflds(i) = secflds_mandatory(i) enddo else ! nflds_sech > 0: enforce mandatory fields do i=1,size(secflds_mandatory) if (.not.any(secflds==secflds_mandatory(i))) then nflds_sech = nflds_sech+1 secflds(nflds_sech) = secflds_mandatory(i) write(6,"('INPUT NOTE: adding mandatory field ', | a,' to secondary history fields (field ',i3,')')") | secflds(nflds_sech)(1:8),nflds_sech endif enddo endif ! Check for dups of secflds field names: ch1024 = ' ' do i=1,nflds_sech ch1024 = secflds(i) secflds(i) = 'dummy' if (any(secflds==ch1024)) then write(6,"(/,'>>> INPUT: Duplicate SECFLDS field names = ', | a,/)") trim(ch1024) call shutdown('SECFLDS') endif secflds(i) = ch1024 enddo ! ! Number of bytes for values of 4d fields on secondary histories: ! Must be either 4 (reals) or 8 (doubles). Default is 4, i.e., ! write 4-byte reals to secondary histories. ! if (sech_nbyte == ispval) then sech_nbyte = 4 elseif (sech_nbyte /= 4 .and. sech_nbyte /= 8) then write(6,"('>>> INPUT: sech_nbyte=',i4,' but must be either ', | '4 (write real to sech) or 8 (write double to sech)')") call shutdown('sech_nbyte') endif end subroutine inp_sechist !----------------------------------------------------------------------- subroutine inp_print(ntask) ! ! Print values of inp (input_type): ! ! Args: integer,intent(in) :: ntask ! Local: integer :: i,n ! write(6,"(/,72('-'))") write(6,"('USER INPUT PARAMETERS:')") ! ! Model-wide: if (len_trim(label) > 0) | write(6,"(' label = ',a,/,4x,'(optional text label for', | ' current run)')") trim(label) if (len_trim(tempdir) > 0) | write(6,"(' tempdir = ',a,' (runtime temporary directory)')") | trim(tempdir) if (len_trim(potential_model) > 0) | write(6,"(' high-lat electric potential model: ', | 'potential_model = ',a)") trim(potential_model) if (len_trim(hrindices_ncfile) > 0) | write(6,"(' hrly indices: hrindices_ncfile = ',a)") | trim(hrindices_ncfile) if (len_trim(weimer_ncfile) > 0) | write(6,"(' weimer coefs: weimer_ncfile = ',a)") | trim(weimer_ncfile) if (len_trim(gpi_ncfile) > 0) | write(6,"(' gpi run: gpi_ncfile = ',a)") trim(gpi_ncfile) if (len_trim(ncep_ncfile) > 0) | write(6,"(' ncep run: ncep_ncfile = ',a)") trim(ncep_ncfile) if (len_trim(ncep_reanalysis) > 0) | write(6,"(' ncep run: ncep_reanalysis = ',a)") | trim(ncep_reanalysis) if (len_trim(gswm_mi_di_ncfile) > 0) | write(6,"(' gswm migrating diurnal file: ', | 'gswm_mi_di_ncfile = ',a)") trim(gswm_mi_di_ncfile) if (len_trim(gswm_mi_sdi_ncfile) > 0) | write(6,"(' gswm migrating semi-diurnal file: ', | 'gswm_mi_sdi_ncfile = ',a)") trim(gswm_mi_sdi_ncfile) if (len_trim(gswm_nm_di_ncfile) > 0) | write(6,"(' gswm non-migrating diurnal file: ', | 'gswm_nm_di_ncfile = ',a)") trim(gswm_nm_di_ncfile) if (len_trim(gswm_nm_sdi_ncfile) > 0) | write(6,"(' gswm non-migrating semi-diurnal file: ', | 'gswm_nm_sdi_ncfile = ',a)") trim(gswm_nm_sdi_ncfile) if (len_trim(solgar_bndry_file) > 0) | write(6,"(' Solgar bndry data: ', | 'solgar_bndry_file = ',a)") trim(solgar_bndry_file) if (len_trim(solgar_import_file) > 0) | write(6,"(' Solgar import data: ', | 'solgar_import_file = ',a)") trim(solgar_import_file) if (len_trim(zatmos_ncfile) > 0) | write(6,"(' Zatmos data: ', | 'zatmos_ncfile = ',a)") trim(zatmos_ncfile) if (wacxg5_nfiles > 0) then do i=1,wacxg5_nfiles write(6,"('wacxg5_ncfiles(',i3,') = ',a)") | i,trim(wacxg5_ncfiles(i)) enddo endif if (len_trim(meped_file) > 0) | write(6,"(' MEPED data: ', | 'meped_file = ',a)") trim(meped_file) if (len_trim(amievol) > 0) | write(6,"(' amievol = ',a,/,4x, | '(file or mss path containing amie data)')") trim(amievol) if (len_trim(hpss_path) > 0) | write(6,"(' hpss_path = ',a,4x, | '(hpss directory for hsi dispose script)')") trim(hpss_path) write(6,"(' start_year = ',i4,' (starting calendar day)')") | start_year write(6,"(' start_day = ',i4,' (starting calendar year)')") | start_day if (calendar_advance /= 0) then write(6,"(' calendar_advance =',i2,' (model will be advanced ', | 'in calendar time starting on this day)')") | calendar_advance else write(6,"(' calendar_advance =',i1,' (model will NOT be ', | 'advanced in calendar time)')") calendar_advance endif write(6,"(' step =',i4,' (model timestep (seconds))', | i4)") step #ifdef MPI write(6,"(' ntask_lon = ',i2,' (number of mpi tasks in ', | 'longitude dimension.')") ntask_lon write(6,"(' ntask_lat = ',i2,' (number of mpi tasks in ', | 'latitude dimension.')") ntask_lat write(6,"(' total tasks = ntask_lon*ntask_lat = ',i4)") | ntask #endif ! ! Primary histories: if (len_trim(source) > 0) then write(6,"(' source = ',a,/,4x,'(file or mss path', | ' containing source history)')") trim(source) write(6,"(' source_start = ',(i3,',',i2,',',i2), | ' (model time of source history)')") | source_start endif n = size(output)-count(output==' ') write(6,"(' output (primary history output files) = ', | /,(4x,a,', ',a))") | (trim(output(i)),i=1,n) n = (size(start)-count(start==ispval))/3 write(6,"(' start (model start times) =', | /,4(4x,i3,',',i2,',',i2))") (start(:,i),i=1,n) n = (size(stop)-count(stop==ispval))/3 write(6,"(' stop (model stop times) =', | /,4(4x,i3,',',i2,',',i2))") (stop(:,i),i=1,n) n = (size(hist)-count(hist==ispval))/3 write(6,"(' hist (primary history disk write frequencies) =', | /,4(4x,i3,',',i2,',',i2))") (hist(:,i),i=1,n) n = (size(save)-count(save==ispval))/3 write(6,"(' save (primary history file save frequencies) =', | /,4(4x,i3,',',i2,',',i2))") (save(:,i),i=1,n) write(6,"(' Maxmimum number of histories per primary file = ', | i3)") mxhist_prim ! ! Secondary histories: if (len_trim(secsource) > 0) then write(6,"(' secsource = ',a,/,4x,'(file or mss path', | ' containing secsource history)')") trim(secsource) write(6,"(' secsource_start = ',(i3,',',i2,',',i2), | ' (model time of secsource history)')") | source_start endif n = size(secout)-count(secout==' ') if (n > 0) | write(6,"(' secout (secondary history output files)=', | /,(4x,a,', ',a))") | (trim(secout(i)),i=1,n) n = (size(secstart)-count(secstart==ispval))/3 if (n > 0) | write(6,"(' secstart (secondary history start times) =', | /,4(4x,i3,',',i2,',',i2))") (secstart(:,i),i=1,n) n = (size(secstop)-count(secstop==ispval))/3 if (n > 0) | write(6,"(' secstop (secondary history stop times) =', | /,4(4x,i3,',',i2,',',i2))") (secstop(:,i),i=1,n) n = (size(sechist)-count(sechist==ispval))/3 if (n > 0) | write(6,"(' sechist (secondary history disk write', | ' frequencies) =',/,4(4x,i3,',',i2,',',i2))") | (sechist(:,i),i=1,n) n = (size(secsave)-count(secsave==ispval))/3 if (n > 0) | write(6,"(' secsave (secondary history file save', | ' frequencies) =',/,4(4x,i3,',',i2,',',i2))") | (secsave(:,i),i=1,n) n = (size(secflds)-count(len_trim(secflds)==0)) if (n > 0) | write(6,"(' secflds (secondary history fields)', | ' =',/,(4x,5a12))") (secflds(i),i=1,n) n = (size(secfmag)-count(len_trim(secfmag)==0)) if (n > 0) | write(6,"(' secfmag (secondary history fields on magnetic ', | 'grid) =',/,(4x,5a12))") (secfmag(i),i=1,n) n = (size(secfgeo2d)-count(len_trim(secfgeo2d)==0)) if (n > 0) | write(6,"(' secfgeo2d (secondary history fields on geo. ', | '2d grid) =',/,(4x,5a12))") (secfgeo2d(i),i=1,n) n = (size(secfmag2d)-count(len_trim(secfmag2d)==0)) if (n > 0) | write(6,"(' secfmag2d (secondary history fields on magnetic ', | '2d grid) =',/,(4x,5a12))") (secfmag2d(i),i=1,n) n = (size(secfmagphr)-count(len_trim(secfmagphr)==0)) if (n > 0) | write(6,"('secfmagphr (secondary history fields on magnetphr', | 'grid) =',/,(4x,5a12))") (secfmagphr(i),i=1,n) write(6,"(' Maximum number of histories per secondary file = ', | i3)") mxhist_sech write(6,"(' Number of bytes for values of fields on secondary', | ' histories (sech_nbyte) = ',i3)") sech_nbyte ! ! More model-wide inputs: write(6,"(' difhor = ',i6,' (horizontal eddy diffusion flag)')") | difhor ! ! iuivi flag is replaced by dynamo flag: ! write(6,"(' iuivi = ',i2,' (ion drifts momentum flag)')") ! | iuivi if (dynamo <= 0) then write(6,"(' dynamo = ',i2,' (dynamo will NOT be calculated)')") | dynamo write(6,"(14x, | '(electric potential and ion drifts will be zero')") else write(6,"(' dynamo = ',i2,' (dynamo will be calculated)')") | dynamo endif write(6,"(' tide (amplitudes and phases of semidiurnal tide) =', | /,4x,5e8.1,5f6.2)") tide write(6,"(' tide2 (amplitude and phase of diurnal tide) =', | /,4x,e8.1,f6.2)") tide2 write(6,"(' tide3m3 (amplitude and phase of 2-day wave)=', | /,4x,e8.1,f6.2)") tide3m3 write(6,"(' tideann = ',i2,' (0/1 flag for annual tides)')") | tideann write(6,"(' aurora = ',i2,' (0/1 flag for aurora)')") aurora write(6,"(' magphr = ',i2,' (0/1 flag for magnetosphere)')") | magphr write(6,"(' solar_protons = ',i2, | ' (0/1 flag for solar protons)')") solar_protons write(6,"(' planetary = ',i2, | ' (0/1 flag for planetary waves in lbc of Z)')") planetary write(6,"(' kelvin = ',i2, | ' (0/1 flag for kelvin waves in lbc of Z)')") kelvin ! ! write(6,"('If any of the following are spval (',e12.4,'),', ! | ' they will be calculated',/,'during the simulation on a per ', ! | 'timestep basis:')") spval if (ntimes_power == 0) then write(6,"(' power = ',e12.4,' (Hemispheric Power)')") power else write(6,"(' time-dependent power: ntimes = ',i4,' power_time=', | /,(3f4.0,e12.4))") ntimes_power,power_time(:,1:ntimes_power) endif if (ntimes_ctpoten == 0) then write(6,"(' ctpoten= ',e12.4,' (Cross-cap potential)')") | ctpoten else write(6,"(' time-dependent ctpoten: ntimes = ',i4, | ' ctpoten_time=',/,(3f4.0,e12.4))") ntimes_ctpoten, | ctpoten_time(:,1:ntimes_ctpoten) endif if (ntimes_kp == 0) then write(6,"(' kp = ',e12.4,' (Kp index)')") kp else write(6,"(' time-dependent Kp: ntimes = ',i4,' kp_time=', | /,(3f4.0,e12.4))") ntimes_kp,kp_time(:,1:ntimes_kp) endif ! write(6,"(' byimf = ',f9.3,' (BY component of IMF)')") | byimf write(6,"(' bzimf = ',f9.3,' (Bz component of IMF)')") | bzimf write(6,"(' swvel = ',f9.3,' (solar wind velocity)')") | swvel write(6,"(' swden = ',f9.3,' (solar wind density)')") | swden write(6,"(' AL = ',f9.3,' (AL, lower auroral mag index)')") | AL write(6,"(' colfac = ',f9.3,' (collision factor)')") | colfac ! write(6,"('END USER INPUT PARAMETERS')") write(6,"(72('-'),/)") end subroutine inp_print !------------------------------------------------------------------- subroutine validate_mtime(mtime,mxday,label) ! ! Validate a model time (day,hr,min) from input. ! (may be start or stop time, or frequency, ! e.g., history write frequency) ! If there is a bad value, stop with error message. ! Label is used to print error msg (usually the keyword name ! from namelist) ! integer,intent(in) :: mtime(3),mxday character(len=*),intent(in) :: label integer :: ier ! ier = 0 ! ! Day: if (mtime(1) < 0 .or. mtime(1) > mxday) then write(6,"(/,'>>> input ',a,': bad model day: ',i5, | ' (must be >= 0 and <= mxday)')") label,mtime(1) ier = 1 endif ! ! Hour: if (mtime(2) < 0 .or. mtime(2) > 23) then write(6,"(/,'>>> input ',a,': bad model hour: ',i5, | ' (must be >= 0 and <= 23)')") label,mtime(2) ier = 1 endif ! ! Minute: if (mtime(3) < 0 .or. mtime(3) > 59) then write(6,"(/,'>>> input ',a,': bad model minute: ',i5, | ' (must be >= 0 and <= 59)')") label,mtime(1) ier = 1 endif ! if (ier > 0) call shutdown('mtime') end subroutine validate_mtime !----------------------------------------------------------------------- subroutine usage_calendar ! ! Print usage statement for calendar inputs. ! character(len=60) :: char72(10) integer :: i ! 123456789-123456789-123456789-123456789-123456789-123456789- char72=(/ |'; ', |'; To set calendar start time and control calendar advance, ', |'; please use the following namelist input parameters, e.g., ', |'; ', |' START_YEAR = 1983 ; starting year (4-digit integer yyyy) ', |' START_DAY = 80 ; starting day of year (integer 1->365) ', |' CALENDAR_ADVANCE=1 ; if 1, advance calendar time ', |' ; if 0, do not advance calendar time ', |'; ', |' '/) do i=1,10 if (len_trim(char72(i)) > 0) write(6,"(a)") char72(i) enddo end subroutine usage_calendar !----------------------------------------------------------------------- subroutine validate_indices_time(rindex,ntimes,name) ! ! Validate user provided time series for solar index "name". Rindex will ! be either ctpoten_time or power_time, from namelist input. ! ! Args: real,intent(in) :: rindex(4,mxind_time) integer,intent(out) :: ntimes character(len=*),intent(in) :: name ! ! Local: integer :: i,ii,n integer(kind=8) :: nsec0,nsec1 ! ! External: integer(kind=8),external :: mtime_to_nsec ! ! Validate times and values in user provided time series: ntimes = 0 if (any(rindex /= spval)) then ! ! Time series must be provided in groups of 4 (day,hr,min,value): n = 0 do i=1,mxind_time do ii=1,4 if (rindex(ii,i) /= spval) n = n+1 enddo enddo if (mod(n,4) /= 0) then write(6,"('>>> INPUT: must provide ',a,' in groups', | ' of 4: n=',i5,' mod(n,4)=',i5)") name,n,mod(n,4) call shutdown('validate_indices_time') endif do i=1,mxind_time if (any(rindex(:,i) /= spval)) then call validate_mtime(int(rindex(1:3,i)),mxday,name) if (rindex(4,i) <= 0.) then write(6,"(/,'>>> INPUT: ',a,' values must be ', | 'positive: i=',i3,' rindex(4,i)=',e12.4)") | name,i,rindex(4,i) call shutdown('validate_indices_time') endif ntimes = ntimes+1 endif enddo ! i=1,mxind_time ! ! Times must be increasing (assume non-spvals are from 1 to ntimes, ! i.e., not interspersed with spvals): if (ntimes > 1) then nsec0 = mtime_to_nsec(int(rindex(1:3,1))) do i=2,ntimes nsec1 = mtime_to_nsec(int(rindex(1:3,i))) if (nsec0 >= nsec1) then write(6,"(/,'>>> INPUT: ',a,' times must increase', | '. Check time at i=',i3,' day,hr,min=',3i4,' and the', | ' time previous to i.')") name,i,int(rindex(1:3,i)) call shutdown('validate_indices_time') endif nsec0 = nsec1 enddo ! i=1,ntimes endif ! ntimes > 1 endif ! ctpoten_time end subroutine validate_indices_time !----------------------------------------------------------------------- subroutine inp_lbc ! ! Validate user's request for lower boundary options, as specified ! by namelist input (called once per run from sub input) ! use params_module,only: dlat implicit none ! ! Local: integer :: i,igswm,incep,iecmwf,izatmos,incep_rean,iwacxg5 ! ! Set local GSWM flag: igswm = 0 if (len_trim(gswm_mi_di_ncfile ) > 0.or. | len_trim(gswm_mi_sdi_ncfile) > 0.or. | len_trim(gswm_nm_di_ncfile ) > 0.or. | len_trim(gswm_nm_sdi_ncfile) > 0) igswm = 1 incep=0 ; iecmwf=0 ; izatmos=0 ; incep_rean=0 if (len_trim(zatmos_ncfile)>0) izatmos=1 if (len_trim(ncep_ncfile) >0) incep=1 if (len_trim(ecmwf_ncfile) >0) iecmwf=1 if (len_trim(ncep_reanalysis) >0) incep_rean=1 if (wacxg5_nfiles > 0) iwacxg5=1 ! ! Must provide one and only one of the following files for lbc: ! zatmos_ncfile, ncep_ncfile, ncep_reanalysis, ecmwf_ncfile ! if (izatmos+incep+iecmwf+incep_rean+iwacxg5 == 0) then write(6,"(/,'>>> Must provide lower boundary data file ', | 'by defining one of the following input parameters: ', | 'ZATMOS_NCFILE, NCEP_NCFILE,',' NCEP_REANALYSIS, ', | 'ECMWF_NCFILE, or WACXG5_NCFILE')") call shutdown('Need data file for lbc') endif if (izatmos+incep+iecmwf+incep_rean+iwacxg5 > 1) then write(6,"(/,'>>> Must provide ONLY ONE lbc data file ', | 'by defining one of the following input parameters: ', | 'ZATMOS_NCFILE, NCEP_NCFILE,',' NCEP_REANALYSIS, ', | 'ECMWF_NCFILE or WACXG5_NCFILE')") write(6,"('zatmos_ncfile=',a)") trim(zatmos_ncfile) write(6,"('ncep_ncfile =',a)") trim(ncep_ncfile) write(6,"('ncep_reanalysis =',a)") trim(ncep_reanalysis) write(6,"('ecmwf_ncfile =',a)") trim(ecmwf_ncfile) if (wacxg5_nfiles > 0) then do i=1,wacxg5_nfiles write(6,"('wacxg5_ncfiles(',i3,') =',a)") | i,trim(wacxg5_ncfiles(i)) enddo endif call shutdown('Only one lbc data file allowed') endif ! ! Cannot request both GSWM and Hough mode tides: if (igswm == 1.and.(any(tide /= 0).or.any(tide2 /= 0))) then write(6,"(/,'>>> Cannot request both GSWM and Hough mode', | ' tides.')") call shutdown('both GSWM and Hough mode tides not allowed') endif ! ! Cannot request non-migrating GSWM tides at 5-deg resolution: if ((len_trim(gswm_nm_di_ncfile) > 0.or. | len_trim(gswm_nm_sdi_ncfile) > 0).and. | dlat == 5.0) then write(6,"(/,'>>> Non-migrating GSWM tides are not', | ' supported in the 5 deg resolution model.')") call shutdown('non-migrating GSWM not allowed at 5 deg res') endif ! ! NCEP available only at 5-deg resolution: if (len_trim(ncep_ncfile) > 0 .and. dlat==2.5) then write(6,"(/,'>>> NCEP lower boundaries are available only', | ' at the 5-deg resolution model.')") call shutdown('NCEP not available at 2.5-deg resolution') endif ! NCEP requested ! ! NCEP_REANALYSIS available only at 2.5 deg resolution: if (len_trim(ncep_reanalysis) > 0.and.dlat==5.0) then write(6,"(/,'>>> NCEP REANALYSIS lower boundaries ', | ' are available only at the 2.5-deg resolution model.')") call shutdown( | 'NCEP REANALYSIS not available at 5.0-deg resolution') endif ! NCEP REANALYSIS requested ! ! ECMWF available only at 2.5 deg resolution: if (len_trim(ecmwf_ncfile) > 0.and.dlat==5.0) then write(6,"(/,'>>> ECMWF lower boundaries are available only', | ' at the 2.5-deg resolution model.')") call shutdown('ECMWF not available at 5.0-deg resolution') endif ! ECMWF requested ! ! WACXG5 available only at 2.5 deg resolution: if (iwacxg5 > 0.and.dlat==5.0) then write(6,"(/,'>>> WACXG5 lower boundaries are available only', | ' at the 2.5-deg resolution model.')") call shutdown('WACXG5 not available at 5.0-deg resolution') endif ! WACXG5 requested ! ! Cannot use planetary, kelvin, or 2-day waves with NCEP or ECMWF: if (len_trim(ncep_reanalysis) > 0.or.len_trim(ncep_ncfile) > 0.or. | len_trim(ecmwf_ncfile) > 0 .or. iwacxg5 > 0) then if (planetary > 0.or.kelvin > 0) then write(6,"(/,'>>> Cannot request Planetary or Kelvin', | ' waves with NCEP or ECMWF lower boundary.')") call shutdown('ECMWF or NCEP and Planetary not allowed') endif if (any(tide3m3 /= 0)) then write(6,"(/,'>>> Cannot request 2-day wave (tide3m3)', | ' with NCEP or ECMWF lower boundary.')") call shutdown('ECMWF or NCEP plus 2-day wave not allowed') endif ! ! Cannot use Annual tides with NCEP or ECMWF or WACXG5: if (tideann > 0) then write(6,"('>>> Cannot request Annual tides with ', | 'NCEP or ECMWF or wacxg5 lower boundary')") call shutdown | ('ECMWF, NCEP or WACXG5 plus Annual tides not allowed') endif endif ! NCEP, NCEP_REAN ECMWF or WACXG5 requested ! ! Report to stdout: ! write(6,"(/,'Input: The following input parameters will be used ', | /,7x,'to configure lower boundary conditions of T,U,V,Z:')") if (len_trim(zatmos_ncfile) > 0) write(6,"('ZATMOS_NCFILE = ',a)") | trim(zatmos_ncfile) if (len_trim(ncep_ncfile) > 0) write(6,"('NCEP_NCFILE = ',a)") | trim(ncep_ncfile) if (len_trim(ncep_reanalysis) > 0) write(6,"('NCEP_REANALYSIS = ', | a)") trim(ncep_reanalysis) if (len_trim(ecmwf_ncfile) > 0) write(6,"('ECMWF_NCFILE = ',a)") | trim(ecmwf_ncfile) if (wacxg5_nfiles > 0) then do i=1,wacxg5_nfiles write(6,"('WACXG5_NCFILES(',i3,') = ',a)") | i,trim(wacxg5_ncfiles(i)) enddo endif if (igswm > 0) then if (len_trim(gswm_mi_di_ncfile) > 0) | write(6,"('GSWM_MI_DI_NCFILE = ',a)") trim(gswm_mi_di_ncfile) if (len_trim(gswm_mi_sdi_ncfile) > 0) | write(6,"('GSWM_MI_SDI_NCFILE = ',a)")trim(gswm_mi_sdi_ncfile) if (len_trim(gswm_nm_di_ncfile) > 0) | write(6,"('GSWM_NM_DI_NCFILE = ',a)") trim(gswm_nm_di_ncfile) if (len_trim(gswm_nm_sdi_ncfile) > 0) | write(6,"('GSWM_NM_SDI_NCFILE = ',a)")trim(gswm_nm_sdi_ncfile) endif write(6,"('TIDE = ',5e12.4)") tide write(6,"('TIDE2 = ',5e12.4,/,8x,5e12.4)") tide2 write(6,"('TIDE3M3 = ',/,5e12.4)") tide3m3 write(6,"('TIDEANN = ',i3)") tideann write(6,"('Planet = ',l1)") planetary write(6,"('Kelvin = ',l1)") kelvin end subroutine inp_lbc !----------------------------------------------------------------------- end module input_module