#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,nmlat,nmlonp1 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. Declare corresponding components of input_type (use same names) ! 3. Add variables to namelist/tgcm_input/ ! 4. Initialize variables in inp_init ! 5. Add to stdout print in inp_print ! 6. 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: ! integer,parameter :: mxlen_filename=1024 character(len=mxlen_filename) :: | label, ! optional generic text label for this run | 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) | current_pg, ! 0/1 flag to add current due to plasma pressure and gravity to rhs (default 1) | current_kq, ! 0/1 flag to calculate height-integrated current density (default 0) | 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 | ntask_maglat, ! number of tasks in mag latitude dimension (not namelist) | ntask_maglon, ! number of tasks in mag longitude dimension (not namelist) | calc_helium, ! calculate helium if calc_helium=1, otherwise set he=0. | enforce_opfloor ! if > 0, enforce O+ floor (see oplus.F) 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 | colfac ! collision factor ! ! Input parameters that can be either constant or time-dependent: real :: | power, ! hemispheric power (gw) (hpower on histories) | ctpoten, ! cross-cap potential (volts) | bximf, ! BX component of IMF | 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 | kp ! Kp index real,dimension(4,mxind_time) :: power_time,ctpoten_time, | bximf_time,byimf_time,bzimf_time,swvel_time,swden_time,al_time, | kp_time,f107_time,f107a_time integer :: | ntimes_ctpoten,ntimes_power,ntimes_bximf,ntimes_byimf, | ntimes_bzimf,ntimes_swden,ntimes_swvel,ntimes_al,ntimes_kp, | ntimes_f107,ntimes_f107a 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 ! ! If indices_interp==1, time-dependent indices (power_time, ctpoten_time, etc) ! will be interpolated to model time, otherwise they will change only ! when the given values change. This has no effect on indices given as constants. ! integer :: indices_interp=1 ! ! Import data file names: 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 ! | 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 | 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) ! ! Primary history user input (dimension parameters are in params.h): character(len=mxlen_filename) :: | 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=mxlen_filename) :: | 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 | ecmwf_daily ! 0 or 1: if 1, then average 6-hourly ecmwf data to daily, ! if 0, then use 6-hourly ecmwf data (default is 0) ! ! Namelist for read: namelist/tgcm_input/ | label,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,kp,aurora, | power,ctpoten,bximf,byimf,bzimf,swvel,swden,al,colfac,tideann, | magphr,solar_protons,gpi_ncfile,ncep_ncfile, gswm_mi_di_ncfile, | ncep_reanalysis,ecmwf_ncfile,step_compqrj,step_ch4,ecmwf_daily, | 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,kp_time, | calendar_advance,ctpoten_time,power_time,f107_time,f107a_time, | bximf_time,byimf_time,bzimf_time,al_time,swden_time,swvel_time, | indices_interp,meped_file,weimer_ncfile,planetary,kelvin, | sech_nbyte,hpss_path,current_pg,current_kq,calc_helium, | enforce_opfloor ! ! List of fields that are always written to secondary histories: character(len=16) :: secflds_mandatory(5) = | (/'TN ', | 'O2 ', | 'O1 ', | 'ZG ', | '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 ! ! If Weimer potential model is requested, but swden and/or swvel are ! not provided, then use default constants. Likewise for byimf and bzimf: ! real,parameter :: swden_default = 4. real,parameter :: swvel_default = 400. real,parameter :: byimf_default = 0. real,parameter :: bzimf_default = 0. 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) ! ! Sub inp_solar validates combinations of potential_model, gpi_ncfile, ! imf_ncfile, and power,ctpoten,f107,f107a,bximf,byimf,bzimf,swden,swvel, ! and their time-dependent equivalents. ! call inp_solar ! ! 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 = ' ' amievol = ' ' hpss_path = ' ' ! gpi_ncfile = ' ' ! user input gpi file path ! ncep_ncfile = ' ' ! user input ncep file path ncep_reanalysis = ' ' ! ncep reanalysis file path ecmwf_ncfile = ' ' ! ECMWF ERA-40 nc data file for T,Z lbc weimer_ncfile = ' ' ! user input weimer coef file path ! 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 current_pg = 1 ! on by default current_kq = 0 ! off by default 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 calc_helium = ispval ecmwf_daily = ispval enforce_opfloor = ispval power_time(:,:) = spval ctpoten_time(:,:) = spval bximf_time(:,:) = spval byimf_time(:,:) = spval bzimf_time(:,:) = spval swden_time(:,:) = spval swvel_time(:,:) = spval al_time (:,:) = spval kp_time (:,:) = spval f107_time (:,:) = spval f107a_time(:,:) = 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 ! ! 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 ! ! 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 ! ! Choose number of tasks in lon,lat dimensions: call mkntask(ntask,nlonp4,nlat,ntask_lon,ntask_lat,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 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 ! ! Choose number of tasks in maglon,maglat dimensions: call mkntask(ntask,nmlonp1,nmlat,ntask_maglon,ntask_maglat,ier) if (ier /= 0) then write(6,"(/,'>>> INPUT: error from mkntask. ntask_maglat=', | i3,' ntask_lon=',i3,' ntask=',i3)") ntask_lat,ntask_maglon, | ntask call shutdown('MKNTASK') else write(6,"('Input: mkntask chose ntask_maglon=',i3, | ' ntask_maglat=',i3,' (ntask=',i3,')')") | ntask_maglon,ntask_maglat,ntask endif #endif ! ! 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) ! ! 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 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: need WEIMER_NCFILE for Weimer2001')") call shutdown('Need WEIMER_NCFILE for Weimer 2001') 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 ! ! Collision factor: if (colfac==spval) then write(6,"(/,'Input: no value read for colfac. Using default', | ' colfac = 1.5')") colfac = 1.5 endif ! ! If calc_helium == 1 then calculate helium, otherwise zero out helium. ! if (calc_helium==ispval) then calc_helium = 1 write(6,"('Input: Using default calc_helium = ',i3)")calc_helium elseif (calc_helium <= 0) then calc_helium = 0 write(6,"('Input: calc_helium=',i3,' -> will zero out ', | 'helium.')") calc_helium endif if (calc_helium > 0) calc_helium=1 ! ! If enforce_opfloor > 0, then enforce O+ floor (see oplus.F) ! if (enforce_opfloor==ispval.or.enforce_opfloor > 0) then enforce_opfloor = 1 elseif (enforce_opfloor <= 0) then enforce_opfloor = 0 endif write(6,"('Input: enforce_opfloor=',i3)") enforce_opfloor ! ! ecmwf data is 6-hourly (ecmwf_ncfile). If ecmwf_daily==1, then ! this data will be averaged to daily values, otherwise, the ! 6-hourly data will be used (default is ecmwf_daily = 0). ! if (ecmwf_daily==ispval) then ! was not read from namelist ecmwf_daily = 0 ! default elseif (ecmwf_daily <= 0) then ecmwf_daily = 0 else if (ecmwf_daily > 0) ecmwf_daily=1 endif if (ecmwf_daily==0) then write(6,"('Input: ecmwf_daily=',i2,' -> will NOT average ', | 'ecmwf data to daily (will use 6-hourly ecmwf data)')") | ecmwf_daily else write(6,"('Input: ecmwf_daily=',i2,' -> will average ', | ' 6-hourly ecmwf data to daily values')") ecmwf_daily 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==ispval) then dynamo = 1 write(6,"('Input: dynamo will be called by default')") 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 ! ! Horizontal eddy diffusion flag: if (difhor == ispval) then difhor = 1 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 ! ! hpss path: if hpss_path not set, then do not make hsi dispose script. ! (see call init_dispose in tgcm.F, and call add_dispose in dispose.F) ! if (len_trim(hpss_path)==0) then ! write(hpss_path,"('/home/',a,'/',a)") trim(logname), ! | trim(tgcm_version) ! write(6,"('inp_model: hpss_path=',a)") trim(hpss_path) ! endif end subroutine inp_model !----------------------------------------------------------------------- subroutine mkntask(ntask,nx,ny,ntaskx,ntasky,ier) ! ! Args: integer,intent(in) :: ntask,nx,ny integer,intent(out) :: ntaskx,ntasky,ier ! ! Local: integer,parameter :: mxtask=1000 integer :: i,j,ntx(mxtask),nty(mxtask),nchoice,ngap, | ngap_prev,ii ntaskx = 0 ntasky = 0 nchoice=0 do i=1,nx ! usually longitude do j=1,ny ! usually latitude 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 nty(nchoice)=j ntx(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 (ntx(i) == nty(i)) then ntasky = nty(i) ntaskx = ntx(i) endif enddo if (ntasky==0.or.ntaskx==0) then ngap_prev = nx*ny do i=1,nchoice ngap = ntx(i)-nty(i) if (abs(ngap) < ngap_prev) then ngap = ntx(i)-nty(i) ngap_prev = abs(ngap) ii = i endif enddo ntasky = nty(ii) ntaskx = ntx(ii) ! ! If they are not equal, ntlon should be > ntlat because nlon > nlat. if (ntaskx < ntasky) then i = ntasky ntasky = ntaskx ntaskx = i endif endif ier =0 if (ntasky==0.or.ntaskx==0.or.ntasky*ntaskx /= 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, | 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=mxlen_filename) :: chlong character(len=mxlen_filename) :: 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 (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. 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 ! ! 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: chlong = ' ' do i=1,nout chlong = output(i) output(i) = 'dummy' if (any(output==chlong)) then write(6,"(/,'>>> INPUT: Duplicate OUTPUT file names = ', | a,/)") trim(chlong) call shutdown('OUTPUT') endif output(i) = chlong 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=mxlen_filename) :: chlong character(len=80) :: 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 are deprecated: 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 ! ! Number of steps in each time series must be a multiple of SECHIST 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: chlong = ' ' do i=1,nout chlong = secout(i) secout(i) = 'dummy' if (any(secout==chlong)) then write(6,"(/,'>>> INPUT: Duplicate SECOUT file names = ', | a,/)") trim(chlong) call shutdown('SECOUT') endif secout(i) = chlong 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: chlong = ' ' do i=1,nflds_sech chlong = secflds(i) secflds(i) = 'dummy' if (any(secflds==chlong)) then write(6,"(/,'>>> INPUT: Duplicate SECFLDS field names = ', | a,/)") trim(chlong) call shutdown('SECFLDS') endif secflds(i) = chlong 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(potential_model) > 0) | write(6,"(' high-lat electric potential model: ', | 'potential_model = ',a)") trim(potential_model) 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 (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) 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(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 = ',i2,' (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 write(6,"(' current_pg = ',i2,' (Add current due to plasma', | ' pressure gradient and gravity to rhs)')") current_pg write(6,"(' current_kq = ',i2, | ' (Calculate height-integrated current density)')") | current_kq endif ! ! More model-wide inputs: ! write(6,"(' eddy_dif = ',i2,' (DOY-dependent eddy diffusion ', ! | 'flag)')") eddy_dif 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 if (ntimes_bximf == 0) then write(6,"(' bximf = ',e12.4,' (BX component of IMF)')") bximf else write(6,"(' time-dependent bximf: ntimes = ',i4,' bximf_time=', | /,(3f4.0,e12.4))") ntimes_bximf,bximf_time(:,1:ntimes_bximf) endif if (ntimes_byimf == 0) then write(6,"(' byimf = ',e12.4,' (BY component of IMF)')") byimf else write(6,"(' time-dependent byimf: ntimes = ',i4,' byimf_time=', | /,(3f4.0,e12.4))") ntimes_byimf,byimf_time(:,1:ntimes_byimf) endif if (ntimes_bzimf == 0) then write(6,"(' bzimf = ',e12.4,' (Bz component of IMF)')") bzimf else write(6,"(' time-dependent bzimf: ntimes = ',i4,' bzimf_time=', | /,(3f4.0,e12.4))") ntimes_bzimf,bzimf_time(:,1:ntimes_bzimf) endif if (ntimes_swvel == 0) then write(6,"(' swvel = ',e12.4,' (solar wind velocity)')") swvel else write(6,"(' time-dependent swvel: ntimes = ',i4,' swvel_time=', | /,(3f4.0,e12.4))") ntimes_swvel,swvel_time(:,1:ntimes_swvel) endif if (ntimes_swden == 0) then write(6,"(' swden = ',e12.4,' (solar wind density)')") swden else write(6,"(' time-dependent swden: ntimes = ',i4,' swden_time=', | /,(3f4.0,e12.4))") ntimes_swden,swden_time(:,1:ntimes_swden) endif if (ntimes_f107 == 0) then write(6,"(' f107 = ',e12.4,' (F10.7 solar flux)')") f107 else write(6,"(' time-dependent f107: ntimes = ',i4,' f107_time=', | /,(3f4.0,e12.4))") ntimes_f107,f107_time(:,1:ntimes_f107) endif if (ntimes_f107a == 0) then write(6,"(' f107a = ',e12.4,' (81-day ave F10.7 flux)')") f107a else write(6,"(' time-dependent f107a: ntimes = ',i4,' f107a_time=', | /,(3f4.0,e12.4))") ntimes_f107a,f107a_time(:,1:ntimes_f107a) endif ! write(6,"(' al = ',e12.4,' (AL, lower auroral mag index)')") | al write(6,"(' calc_helium = ',i4,' (0/1 flag for helium)')") | calc_helium ! 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_timedep(constant,timedep,mxtimes,ntimes,name) ! ! Validate times and values in user provided time series. ! ! Args: real,intent(in) :: constant,timedep(4,mxtimes) integer,intent(in) :: mxtimes integer,intent(out) :: ntimes character(len=*),intent(in) :: name ! ! Local: integer :: i,ii,n integer(kind=8) :: nsec,nsec0,nsec1,nsec_start,nsec_stop ! ! External: integer(kind=8),external :: mtime_to_nsec ! ! Validate times and values in user provided time series: ntimes = 0 if (any(timedep /= spval)) then ! ! Time series must be provided in groups of 4 (day,hr,min,value): n = 0 do i=1,mxtimes do ii=1,4 if (timedep(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_timedep') endif do i=1,mxtimes if (any(timedep(:,i) /= spval)) then call validate_mtime(int(timedep(1:3,i)),mxday,name) ntimes = ntimes+1 endif enddo ! i=1,mxtimes nsec_start = mtime_to_nsec(start(:,1)) ! model start time nsec_stop = mtime_to_nsec(stop(:,1)) ! model stop time ! ! First time must be model start time: if (ntimes > 0) then nsec = mtime_to_nsec(int(timedep(1:3,1))) if (nsec /= nsec_start) then write(6,"(/,'>>> INPUT: Please provide first value of ',a, | ' at model START time.')") trim(name) call shutdown('validate_timedep') endif ! ! All times must be between START and STOP times: do i=1,ntimes nsec = mtime_to_nsec(int(timedep(1:3,i))) if (nsec < nsec_start .or. | nsec > nsec_stop) then write(6,"(/,'>>> INPUT: ',a,' time ',3i4,' is outside ', | 'model START/STOP times: START=',3i4,' STOP=',3i4)") | trim(name),int(timedep(1:3,i)),start(:,1),stop(:,1) call shutdown('validate_timedep') endif enddo endif ! ntimes > 0 ! ! 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(timedep(1:3,1))) do i=2,ntimes nsec1 = mtime_to_nsec(int(timedep(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(timedep(1:3,i)) call shutdown('validate_timedep') endif nsec0 = nsec1 enddo ! i=1,ntimes endif ! ntimes > 1 endif ! any(timedep /= spval) ! ! User cannot provide both a constant and time-dependent values: if (ntimes > 0 .and. constant /= spval) then write(6,"('>>> INPUT: Please provide either constant or ', | 'time-dependent values for ',a,' (not both)')") trim(name) write(6,"(a,'=',e12.4,' ',a,'_time=',/,(6e12.4))") | trim(name),constant,trim(name),timedep(4,:) call shutdown('validate_timedep') endif end subroutine validate_timedep !----------------------------------------------------------------------- subroutine inp_solar ! ! NOTE: imf_ncfile is not available in timegcm (only in tiegcm) ! ! Validate combinations of potential_model, gpi_ncfile, imf_ncfile, and ! power,ctpoten,f107,f107a,bximf,byimf,bzimf,swden,swvel, and their ! time-dependent equivalents. ! ! The rules for these namelist read parameters are as follows: ! 1. Potential_model must be 'HEELIS','WEIMER','WEIMER01','WEIMER05', or 'NONE' ! (if 'WEIMER', then the 2005 model will be called) ! (if potential_model is not provided, it defaults to 'HEELIS') ! 2. gpi_ncfile data file can be provided only with Heelis potential model. ! (data file has 3-hourly Kp and daily f107,f107a) ! 3. imf_ncfile data file can be provided only with Weimer potential model. ! (data file has hourly bx,by,bz,swvel,swden,kp, and daily f107,f107a) ! 4. User cannot provide both gpi_ncfile and imf_ncfile in a single run, ! except when only f10.7 is requested from the gpi file. ! 5. User can provide the following parameters as either constants or ! time-dependent values: ctpoten,power,bximf,byimf,bzimf,swden,swvel ! (time-dependent keywords are xxxx_time, e.g., ctpoten_time) ! Time-dependent namelist f107,f107a are not yet available. ! Valid ranges for user-provided parameters are not enforced. ! 6. KP can be provided only if non-gpi run, and at least one of hpower ! and ctpoten are NOT provided. KP cannot be specified in a Weimer ! potential run. ! ! If (potential_model == 'HEELIS') then ! [user does not need to provide bx,by,bz,swvel,swden] ! if (gpi_ncfile is NOT provided) then ! [user must provide hp,cp,f107,f107a] ! elseif (gpi_ncfile is provided) then ! [user must NOT provide at least one of hp,cp,f107,f107a] ! [parameters not provided will be taken or calculated from the data] ! endif ! Endif ! ! If (potential_model == 'WEIMER') then ! [user is not allowed to provide ctpoten (derived from Weimer potential)] ! [if user does not provide power, it will be calculated from bz,swvel] ! if (imf_ncfile is NOT provided) then ! [user must provide bximf,byimf,bzimf,swden,swvel,f107,f107a] ! elseif (imf_ncfile is provided) then ! [user must NOT provide at least one of bx,by,bz,swden,swvel,f107,f107a] ! [parameters not provided will be taken from the data] ! endif ! Endif ! ! If time-dependent values are given, sub validate_timedep validates ! the times, and returns ntimes_xxxx. If only constants are given, ! it returns ntimes_xxxx == 0 ! call validate_timedep(ctpoten,ctpoten_time,mxind_time, | ntimes_ctpoten,'ctpoten') call validate_timedep(power,power_time,mxind_time, | ntimes_power,'power') call validate_timedep(byimf,byimf_time,mxind_time, | ntimes_byimf,'byimf') call validate_timedep(bzimf,bzimf_time,mxind_time, | ntimes_bzimf,'bzimf') call validate_timedep(swden,swden_time,mxind_time, | ntimes_swden,'swden') call validate_timedep(swvel,swvel_time,mxind_time, | ntimes_swvel,'swvel') call validate_timedep(al,al_time,mxind_time, | ntimes_al,'al') aluse = .true. if (al == spval) aluse = .false. call validate_timedep(kp,kp_time,mxind_time, | ntimes_kp,'kp') call validate_timedep(f107,f107_time,mxind_time, | ntimes_f107,'f107') call validate_timedep(f107a,f107a_time,mxind_time, | ntimes_f107a,'f107a') ! ! Check electric potential model: ! 4/08 btf: Add wiemer05 option ! 4/25/08 btf: default potential_model is still heelis: ! if (len_trim(potential_model)==0) then write (6,"(4x,'Will use default Heelis elecric potential', | ' model')") potential_model='HEELIS' endif select case (trim(potential_model)) case('WEIMER01') write(6,"('Will use the Weimer 2001 potential model')") call expand_path(weimer_ncfile) ! coeffs file write(6,"('weimer_ncfile=',a)") trim(weimer_ncfile) ! ! Weimer05 not available in timegcm (only tiegcm): ! case('WEIMER05') ! write(6,"('Will use the Weimer 2005 potential model')") ! call expand_path(wei05sc_ncfile) ! coeffs file ! write(6,"(' wei05sc_ncfile=',a)") trim(wei05sc_ncfile) case('WEIMER') write(6,"('Will use the Weimer 2001 potential model')") call expand_path(weimer_ncfile) ! coeffs file write(6,"('weimer_ncfile=',a)") trim(weimer_ncfile) case('HEELIS') write (6,"('Will use the Heelis potential model')") case('NONE') write(6,"('Will NOT use an empirical potential model')") write(6,"('High-lat convection will be zero.)')") case default write(6,"(/,'>>> INPUT: unknown potential_model: ',a)") | trim(potential_model) write(6,"('potential_model can be one of the following:')") write(6,"('''HEELIS''',',','''WEIMER01''',',', | '''WEIMER''',',','''NONE''')") call shutdown('POTENTIAL_MODEL') end select ! ! gpi and imf data files can be used together only if only f10.7 flux ! is used from the gpi file (imf_ncfile not available in timegcm) ! if (len_trim(gpi_ncfile) > 0.and.len_trim(imf_ncfile) > 0) then ! write(6,"('Note INPUT: Both gpi_ncfile and imf_ncfile are ', ! | 'specified.',/,' In this case, only f10.7 flux will be ', ! | 'used from the gpi file.')") ! write(6,"(/,'>>> INPUT: User cannot request both GPI ', ! | '(gpi_ncfile) and IMF (imf_ncfile) data runs.')") ! call shutdown('GPI and IMF not allowed') ! endif ! ! Kp was specified: if (kp /= spval.or.ntimes_kp > 0) then ! ! Allow Kp and gpi_ncfile in same run. if (len_trim(gpi_ncfile) > 0) then ! write(6,"(/,'>>> INPUT: Cannot provide KP namelist input', ! | ' with a GPI run.')") ! call shutdown('KP input') write(6,"(/,'>>> WARNING INPUT: Am allowing constant ', | 'KP namelist and GPI data file')") endif ! ! Cannot provide KP input for a Weimer run: ! (altho later, we might make it possible to use the Kp in an ! IMF data file, with a Weimer run) ! if (potential_model(1:6)=='WEIMER') then write(6,"(/,'>>> INPUT: Cannot provide KP namelist input', | ' with a WEIMER run.')") call shutdown('KP input') endif ! ! If KP is provided, then at least one of power and ctpoten must NOT ! be provided, because the given KP will be used to calculate power ! and/or ctpoten. ! if ((ctpoten/=spval.or.ntimes_ctpoten>0).and. | (power /=spval.or.ntimes_power>0)) then write(6,"(/,'>>> INPUT: Cannot provide namelist KP and both', | ' POWER and CTPOTEN')") write(6,"(/,'If KP is provided, then at least one of ', | ' POWER and CTPOTEN must NOT be provided (KP will be used', | ' to calculate POWER and/or CTPOTEN)')") call shutdown('KP input') endif endif ! Kp provided ! ! Check parameters needed for Heelis potential model: if (trim(potential_model)=='HEELIS') then ! ! IMF data not allowed with Heelis potential model: ! (imf data file not available in timegcm) ! if (len_trim(imf_ncfile) > 0) then ! write(6,"(/,'>>> INPUT: IMF data runs (imf_ncfile) can', ! | ' be requested only with WEIMER potential model.')") ! call shutdown('IMF with HEELIS') ! endif ! ! 12/3/08 btf: User may set BY to test BY effect on Heelis (see aurora.F) ! if (byimf == spval) then write(6,"('Note input: Setting BY to 0 with HEELIS ', | 'potential model.')") byimf = 0. endif ! ! Heelis non-gpi run: user must provide power,ctpoten,f107,f107a: ! Later, an alternative would be for the user to provide IMF data ! then use empirical calculation to get power, etc from the IMF. ! Note: namelist time-dependent f107 is not available. ! 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 endif ! heelis potential model ! ! Check parameters needed for Weimer potential model: ! (note that IMF data files are not available in TIMEGCM) ! if (potential_model(1:6)=='WEIMER') then ! ! If gpi data is requested with Weimer, then only f10.7 will be ! used from the gpi file. ! if (len_trim(gpi_ncfile) > 0) then write(6,"('Input note: gpi_ncfile has been specified with', | ' Weimer convection model.',/,' In this case, only ', | 'f10.7 flux will be used from the gpi file.')") endif ! ! Weimer non-gpi run must provide f107: ! if (len_trim(gpi_ncfile) <= 0.and.(f107==spval.or.f107a==spval)) | then write(6,"(/,'>>> Weimer potential model without GPI data', | ' must provide namelist f107,f107a')") call shutdown('WEIMER non-GPI without f107') endif ! ! ctpoten cannot be provided by the user, since it will be ! calculated from the Weimer potential: ! if (ctpoten /= spval .or. ntimes_ctpoten > 0.and. | kp==spval.and.ntimes_kp==0) then write(6,"(/,'>>> INPUT: Cannot provide CTPOTEN with', | ' Weimer potential model')") write(6,"('(ctpoten is calculated from the Weimer', | ' electric potential)')") call shutdown('ctpoten and Weimer') endif ! ! If Weimer potential model is requested and byimf and/or bzimf are ! not provided, use default constants (bximf is not used in Weimer): ! if (byimf==spval.and.ntimes_byimf==0) then write(6,"('Input note: For Weimer potential run, I am setting', | ' default byimf = ',f8.2)") byimf_default byimf = byimf_default endif if (bzimf==spval.and.ntimes_bzimf==0) then write(6,"('Input note: For Weimer potential run, I am setting', | ' default bzimf = ',f8.2)") bzimf_default bzimf = bzimf_default endif ! ! If Weimer potential model is requested and swden and/or swvel are not ! provided, use default constants: ! if (swden==spval.and.ntimes_swden==0) then write(6,"('Input note: For Weimer potential run, I am setting', | ' default swden = ',f8.2)") swden_default swden = swden_default endif if (swvel==spval.and.ntimes_swvel==0) then write(6,"('Input note: For Weimer potential run, I am setting', | ' default swvel = ',f8.2)") swvel_default swvel = swvel_default endif endif ! weimer potential model ! ! Calendar must be advanced if using any date-sensitive data ! if (calendar_advance <= 0) then if (len_trim(gpi_ncfile) > 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('calendar_advance') endif if (len_trim(ncep_ncfile) > 0) then write(6,"(/,'>>> INPUT: Model must advance in', | ' time if NCEP_NCFILE is to be used.')") write(6,"(' To make an NCEP lb run, you must set ', | 'CALENDAR_ADVANCE = 1')") call shutdown('calendar_advance') endif if (len_trim(ncep_reanalysis) > 0) then write(6,"(/,'>>> INPUT: Model must advance in', | ' time if NCEP_REANALYSIS is to be used.')") write(6,"(' To make an NCEP REANALYSIS lb run, you must', | ' set CALENDAR_ADVANCE = 1')") call shutdown('calendar_advance') endif if (len_trim(ecmwf_ncfile) > 0) then write(6,"(/,'>>> INPUT: Model must advance in', | ' time if ECMWF_NCFILE is to be used.')") write(6,"(' To make an ECMWF lb run, you must', | ' set CALENDAR_ADVANCE = 1')") call shutdown('calendar_advance') endif endif ! calendar_advance <= 0 ! ! IMF data file not available in timegcm: ! if (len_trim(imf_ncfile) > 0) then ! if (calendar_advance <= 0) then ! write(6,"(/,'>>> INPUT: Model must advance in calendar', ! | ' time if IMF database is to be used.')") ! write(6,"(' To make an IMF run, you must set ', ! | 'CALENDAR_ADVANCE = 1')") ! call shutdown('calendar_advance') ! endif ! endif ! ! Report to stdout for debug: write(6,"(/,'inp_solar returning:')") write(6,"('potential_model=',a)") trim(potential_model) if (len_trim(gpi_ncfile) > 0) | write(6,"('gpi_ncfile=',a)") trim(gpi_ncfile) write(6,"('power=',e12.4,' ctpoten=',e12.4)") power,ctpoten write(6,"('f107 =',e12.4,' f107a =',e12.4)") f107,f107a write(6,"('bximf=',e12.4,' byimf =',e12.4,' bzimf=',e12.4)") | bximf,byimf,bzimf write(6,"('swden=',e12.4,' swvel =',e12.4)") swden,swvel end subroutine inp_solar !----------------------------------------------------------------------- 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 :: igswm,incep,iecmwf,izatmos,incep_rean ! ! 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 ! ! 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 == 0) then write(6,"(/,'>>> Must provide lower boundary data file ', | 'by defining one of the following input parameters: ', | 'ZATMOS_NCFILE, NCEP_NCFILE,',' NCEP_REANALYSIS, or ', | 'ECMWF_NCFILE')") call shutdown('Need data file for lbc') endif if (izatmos+incep+iecmwf+incep_rean > 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, or ', | 'ECMWF_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) 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 ! ! ZATMOS available only at 5-deg resolution: ! if (izatmos > 0 .and. dlat==2.5) then ! write(6,"(/,'>>> ZATMOS lower boundaries are available only', ! | ' at the 5-deg resolution model.')") ! call shutdown('ZATMOS not available at 2.5-deg resolution') ! endif ! ZATMOS requested ! ! 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 ! ! 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) 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: if (tideann > 0) then write(6,"('>>> Cannot request Annual tides with ', | 'NCEP or ECMWF lower boundary')") call shutdown('ECMWF or NCEP plus Annual tides not allowed') endif endif ! NCEP, NCEP_REAN or ECMWF 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 (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