From nancy at ucar.edu Wed Aug 5 18:25:12 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Wed, 5 Aug 2009 18:25:12 -0600 (MDT) Subject: [Dart-dev] [3985] DART/trunk/time_manager/time_manager_mod.html: Initial documentation for the time manager functions. Message-ID: <200908060025.n760PC2x013725@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090805/c4fd2463/attachment-0001.html -------------- next part -------------- Added: DART/trunk/time_manager/time_manager_mod.html =================================================================== --- DART/trunk/time_manager/time_manager_mod.html (rev 0) +++ DART/trunk/time_manager/time_manager_mod.html 2009-08-06 00:25:12 UTC (rev 3985) @@ -0,0 +1,1031 @@ + + +module time_manager_mod + + + + + +
+INTERFACE / +PUBLIC COMPONENTS / +NAMELIST / +FILES / +REFERENCES / +ERRORS / +BUGS / +PLANS / +PRIVATE COMPONENTS +
+ + + +

MODULE time_manager_mod

+ + + + + +
+

OVERVIEW

+ +

+Provides a set of routines to manipulate both time and calendars +of various types. +

+Time intervals are stored and defined in terms of integer number +of days and integer seconds. The minimum time resolution is 1 second. +Mathematical operations (e.g. addition, subtraction, multiplication) are +defined on these intervals. Seconds which roll over 86400 (the number +of seconds in a day) are converted into days. +

+Calendars interpret time intervals in terms of years, months, days. +Various calendars commonly in use in the scientific community are +supported. +

+ + + + +


+

OTHER MODULES USED

+
+types_mod
+utilities_mod
+
+ + + + + +


+

PUBLIC INTERFACE

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
use time_manager_mod, only : time_type
 operator(+)
 operator(-)
 operator(*)
 operator(/)
 operator(>)
 operator(>=)
 operator(==)
 operator(/=)
 operator(<)
 operator(<=)
 operator(//)
 set_time
 set_time_missing
 increment_time
 decrement_time
 get_time
 interval_alarm
 repeat_alarm
 THIRTY_DAY_MONTHS
 JULIAN
 GREGORIAN
 NOLEAP
 NO_CALENDAR
 GREGORIAN_MARS
 set_calendar_type
 get_calendar_type
 get_calendar_string
 set_date
 get_date
 increment_date
 decrement_date
 days_in_month
 leap_year
 length_of_year
 days_in_year
 month_name
 julian_day
 time_manager_init
 print_time
 print_date
 write_time
 read_time
 interactive_time
+ +

NOTES

+ +

+No namelist at this time. + + + +

+ + + + + + + + +


+

PUBLIC COMPONENTS

+
+ + + + + + +


+
+ var = set_time(seconds [, days]) +
+type(time_type)                        :: set_time
+integer,         intent(in)            :: seconds
+integer,         intent(in), optional  :: days
+
+

Description

+

+Fills a time type. If seconds are > 86400, they are converted +into the appropriate number of days. Note that seconds are specified first. +

+ + + + + +
secondsNumber of seconds. If larger than 86400, they are converted + into the appropriate number of days.
daysNumber of days. Default is 0.
+
+ + + +


+
+ var = set_time_missing() +
+type(time_type)                        :: set_time_missing
+
+

Description

+

+Set a time type to a missing value. The +resulting time value will cause an error +if used for an arithmetic operation or if get_time() is called. +

+
+ + + +


+
+ var = increment_time(time, seconds [, days]) +
+type(time_type)                        :: increment_time
+type(time_type), intent(in)            :: time
+integer,         intent(in)            :: seconds
+integer,         intent(in), optional  :: days
+
+

Description

+

+Adds the specified number of seconds and optionally, days, to the +given time and returns the new time. Increments cannot be negative +(see decrement_time below). +

+ + + + + + + +
timetime value to be incremented.
secondsnumber of seconds to add to given time.
daysoptionally a number of days to add to the given time.
+
+ + + +


+
+ var = decrement_time(time, seconds [, days]) +
+type(time_type)                        :: decrement_time
+type(time_type), intent(in)            :: time
+integer,         intent(in)            :: seconds
+integer,         intent(in), optional  :: days
+
+

Description

+

+Subtract the specified number of seconds and optionally, days, to the +given time and returns the new time. Decrements cannot be negative +(see increment_time above). +

+ + + + + + + +
timetime value to be decremented.
secondsnumber of seconds to subtract from the given time.
daysoptionally a number of days to subtract from the given time.
+
+ + + +


+
+ var = interval_alarm(time, time_interval, alarm, alarm_interval) +
+logical                        :: interval_alarm
+type(time_type), intent(in)    :: time
+type(time_type), intent(in)    :: time_interval
+type(time_type), intent(inout) :: alarm
+type(time_type), intent(in)    :: alarm_interval
+
+

Description

+

+ Supports a commonly used type of test on times for models. Given the + current time, and a time for an alarm, determines if this is the closest + time to the alarm time given a time step of time_interval. If this + is the closest time (alarm - time <= time_interval/2), the function + returns true and the alarm is incremented by the alarm_interval. Watch + for problems if the new alarm time is less than time + time_interval. +

+ + + + + + + + + +
timeCurrent time.
time_intervalBin size for determining if alarm time is close enough to now.
alarmWhen alarm next goes off next. Updated by this routine.
alarm_intervalHow often alarm goes off.
+
+ + + +


+
+ var = repeat_alarm(time, alarm_frequency, alarm_length) +
+type(time_type)                :: repeat_alarm
+type(time_type), intent(in)    :: time
+type(time_type), intent(in)    :: alarm_frequency
+type(time_type), intent(in)    :: alarm_length
+
+

Description

+

+Repeat_alarm supports an alarm that goes off with alarm_frequency and +lasts for alarm_length. If the nearest occurence of an alarm time +is less than half an alarm_length from the input time, repeat_alarm +is true. For instance, if the alarm_frequency is 1 day, and the +alarm_length is 2 hours, then repeat_alarm is true from time 2300 on +day n to time 0100 on day n + 1 for all n. +

+ + + + + + + +
timeCurrent time.
alarm_frequencyHow often the alarm goes off.
alarm_lengthHow long the alarm is true.
+
+ + + +


+
+ var = get_calendar_type() +
+integer                :: get_calendar_type
+
+

Description

+

+Returns default calendar type for mapping from time to date. +Calendar types are public integer parameters that define +various calendars. See elsewhere in this file for the list. +

+
+ + + +


+
+ var = set_date(year, month, day [, hours, minutes, seconds]) +
+type(time_type)                :: set_date
+integer, intent(in)            :: year
+integer, intent(in)            :: month
+integer, intent(in)            :: day
+integer, intent(in), optional  :: hours
+integer, intent(in), optional  :: minutes
+integer, intent(in), optional  :: seconds
+
+

Description

+

+Given a date interpreted using the current calendar type, +compute the corresponding time. +P> + + + + + + + + + + + + + +
yearInteger year.
monthInteger month number.
dayInteger day number.
hoursInteger hour. Default is 0.
minutesInteger minutes. Default is 0.
secondsInteger seconds. Default is 0.
+
+ + + +


+
+ var = increment_date(time [, years, months, days, hours, minutes, seconds]) +
+type(time_type)                :: increment_date
+type(time_type), intent(in)    :: time
+integer, intent(in), optional  :: years
+integer, intent(in), optional  :: months
+integer, intent(in), optional  :: days
+integer, intent(in), optional  :: hours
+integer, intent(in), optional  :: minutes
+integer, intent(in), optional  :: seconds
+
+

Description

+

+Given a time and some date increment, compute a new time. +The interpretation of the date depends on the currently selected +calendar type. +P> + + + + + + + + + + + + + + + +
timeCurrent time.
yearInteger years to add. Default is 0.
monthInteger months to add. Default is 0.
dayInteger days to add. Default is 0.
hoursInteger hours to add. Default is 0.
minutesInteger minutes to add. Default is 0.
secondsInteger seconds to add. Default is 0.
+
+ + + +


+
+ var = decrement_date(time [, years, months, days, hours, minutes, seconds]) +
+type(time_type)                :: decrement_date
+type(time_type), intent(in)    :: time
+integer, intent(in), optional  :: years
+integer, intent(in), optional  :: months
+integer, intent(in), optional  :: days
+integer, intent(in), optional  :: hours
+integer, intent(in), optional  :: minutes
+integer, intent(in), optional  :: seconds
+
+

Description

+

+Given a time and some date decrement, compute a new time. +The interpretation of the date depends on the currently selected +calendar type. +

+ + + + + + + + + + + + + + + +
timeCurrent time.
yearInteger years to subtract. Default is 0.
monthInteger months to subtract. Default is 0.
dayInteger days to subtract. Default is 0.
hoursInteger hours to subtract. Default is 0.
minutesInteger minutes to subtract. Default is 0.
secondsInteger seconds to subtract. Default is 0.
+
+ + + +


+
+ var = days_in_month(time) +
+integer                        :: days_in_month
+type(time_type), intent(in)    :: time
+
+

Description

+

+Given a time, determine the month based on the currently +selected calendar type and return the +numbers of days in that month. +

+ + + +
timeCurrent time.
+
+ + + +


+
+ var = leap_year(time) +
+logical                        :: leap_year
+type(time_type),intent(in)     :: time
+
+

Description

+

+Given a time, determine if the current year is a leap +year in the currently selected calendar type. +

+ + + +
timeCurrent time.
+
+ + + +


+
+ var = length_of_year() +
+integer                      :: length_of_year
+
+

Description

+

+For the currently selected calendar type, return the +number of days in a year if that value is fixed (e.g. there are +not leap years). For other calendar types, see +days_in_year() which takes a time +argument to determine the current year. +

+
+ + + +


+
+ var = days_in_year(time) +
+integer                        :: days_in_year
+type(time_type), intent(in)    :: time
+
+

Description

+

+Given a time, determine the year based on the currently +selected calendar type and return the +numbers of days in that year. +

+ + + +
timeCurrent time.
+
+ + + +


+
+ var = month_name(n) +
+character(len=9)               :: month_name
+integer,         intent(in)    :: n
+
+

Description

+

+Return a character string containing the month name corresponding +to the given month number. +

+ + + +
nMonth number. Must be between 1 and 12, inclusive.
+
+ + + +


+
+ var = julian_day(year, month, day) +
+integer                        :: julian_day
+integer,        intent(in)     :: year
+integer,        intent(in)     :: month
+integer,        intent(in)     :: day
+
+

Description

+

+Given a date in year/month/day format, +compute the day number from the beginning of the year. +The currently selected calendar type must be GREGORIAN. +

+ + + + + + + +
yearYear number in the Gregorian calendar.
monthMonth number in the Gregorian calendar.
dayDay of month in the Gregorian calendar.
+
+ + + +


+
+ var = read_time(file_unit [, form, ios_out]) +
+type(time_type)                         :: read_time
+integer,          intent(in)            :: file_unit
+character(len=*), intent(in),  optional :: form
+integer,          intent(out), optional :: ios_out
+
+

Description

+

+Read a time from the given file unit number. The unit must already +be open. The default format is ascii/formatted. If an error is +encountered and ios_out is specified, the error status will be returned +to the caller; otherwise the error is fatal. +

+ + + + + + + +
file_unitInteger file unit number of an already open file.
formFormat to read the time. Options are 'formatted' + or 'unformatted'. Default is 'formatted'.
ios_outOn error, if specified, the error status code is returned here. + If not specified, an error calls the standard error_handler and + exits.
+
+ + + + + + +


+
+ call get_time(time, seconds [, days]) +
+type(time_type), intent(in)             :: time
+integer,         intent(out)            :: seconds
+integer,         intent(out), optional  :: days
+
+

Description

+

+Returns days and seconds ( < 86400 ) corresponding to a time. +If the optional 'days' argument is not given, the days are converted +to seconds and the total time is returned as seconds. +Note that seconds preceeds days in the argument list. +

+ + + + + + + +
timeTime to convert into seconds and days.
secondsIf days is specified, number of seconds in the current day. + Otherwise, total number of seconds in time.
daysIf specified, number of days in time.
+
+ + + +


+
+ call set_calendar_type(mytype) +or + call set_calendar_type(calstring) +
+integer, intent(in)               :: mytype
+ or
+character(len=*), intent(in)      :: calstring
+
+

Description

+

+Selects the current calendar type, for converting between time +and year/month/day. The argument can either be one of the predefined +calendar integer parameter types (see elsewhere in this file for +the list of types), or a string which matches the name of the +integer parameters. The string interface is especially suitable for +namelist use. +

+ + + +
mytypeInteger parameter to select the calendar type.
+or + + + +
calstringCharacter string to select the calendar type. + Valid strings match the names of the integer parameters.
+
+ + + +


+
+ call get_calendar_string(mystring) +
+character(len=*), intent(out)     :: mystring
+
+ +

Description

+

+Return the character string corresponding to the +currently selected calendar type. +

+ + + +
mystringCharacter string corresponding to the current calendar type.
+
+ +subroutine get_date(time, year, month, day, hour, minute, second) + + +


+
+ call get_date(time, year, month, day, hour, minute, second) +
+type(time_type), intent(in)       :: time
+integer, intent(out)              :: year
+integer, intent(out)              :: month
+integer, intent(out)              :: day
+integer, intent(out)              :: hour
+integer, intent(out)              :: minute
+integer, intent(out)              :: second
+
+

Description

+

+Given a time, compute the corresponding date given the +currently selected calendar type. +

+ + + + + + + + + + + + + + + +
timeInput time.
yearCorresponding calendar year.
monthCorresponding calendar month.
dayCorresponding calendar day.
hourCorresponding hour.
minuteCorresponding minute.
secondCorresponding second.
+
+ + + +


+
+ call time_manager_init() +
+
+

Description

+

+Initializes any internal data needed by the time manager code. +Does not need to be called before using any of the time +manager routines; it will be called internally before executing +any of the other routines. +

+
+ + + +


+
+ call print_time(time [, str, iunit]) +
+type(time_type),  intent(in)           :: time
+character(len=*), intent(in), optional :: str
+integer,          intent(in), optional :: iunit
+ 
+
+

Description

+

+Print the time as days and seconds. If the optional str argument +is specified, print that string as a label. If iunit is specified, +write output to that unit; otherwise write to standard output/terminal. +

+ + + + + + + +
timeTime to be printed as days/seconds.
strString label to print before days/seconds. Default: 'TIME: '.
iunitUnit number to write output on. Default is standard output/terminal + (unit 6).
+
+ +subroutine print_date (time,str,iunit) + + +


+
+ call print_date(time [, str, iunit]) +
+type(time_type),  intent(in)           :: time
+character(len=*), intent(in), optional :: str
+integer,          intent(in), optional :: iunit
+ 
+
+

Description

+

+Print the time as year/month/day/hour/minute/second, as computed +from the currently selected calendar type. +If the optional str argument +is specified, print that string as a label. If iunit is specified, +write output to that unit; otherwise write to standard output/terminal. +

+ + + + + + + +
timeTime to be printed as a calendar date/time.
strString label to print before date. Default: 'DATE: '.
iunitUnit number to write output on. Default is standard output/terminal + (unit 6).
+
+ + + +


+
+ call write_time(file_unit, time [, form, ios]) +
+integer,          intent(in)               :: file_unit
+type(time_type),  intent(in)               :: time
+character(len=*), intent(in),  optional    :: form
+integer,          intent(out), optional    :: ios
+
+ +

Description

+

+Write a time to an already open file unit. The optional 'form' +argument controls whether it is formatted or unformatted. +On error, the optional 'ios' argument returns the error code; otherwise +a fatal error is triggered. +

+ + + + + + + + + +
file_unitInteger unit number for an already open file.
timeTime to write to the file.
formString format specifier; either 'unformatted' or 'formatted'. + Defaults to 'formatted'.
iosIf specified, on error the i/o status error code is returned here. + Otherwise, the standard error handler is called and the + program exits.
+
+ + + +


+
+ call interactive_time(time) +
+type(time_type), intent(inout)    :: time
+
+ +

Description

+

+Prompt the user for a time as a calendar date, based on the +currently selected calendar type. Writes prompt to standard output +and reads from standard input. +

+ + + +
timeTime type to be returned.
+
+ + + + + + + + +


+
+type time_type
+   private
+   integer :: seconds
+   integer :: days
+end type time_type
+
+ +

Description

+

+This type is used to define a time interval. +

+ + + + + + + +


+
+ integer :: NO_CALENDAR
+ integer :: GREGORIAN
+ integer :: GREGORIAN_MARS
+ integer :: JULIAN
+ integer :: THIRTY_DAY_MONTHS
+ integer :: NOLEAP
+
+ +

Description

+

+The public integer parameters which define different calendar types. +The same names defined as strings can be used to set the calendar type. +

+ + + + + + +


+
+ operator(+)
+ operator(-)
+ operator(*)
+ operator(/)
+ operator(>)
+ operator(>=)
+ operator(==)
+ operator(/=)
+ operator(<)
+ operator(<=)
+ operator(//)
+
+ +

Description

+

+Arithmetic operations are defined for time types, so expressions like +

+t3 = t1 + t2
+
+can be constructed. To use these operators, they must be listed +on the module use statement in the form specified above. +

+

+Multiplication is one time and one scalar. +

+

+Division with a single slash is integer, and returns the largest +integer for which time1 >= time2 * n. Division with a double slash +returns a double precision quotient of the two times. +

+ + + + + +


+

NAMELIST

+

No namelist is currently defined for the time manager code. +
+ + + + + + + +



+

FILES

+ + + + + + + +


+

REFERENCES

+ + + + + + + +
+

ERROR CODES and CONDITIONS

+
+ + + + + + + + +
RoutineMessageComment
+
+ + + + + + +


+

KNOWN BUGS

+

+none +

+ + + + + + +


+

FUTURE PLANS

+

+none +

+ + + + + + +


+

PRIVATE COMPONENTS

+

+none +

+ + + +
+ + @@ Diff output truncated at 40000 characters. @@ From nancy at ucar.edu Thu Aug 6 10:53:02 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 6 Aug 2009 10:53:02 -0600 (MDT) Subject: [Dart-dev] [3986] DART/trunk/converters/work/path_names_wrf-3dvar_tf_dart: Remove duplicated list of obs_def modules. Message-ID: <200908061653.n76Gr2ET018472@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090806/7fb1a8f6/attachment.html -------------- next part -------------- Modified: DART/trunk/converters/work/path_names_wrf-3dvar_tf_dart =================================================================== --- DART/trunk/converters/work/path_names_wrf-3dvar_tf_dart 2009-08-06 00:25:12 UTC (rev 3985) +++ DART/trunk/converters/work/path_names_wrf-3dvar_tf_dart 2009-08-06 16:53:01 UTC (rev 3986) @@ -12,5 +12,3 @@ common/types_mod.f90 mpi_utilities/null_mpi_utilities_mod.f90 utilities/utilities_mod.f90 -obs_def/obs_def_radar_mod.f90 -obs_def/obs_def_dew_point_mod.f90 From nancy at ucar.edu Thu Aug 6 11:20:57 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 6 Aug 2009 11:20:57 -0600 (MDT) Subject: [Dart-dev] [3987] DART/trunk/time_manager/schedule_mod.html: Initial cut at schedule module documentation. Message-ID: <200908061720.n76HKvPY015764@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090806/2912afaf/attachment.html -------------- next part -------------- Added: DART/trunk/time_manager/schedule_mod.html =================================================================== --- DART/trunk/time_manager/schedule_mod.html (rev 0) +++ DART/trunk/time_manager/schedule_mod.html 2009-08-06 17:20:57 UTC (rev 3987) @@ -0,0 +1,385 @@ + + +module schedule_mod + + + + + +
+INTERFACE / +PUBLIC COMPONENTS / +NAMELIST / +FILES / +REFERENCES / +ERRORS / +BUGS / +PLANS / +PRIVATE COMPONENTS +
+ + + +

MODULE schedule_mod

+ + + + + +
+

OVERVIEW

+ +

+Provides a set of routines to generate a regular pattern +of time windows. +

+ +

+ + + + +


+

OTHER MODULES USED

+
+types_mod
+utilities_mod
+time_manager_mod
+
+ + + + + +


+

PUBLIC INTERFACE

+ +
Contact: Jeff Anderson, Tim Hoar
+ + + + + +
use schedule_mod, only : schedule_type
 set_regular_schedule
 get_time_from_schedule
 get_schedule_length
+ +

NOTES

+ +

+Namelist +&schedule_mod_nml +may be read from file input.nml. +

+ + + + + + +


+

PUBLIC COMPONENTS

+
+ + + + + + +


+
+ call set_regular_schedule(schedule) +
+type(schedule_type), intent(out)       :: schedule
+
+

Description

+

+Uses the namelist information to compute and fill a +schedule_type variable. +

+ + + +
scheduleFills this derived type with the information needed to + generate a series of regularly spaced time windows.
+
+ + + +


+
+ call get_time_from_schedule(mytime, schedule, iepoch [, edge]) +
+type(time_type),     intent(out)           :: mytime
+ or
+real(digits12),      intent(out)           :: mytime
+type(schedule_type), intent(in)            :: schedule
+integer,             intent(in)            :: iepoch
+integer,             intent(in), optional  :: edge
+
+

Description

+

+Returns either the leading or trailing time for the specified +bin/epoch number for the given schedule. The time can be returned in one +of two formats, depending on the variable type specified for the +first argument: either a DART derived time_type, or a real of kind +digits12 (defined in the types_mod). +

+ + + + + + + + + +
mytimeReturn value with the leading or trailing edge time for the + requested bin. There are two supported return formats, either as + a standard DART time_type, or as a real value which will contain + the number of days plus any fraction.
scheduleSchedule type to extract information from.
iepochThe bin number, or epoch number, to return a time for. + Unless edge is specified and requests the ending time, the time + returned is the starting time for this bin.
edgeIf specified, and if edge is larger than 1, the trailing edge time + of the bin is returned. Any other value, or if this argument is + not specified, returns the leading edge time of the bin.
+
+ + + +


+
+ var = get_schedule_length() +
+integer                             :: get_schedule_length
+type(schedule_type), intent(in)     :: schedule
+
+

Description

+

+Return the total number of intervals/bins/epochs defined by +this schedule. +

+ + + +
scheduleReturn number of time intervals in this schedule.
+
+ + + + +


+
+type schedule_type
+   private
+   integer :: num_bins
+   integer :: current_bin
+   logical :: last_bin
+   integer :: calendar
+   character(len=32) :: calendarstring
+   type(time_type)          :: binwidth
+   type(time_type)          :: bininterval
+   type(time_type), pointer :: binstart(   :) => NULL()
+   type(time_type), pointer :: binend(     :) => NULL()
+   real(digits12),  pointer :: epoch_start(:) => NULL()
+   real(digits12),  pointer :: epoch_end(  :) => NULL()
+end type schedule_type
+
+ +

Description

+

+This type is used to define a schedule. +

+ + + + + + +


+

NAMELIST

+

We adhere to the F90 standard of starting a namelist with an ampersand + '&' and terminating with a slash '/'. +

+ namelist / schedule_mod_nml / 
+    first_bin_start, first_bin_end, last_bin_end, &
+    bin_interval_days, bin_interval_seconds, &
+    max_num_bins, calendar, print_table
+ 
+

Discussion

+

+Controls various aspects of filter. The inflation control variables are all +dimensioned 2, the first value being for the prior inflation and the second +being for the posterior inflation. + +

+

This namelist is read in a file called input.nml +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Contents Type Description
first_bin_startinteger, dimension(6)Date/time specification for starting time + of first bin. + Default: 2008, 9, 7, 0, 0, 0
first_bin_endinteger, dimension(6)Date/time specification for ending time + of first bin. Sets the bin width. + Default: 2008, 9, 7, 2, 0, 0
last_bin_endinteger, dimension(6)Date/time specification for ending time + of last bin. Sets the length of the overall + time of the schedule. + Default: 2008, 9, 11, 0, 0, 0
bin_interval_daysintegerSets the time between bins. Must be larger or + equal to the bin width. + Default: 0
bin_interval_secondsintegerSets the time between bins. Must be larger or + equal to the bin width. + Default: 21600
max_num_binsintegerUpper limit on the number of bins. + Default: 1000
calendarcharacter(len=32)String calendar type. Valid types are listed + in the +time_manager_mod file. + Default: "Gregorian"
print_tablelogicalIf .TRUE., print out information about the schedule + each time set_regular_schedule() is called. + Default: .FALSE.
+ +
+ + + + + + + +


+

FILES

+ + + + + + + +


+

REFERENCES

+ + + + + + + +
+

ERROR CODES and CONDITIONS

+
+ + + + + + + + +
RoutineMessageComment
+
+ + + + + + +


+

KNOWN BUGS

+

+none +

+ + + + + + +


+

FUTURE PLANS

+

+Setting the schedule from the namelist values means you can +only have a single schedule +object in the entire program. We also need a subroutine to initialize +a schedule type by giving explicit arguments. +

+ + + + + + +


+

PRIVATE COMPONENTS

+

+none +

+ + + +
+ + + + + + +
Contact: Jeff Anderson, Tim Hoar
Revision: $Revision$
Source: $URL$
Change Date: $Date$
Change history: try "svn log" or "svn diff"
+
+ + Property changes on: DART/trunk/time_manager/schedule_mod.html ___________________________________________________________________ Name: svn:mime-type + text/html Name: svn:keywords + Date Revision Author HeadURL Id From nancy at ucar.edu Thu Aug 6 12:53:44 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 6 Aug 2009 12:53:44 -0600 (MDT) Subject: [Dart-dev] [3989] DART/trunk/common/types_mod.html: Added missing doc file. Message-ID: <200908061853.n76Iri3e004358@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090806/9c863c04/attachment.html -------------- next part -------------- Added: DART/trunk/common/types_mod.html =================================================================== --- DART/trunk/common/types_mod.html (rev 0) +++ DART/trunk/common/types_mod.html 2009-08-06 18:53:44 UTC (rev 3989) @@ -0,0 +1,346 @@ + + +module types_mod + + + + + +
+INTERFACE / +PUBLIC COMPONENTS / +NAMELIST / +FILES / +REFERENCES / +ERRORS / +BUGS / +PLANS / +PRIVATE COMPONENTS +
+ + + +

MODULE types_mod

+ + + + + +
+

OVERVIEW

+ +

+Provides some commonly used mathematical constants, and a set of +Fortran integer and real kinds, to be used to select the right +variable size (e.g. 4 bytes, 8 bytes) to match the rest of the +DART interfaces. (DART does not depend on compiler flags to +set precision, but explicitly specifies a kind for each variable +in the public interfaces.) +

+ +

+ + + + +


+

OTHER MODULES USED

+
+none
+
+ + + + + +


+

PUBLIC INTERFACE

+ +This routine provides the following constants, but no routines +of any kind. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
use types_mod, only : i4
 i8
 r4
 r8
 c4
 c8
 digits12
 PI
 DEG2RAD
 RAD2DEG
 SECPERDAY
 MISSING_R4
 MISSING_R8
 MISSING_I
 MISSING_DATA
 metadatalength
 obstypelength
 t_kelvin
 es_alpha
 es_beta
 es_gamma
 gas_constant_v
 gas_constant
 L_over_Rv
 ps0
 earth_radius
 gravity
+ +

NOTES

+ +

+No namelist is used by this module. +

+ + + + + + +


+

PUBLIC COMPONENTS

+
+ + + + + +


+
+integer, parameter :: i4
+integer, parameter :: i8
+integer, parameter :: r4
+integer, parameter :: r8
+integer, parameter :: c4
+integer, parameter :: c8
+integer, parameter :: digits12
+
+ +

Description

+

+These kinds are used when declaring variables, like: +

+real(r8)    :: myvariable
+integer(i4) :: shortint
+
+All DART public interfaces use types on the real values to +ensure they are consistent across various compilers and +compile-time options. The digits12 is generally only used +for reals which require extra precision. +

+Some models are able to run with single precision real values, +which saves both memory when executing and file space when +writing and reading restart files. To accomplish this, the +users edit this file, redefine r8 to equal r4, and then rebuild +all of DART. +

+ + + + + +


+
+real(KIND=R8), parameter :: PI
+real(KIND=R8), parameter :: DEG2RAD
+real(KIND=R8), parameter :: RAD2DEG
+real(KIND=R8), parameter :: SECPERDAY
+
+ +

Description

+

+Some commonly used math constants, defined here for convenience. +

+ + + + +


+
+real(KIND=R4), parameter :: MISSING_R4
+real(KIND=R8), parameter :: MISSING_R8
+integer,       parameter :: MISSING_I
+integer,       parameter :: MISSING_DATA
+
+ +

Description

+

+Numeric constants used in the DART code when a numeric +value is required, but the data is invalid or missing. +These are typically defined as negative and a series +of 8's, so they are distinctive when scanning a list of values. +

+ + + + + +


+
+integer, parameter :: metadatalength
+integer, parameter :: obstypelength
+
+ +

Description

+

+Some common string limits used system-wide by DART code. +The obstypelength is limited by the Fortran-imposed maximum +number of characters in a parameter; the metadatalength was +selected to be long enough to allow descriptive names but +short enough to keep printing to less than a single line. +

+ + + + + +


+
+real(KIND=R8), parameter :: t_kevin
+real(KIND=R8), parameter :: es_alpha
+real(KIND=R8), parameter :: es_beta
+real(KIND=R8), parameter :: es_gamma
+real(KIND=R8), parameter :: gas_constant_v
+real(KIND=R8), parameter :: gas_constant
+real(KIND=R8), parameter :: L_over_Rv
+real(KIND=R8), parameter :: ps0
+real(KIND=R8), parameter :: earth_radius
+real(KIND=R8), parameter :: gravity
+
+ +

Description

+

+A set of geophysical constants, which could be +argued do not belong in a DART-supplied file since +they are quite probably specific to a model or a +particular forward operator. +

+Best case would be if we could engineer the code so +these constants were provided by the model and then +used when compiling the forward operator files. +But given that Fortran use statements +cannot be circular, this poses a problem. +Perhaps we could work out how the obs_def code could +define these constants and then they could be used +by the model code. +For now, they are defined here but it is up to the +model and obs_def code writers whether to use these or not. +

+ + + + + + + + +


+

FILES

+ + + + + + + +


+

REFERENCES

+ + + + + + + +
+

ERROR CODES and CONDITIONS

+
+ + + + + + + + +
RoutineMessageComment
+
+ + + + + + +


+

KNOWN BUGS

+

+none +

+ + + + + + +


+

FUTURE PLANS

+

+none +

+ + + + + + +


+

PRIVATE COMPONENTS

+

+none +

+ + + +
+ + + + + + +
Contact: Jeff Anderson, Tim Hoar
Revision: $Revision$
Source: $URL$
Change Date: $Date$
Change history: try "svn log" or "svn diff"
+
+ + Property changes on: DART/trunk/common/types_mod.html ___________________________________________________________________ Name: svn:mime-type + text/html Name: svn:keywords + Date Revision Author HeadURL Id From nancy at ucar.edu Fri Aug 7 15:44:00 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Fri, 7 Aug 2009 15:44:00 -0600 (MDT) Subject: [Dart-dev] [3992] DART/trunk/models/wrf/model_mod.f90: Glen and I added code to allow reflectivity kinds to be interpolated, Message-ID: <200908072144.n77Li0FE014377@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090807/961cdc23/attachment-0001.html -------------- next part -------------- Modified: DART/trunk/models/wrf/model_mod.f90 =================================================================== --- DART/trunk/models/wrf/model_mod.f90 2009-08-07 21:25:26 UTC (rev 3991) +++ DART/trunk/models/wrf/model_mod.f90 2009-08-07 21:44:00 UTC (rev 3992) @@ -54,6 +54,7 @@ KIND_ICE_NUMBER_CONCENTRATION, KIND_GEOPOTENTIAL_HEIGHT, & KIND_POTENTIAL_TEMPERATURE, KIND_SOIL_MOISTURE, & KIND_VORTEX_LAT, KIND_VORTEX_LON, & + KIND_RADAR_REFLECTIVITY, & KIND_VORTEX_PMIN, KIND_VORTEX_WMAX, & get_raw_obs_kind_index, get_num_raw_obs_kinds, & get_raw_obs_kind_name @@ -229,9 +230,9 @@ logical :: polar logical :: scm - integer :: n_moist +! integer :: n_moist !! obsolete now integer :: domain_size - logical :: surf_obs +! logical :: surf_obs !! obsolete now integer :: vert_coord real(r8), dimension(:), pointer :: znu, dn, dnw, zs real(r8), dimension(:,:), pointer :: mub, latitude, longitude, hgt @@ -245,7 +246,7 @@ ! JPH local variables to hold type indices integer :: type_u, type_v, type_w, type_t, type_qv, type_qr, & - type_qc, type_qg, type_qi, type_qs, type_gz + type_qc, type_qg, type_qi, type_qs, type_gz, type_refl integer :: type_u10, type_v10, type_t2, type_th2, type_q2, & type_ps, type_mu, type_tsk, type_tslb, type_sh2o, type_smois @@ -342,23 +343,6 @@ call fill_dart_kinds_table(wrf_state_variables, in_state_vector) -!--------------------------- -! next block to be obsolete -!--------------------------- -wrf%dom(:)%n_moist = num_moist_vars - -if( num_moist_vars > 7) then - write(*,'(''num_moist_vars = '',i3)')num_moist_vars - call error_handler(E_ERR,'static_init_model', & - 'num_moist_vars is too large.', source, revision,revdate) -endif - -wrf%dom(:)%surf_obs = surf_obs - -!--------------------------- -! end obsolete -!--------------------------- - if ( debug ) then if ( output_state_vector ) then write(*,*)'netcdf file in state vector format' @@ -588,7 +572,7 @@ wrf%dom(id)%type_qv = get_type_ind_from_type_string(id,'QVAPOR') wrf%dom(id)%type_qr = get_type_ind_from_type_string(id,'QRAIN') wrf%dom(id)%type_qc = get_type_ind_from_type_string(id,'QCLOUD') - wrf%dom(id)%type_qg = get_type_ind_from_type_string(id,'QGRAUPEL') + wrf%dom(id)%type_qg = get_type_ind_from_type_string(id,'QGRAUP') wrf%dom(id)%type_qi = get_type_ind_from_type_string(id,'QICE') wrf%dom(id)%type_qs = get_type_ind_from_type_string(id,'QSNOW') wrf%dom(id)%type_u10 = get_type_ind_from_type_string(id,'U10') @@ -602,6 +586,7 @@ wrf%dom(id)%type_tslb = get_type_ind_from_type_string(id,'TSLB') wrf%dom(id)%type_smois = get_type_ind_from_type_string(id,'SMOIS') wrf%dom(id)%type_sh2o = get_type_ind_from_type_string(id,'SH2O') + wrf%dom(id)%type_refl = get_type_ind_from_type_string(id,'REFL_10CM') enddo WRFDomains @@ -1077,6 +1062,13 @@ ! Set a working integer k value -- if (int(zloc) < 1), then k = 1 k = max(1,int(zloc)) + ! The big horizontal interp loop below computes the data values in the level + ! below and above the actual location, and then does a separate vertical + ! interpolation (if the obs is not a 2d surface obs). The two values are + ! stored in fld(1:2). Set them to missing here, and if the code below cannot + ! compute a value, it can just drop out and not have to explicitly set it to + ! missing anymore. + fld(:) = missing_r8 !---------------------------------- ! 1. Horizontal Interpolation @@ -1123,140 +1115,133 @@ ! This is for 3D wind fields -- surface winds later if(.not. surf_var) then - ! xloc and yloc are indices on mass-grid. If we are on a periodic longitude domain, - ! then xloc can range from [1 wes). This means that simply adding 0.5 to xloc has - ! the potential to render xloc_u out of the valid mass-grid index bounds (>wes). - ! To remedy this, we can either do periodicity check on xloc_u value, or we can - ! leave it to a subroutine or function to alter xloc to xloc_u if the observation - ! type requires it. - xloc_u = xloc + 0.5_r8 - yloc_v = yloc + 0.5_r8 + if ( ( wrf%dom(id)%type_u >= 0 ) .and. ( wrf%dom(id)%type_v >= 0 ) ) then - ! Check periodicity if necessary -- but only subtract 'we' because the U-grid - ! cannot have an index < 1 (i.e., U(wes) = U(1) ). - if ( wrf%dom(id)%periodic_x .and. xloc_u > real(wrf%dom(id)%wes,r8) ) & - xloc_u = xloc_u - real(wrf%dom(id)%we,r8) - - ! Get South West gridpoint indices for xloc_u and yloc_v - call toGrid(xloc_u,i_u,dx_u,dxm_u) - call toGrid(yloc_v,j_v,dy_v,dym_v) - - ! Check to make sure retrieved integer gridpoints are in valid range - if ( boundsCheck( i_u, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_u) .and. & - boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_v) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_u) .and. & - boundsCheck( j_v, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_v) .and. & - boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_u) ) then - - ! Need to get grid cell corners surrounding observation location -- with - ! periodicity, this could be non-consecutive (i.e., NOT necessarily i and i+1); - ! Furthermore, it could be different for the U-grid and V-grid. Remember, for - ! now, we are disallowing observations to be located poleward of the 1st and - ! last mass points. - - call getCorners(i_u, j, id, wrf%dom(id)%type_u, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners U rc = ', rc - - call getCorners(i, j_v, id, wrf%dom(id)%type_v, ll_v, ul_v, lr_v, ur_v, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners V rc = ', rc - - ! Now we want to get the corresponding DART state vector indices, and then - ! interpolate horizontally on TWO different vertical levels (so that we can - ! do the vertical interpolation properly later) - do k2 = 1, 2 - - ! Interpolation for the U field - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+k2-1, wrf%dom(id)%type_u) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+k2-1, wrf%dom(id)%type_u) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+k2-1, wrf%dom(id)%type_u) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+k2-1, wrf%dom(id)%type_u) - - ugrid = dym*( dxm_u*x(ill) + dx_u*x(ilr) ) + dy*( dxm_u*x(iul) + dx_u*x(iur) ) - - ! Interpolation for the V field - ill = wrf%dom(id)%dart_ind(ll_v(1), ll_v(2), k+k2-1, wrf%dom(id)%type_v) - iul = wrf%dom(id)%dart_ind(ul_v(1), ul_v(2), k+k2-1, wrf%dom(id)%type_v) - ilr = wrf%dom(id)%dart_ind(lr_v(1), lr_v(2), k+k2-1, wrf%dom(id)%type_v) - iur = wrf%dom(id)%dart_ind(ur_v(1), ur_v(2), k+k2-1, wrf%dom(id)%type_v) + ! xloc and yloc are indices on mass-grid. If we are on a periodic longitude domain, + ! then xloc can range from [1 wes). This means that simply adding 0.5 to xloc has + ! the potential to render xloc_u out of the valid mass-grid index bounds (>wes). + ! To remedy this, we can either do periodicity check on xloc_u value, or we can + ! leave it to a subroutine or function to alter xloc to xloc_u if the observation + ! type requires it. + xloc_u = xloc + 0.5_r8 + yloc_v = yloc + 0.5_r8 + + ! Check periodicity if necessary -- but only subtract 'we' because the U-grid + ! cannot have an index < 1 (i.e., U(wes) = U(1) ). + if ( wrf%dom(id)%periodic_x .and. xloc_u > real(wrf%dom(id)%wes,r8) ) & + xloc_u = xloc_u - real(wrf%dom(id)%we,r8) + + ! Get South West gridpoint indices for xloc_u and yloc_v + call toGrid(xloc_u,i_u,dx_u,dxm_u) + call toGrid(yloc_v,j_v,dy_v,dym_v) + + ! Check to make sure retrieved integer gridpoints are in valid range + if ( boundsCheck( i_u, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_u) .and. & + boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_v) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_u) .and. & + boundsCheck( j_v, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_v) .and. & + boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_u) ) then + + ! Need to get grid cell corners surrounding observation location -- with + ! periodicity, this could be non-consecutive (i.e., NOT necessarily i and i+1); + ! Furthermore, it could be different for the U-grid and V-grid. Remember, for + ! now, we are disallowing observations to be located poleward of the 1st and + ! last mass points. - vgrid = dym_v*( dxm*x(ill) + dx*x(ilr) ) + dy_v*( dxm*x(iul) + dx*x(iur) ) - - ! Certain map projections have wind on grid different than true wind (on map) - ! subroutine gridwind_to_truewind is in module_map_utils.f90 - call gridwind_to_truewind(xyz_loc(1), wrf%dom(id)%proj, ugrid, vgrid, & - utrue, vtrue) + call getCorners(i_u, j, id, wrf%dom(id)%type_u, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners U rc = ', rc - ! Figure out which field was the actual desired observation and store that - ! field as one of the two elements of "fld" (the other element is the other - ! k-level) - if( obs_kind == KIND_U_WIND_COMPONENT) then - fld(k2) = utrue - else ! must want v - fld(k2) = vtrue - end if + call getCorners(i, j_v, id, wrf%dom(id)%type_v, ll_v, ul_v, lr_v, ur_v, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners V rc = ', rc - end do - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - + ! Now we want to get the corresponding DART state vector indices, and then + ! interpolate horizontally on TWO different vertical levels (so that we can + ! do the vertical interpolation properly later) + do k2 = 1, 2 + + ! Interpolation for the U field + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+k2-1, wrf%dom(id)%type_u) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+k2-1, wrf%dom(id)%type_u) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+k2-1, wrf%dom(id)%type_u) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+k2-1, wrf%dom(id)%type_u) + + ugrid = dym*( dxm_u*x(ill) + dx_u*x(ilr) ) + dy*( dxm_u*x(iul) + dx_u*x(iur) ) + + ! Interpolation for the V field + ill = wrf%dom(id)%dart_ind(ll_v(1), ll_v(2), k+k2-1, wrf%dom(id)%type_v) + iul = wrf%dom(id)%dart_ind(ul_v(1), ul_v(2), k+k2-1, wrf%dom(id)%type_v) + ilr = wrf%dom(id)%dart_ind(lr_v(1), lr_v(2), k+k2-1, wrf%dom(id)%type_v) + iur = wrf%dom(id)%dart_ind(ur_v(1), ur_v(2), k+k2-1, wrf%dom(id)%type_v) + + vgrid = dym_v*( dxm*x(ill) + dx*x(ilr) ) + dy_v*( dxm*x(iul) + dx*x(iur) ) + + ! Certain map projections have wind on grid different than true wind (on map) + ! subroutine gridwind_to_truewind is in module_map_utils.f90 + call gridwind_to_truewind(xyz_loc(1), wrf%dom(id)%proj, ugrid, vgrid, & + utrue, vtrue) + + ! Figure out which field was the actual desired observation and store that + ! field as one of the two elements of "fld" (the other element is the other + ! k-level) + if( obs_kind == KIND_U_WIND_COMPONENT) then + fld(k2) = utrue + else ! must want v + fld(k2) = vtrue + end if + + end do + + end if end if - ! This is for surface wind fields -- NOTE: surface winds are on Mass grid (therefore, - ! TYPE_T), not U-grid & V-grid. - ! Also, because surface winds are at a given single vertical level, only fld(1) will - ! be filled. - ! (U10 & V10, which are added to dart_ind if surf_obs = .true.) + ! This is for surface wind fields -- NOTE: surface winds are on Mass grid + ! (therefore, TYPE_T), not U-grid & V-grid. + ! Also, because surface winds are at a given single vertical level, + ! only fld(1) will be filled. else -! JPH -- should test this for doubly periodic -! JPH -- does not pass for SCM config, so just do it below - ! Check to make sure retrieved integer gridpoints are in valid range - if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & - wrf%dom(id)%surf_obs ) .or. wrf%dom(id)%scm ) then + if ( ( wrf%dom(id)%type_u10 >= 0 ) .and. ( wrf%dom(id)%type_v10 >= 0 ) ) then - call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners U10, V10 rc = ', rc - - ! Interpolation for the U10 field - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_u10) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_u10) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_u10) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_u10) - ugrid = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! Interpolation for the V10 field - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_v10) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_v10) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_v10) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_v10) - vgrid = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - call gridwind_to_truewind(xyz_loc(1), wrf%dom(id)%proj, ugrid, vgrid, & - utrue, vtrue) - - ! U10 (U at 10 meters) - if( obs_kind == KIND_U_WIND_COMPONENT) then - fld(1) = utrue - ! V10 (V at 10 meters) - else - fld(1) = vtrue + ! JPH -- should test this for doubly periodic + ! JPH -- does not pass for SCM config, so just do it below + ! Check to make sure retrieved integer gridpoints are in valid range + if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) ) & + .or. wrf%dom(id)%scm ) then + + call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners U10, V10 rc = ', rc + + ! Interpolation for the U10 field + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_u10) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_u10) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_u10) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_u10) + ugrid = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + ! Interpolation for the V10 field + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_v10) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_v10) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_v10) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_v10) + vgrid = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + call gridwind_to_truewind(xyz_loc(1), wrf%dom(id)%proj, ugrid, vgrid, & + utrue, vtrue) + + ! U10 (U at 10 meters) + if( obs_kind == KIND_U_WIND_COMPONENT) then + fld(1) = utrue + ! V10 (V at 10 meters) + else + fld(1) = vtrue + end if + end if - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(1) = missing_r8 - end if end if @@ -1269,90 +1254,84 @@ ! This is for 3D temperature field -- surface temps later if(.not. surf_var) then - ! Check to make sure retrieved integer gridpoints are in valid range - if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_t ) ) then + if ( wrf%dom(id)%type_t >= 0 ) then - call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners T rc = ', rc - - ! Interpolation for T field at level k - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k, wrf%dom(id)%type_t) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k, wrf%dom(id)%type_t) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k, wrf%dom(id)%type_t) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k, wrf%dom(id)%type_t) - - ! In terms of perturbation potential temperature - a1 = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - pres1 = model_pressure_t(ll(1), ll(2), k, id, x) - pres2 = model_pressure_t(lr(1), lr(2), k, id, x) - pres3 = model_pressure_t(ul(1), ul(2), k, id, x) - pres4 = model_pressure_t(ur(1), ur(2), k, id, x) - - ! Pressure at location - pres = dym*( dxm*pres1 + dx*pres2 ) + dy*( dxm*pres3 + dx*pres4 ) - - ! Full sensible temperature field - fld(1) = (ts0 + a1)*(pres/ps0)**kappa - - - ! Interpolation for T field at level k+1 - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+1, wrf%dom(id)%type_t) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+1, wrf%dom(id)%type_t) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+1, wrf%dom(id)%type_t) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+1, wrf%dom(id)%type_t) - - ! In terms of perturbation potential temperature - a1 = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - pres1 = model_pressure_t(ll(1), ll(2), k+1, id, x) - pres2 = model_pressure_t(lr(1), lr(2), k+1, id, x) - pres3 = model_pressure_t(ul(1), ul(2), k+1, id, x) - pres4 = model_pressure_t(ur(1), ur(2), k+1, id, x) - - ! Pressure at location - pres = dym*( dxm*pres1 + dx*pres2 ) + dy*( dxm*pres3 + dx*pres4 ) - - ! Full sensible temperature field - fld(2) = (ts0 + a1)*(pres/ps0)**kappa - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - + ! Check to make sure retrieved integer gridpoints are in valid range + if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_t ) ) then + + call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners T rc = ', rc + + ! Interpolation for T field at level k + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k, wrf%dom(id)%type_t) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k, wrf%dom(id)%type_t) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k, wrf%dom(id)%type_t) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k, wrf%dom(id)%type_t) + + ! In terms of perturbation potential temperature + a1 = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + pres1 = model_pressure_t(ll(1), ll(2), k, id, x) + pres2 = model_pressure_t(lr(1), lr(2), k, id, x) + pres3 = model_pressure_t(ul(1), ul(2), k, id, x) + pres4 = model_pressure_t(ur(1), ur(2), k, id, x) + + ! Pressure at location + pres = dym*( dxm*pres1 + dx*pres2 ) + dy*( dxm*pres3 + dx*pres4 ) + + ! Full sensible temperature field + fld(1) = (ts0 + a1)*(pres/ps0)**kappa + + + ! Interpolation for T field at level k+1 + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+1, wrf%dom(id)%type_t) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+1, wrf%dom(id)%type_t) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+1, wrf%dom(id)%type_t) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+1, wrf%dom(id)%type_t) + + ! In terms of perturbation potential temperature + a1 = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + pres1 = model_pressure_t(ll(1), ll(2), k+1, id, x) + pres2 = model_pressure_t(lr(1), lr(2), k+1, id, x) + pres3 = model_pressure_t(ul(1), ul(2), k+1, id, x) + pres4 = model_pressure_t(ur(1), ur(2), k+1, id, x) + + ! Pressure at location + pres = dym*( dxm*pres1 + dx*pres2 ) + dy*( dxm*pres3 + dx*pres4 ) + + ! Full sensible temperature field + fld(2) = (ts0 + a1)*(pres/ps0)**kappa + + end if end if - ! This is for surface temperature (T2, which is added to dart_ind if surf_obs = .true.) + ! This is for surface temperature (T2) else - ! Check to make sure retrieved integer gridpoints are in valid range - if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & - wrf%dom(id)%surf_obs ) .or. wrf%dom(id)%scm ) then + if ( wrf%dom(id)%type_t2 >= 0 ) then - call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners T2 rc = ', rc - - ! Interpolation for the T2 field - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_t2) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_t2) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_t2) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_t2) - - fld(1) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(1) = missing_r8 - + ! Check to make sure retrieved integer gridpoints are in valid range + if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) ) & + .or. wrf%dom(id)%scm ) then + + call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners T2 rc = ', rc + + ! Interpolation for the T2 field + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_t2) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_t2) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_t2) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_t2) + + fld(1) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + end if end if end if @@ -1367,66 +1346,59 @@ ! This is for 3D potential temperature field -- surface pot temps later if(.not. surf_var) then - ! Check to make sure retrieved integer gridpoints are in valid range - if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_t ) ) then - - call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners Theta rc = ', rc - - ! Interpolation for Theta field at level k - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k, wrf%dom(id)%type_t) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k, wrf%dom(id)%type_t) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k, wrf%dom(id)%type_t) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k, wrf%dom(id)%type_t) - - fld(1) = ts0 + dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! Interpolation for Theta field at level k+1 - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+1, wrf%dom(id)%type_t) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+1, wrf%dom(id)%type_t) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+1, wrf%dom(id)%type_t) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+1, wrf%dom(id)%type_t) - - fld(2) = ts0 + dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - + if ( wrf%dom(id)%type_t >= 0 ) then + + ! Check to make sure retrieved integer gridpoints are in valid range + if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_t ) ) then + + call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners Theta rc = ', rc + + ! Interpolation for Theta field at level k + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k, wrf%dom(id)%type_t) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k, wrf%dom(id)%type_t) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k, wrf%dom(id)%type_t) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k, wrf%dom(id)%type_t) + + fld(1) = ts0 + dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + ! Interpolation for Theta field at level k+1 + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+1, wrf%dom(id)%type_t) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+1, wrf%dom(id)%type_t) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+1, wrf%dom(id)%type_t) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+1, wrf%dom(id)%type_t) + + fld(2) = ts0 + dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + end if end if - ! This is for surface potential temperature (TH2, which is added to dart_ind - ! if surf_obs = .true.) + ! This is for surface potential temperature (TH2) else - ! Check to make sure retrieved integer gridpoints are in valid range - if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & - wrf%dom(id)%surf_obs ) .or. wrf%dom(id)%scm ) then + if ( wrf%dom(id)%type_th2 >= 0 ) then - call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners TH2 rc = ', rc - - ! Interpolation for the TH2 field - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_th2) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_th2) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_th2) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_th2) - - fld(1) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(1) = missing_r8 - + ! Check to make sure retrieved integer gridpoints are in valid range + if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) ) & + .or. wrf%dom(id)%scm ) then + + call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners TH2 rc = ', rc + + ! Interpolation for the TH2 field + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), 1, wrf%dom(id)%type_th2) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), 1, wrf%dom(id)%type_th2) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), 1, wrf%dom(id)%type_th2) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), 1, wrf%dom(id)%type_th2) + + fld(1) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + end if end if end if @@ -1470,12 +1442,6 @@ fld(2) = dym*( dxm*rho1 + dx*rho2 ) + dy*( dxm*rho3 + dx*rho4 ) - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - end if @@ -1484,41 +1450,38 @@ elseif ( obs_kind == KIND_VERTICAL_VELOCITY ) then - ! Adjust zloc for staggered ZNW grid (or W-grid, as compared to ZNU or M-grid) - zloc = zloc + 0.5_r8 - k = max(1,int(zloc)) - - ! Check to make sure retrieved integer gridpoints are in valid range - if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_w ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_w ) .and. & - boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_w ) ) then + if ( wrf%dom(id)%type_w >= 0 ) then - call getCorners(i, j, id, wrf%dom(id)%type_w, ll, ul, lr, ur, rc ) - if ( rc .ne. 0 ) & - print*, 'model_mod.f90 :: model_interpolate :: getCorners W rc = ', rc + ! Adjust zloc for staggered ZNW grid (or W-grid, as compared to ZNU or M-grid) + zloc = zloc + 0.5_r8 + k = max(1,int(zloc)) - ! Interpolation for W field at level k - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k, wrf%dom(id)%type_w) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k, wrf%dom(id)%type_w) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k, wrf%dom(id)%type_w) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k, wrf%dom(id)%type_w) + ! Check to make sure retrieved integer gridpoints are in valid range + if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_w ) .and. & + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_w ) .and. & + boundsCheck( k, .false., id, dim=3, type=wrf%dom(id)%type_w ) ) then + + call getCorners(i, j, id, wrf%dom(id)%type_w, ll, ul, lr, ur, rc ) + if ( rc .ne. 0 ) & + print*, 'model_mod.f90 :: model_interpolate :: getCorners W rc = ', rc + + ! Interpolation for W field at level k + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k, wrf%dom(id)%type_w) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k, wrf%dom(id)%type_w) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k, wrf%dom(id)%type_w) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k, wrf%dom(id)%type_w) + + fld(1) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) + + ! Interpolation for W field at level k+1 + ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+1, wrf%dom(id)%type_w) + iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+1, wrf%dom(id)%type_w) + ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+1, wrf%dom(id)%type_w) + iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+1, wrf%dom(id)%type_w) + + fld(2) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - fld(1) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! Interpolation for W field at level k+1 - ill = wrf%dom(id)%dart_ind(ll(1), ll(2), k+1, wrf%dom(id)%type_w) - iul = wrf%dom(id)%dart_ind(ul(1), ul(2), k+1, wrf%dom(id)%type_w) - ilr = wrf%dom(id)%dart_ind(lr(1), lr(2), k+1, wrf%dom(id)%type_w) - iur = wrf%dom(id)%dart_ind(ur(1), ur(2), k+1, wrf%dom(id)%type_w) - - fld(2) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - + end if end if @@ -1528,12 +1491,13 @@ ! Convert water vapor mixing ratio to specific humidity: else if( obs_kind == KIND_SPECIFIC_HUMIDITY ) then - ! First confirm that vapor mixing ratio is in the DART state vector - if ( wrf%dom(id)%n_moist >= 1 ) then - - ! This is for 3D specific humidity -- surface spec humidity later - if(.not. surf_var) then + ! This is for 3D specific humidity -- surface spec humidity later + if(.not. surf_var) then + ! First confirm that vapor mixing ratio is in the DART state vector + !if ( wrf%dom(id)%n_moist >= 1 ) then + if ( wrf%dom(id)%type_qv >= 0 ) then + ! Check to make sure retrieved integer gridpoints are in valid range if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & @@ -1561,22 +1525,19 @@ a1 = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) fld(2) = a1 /(1.0_r8 + a1) - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - end if + end if - ! This is for surface specific humidity (calculated from Q2, which is added to - ! dart_ind if surf_obs = .true.) - else + ! This is for surface specific humidity (calculated from Q2) + else + ! confirm that field is in the DART state vector + if ( wrf%dom(id)%type_q2 >= 0 ) then + ! Check to make sure retrieved integer gridpoints are in valid range if ( ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & - boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & - wrf%dom(id)%surf_obs ) .or. wrf%dom(id)%scm ) then + boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) ) & + .or. wrf%dom(id)%scm ) then call getCorners(i, j, id, wrf%dom(id)%type_t, ll, ul, lr, ur, rc ) if ( rc .ne. 0 ) & @@ -1591,20 +1552,8 @@ a1 = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) fld(1) = a1 /(1.0_r8 + a1) - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(1) = missing_r8 - end if end if - - ! If not in the state vector, then set to 0 (?) - else - - fld(:) = 0.0_r8 - end if @@ -1612,12 +1561,13 @@ ! 1.g Vapor Mixing Ratio (QV, Q2) else if( obs_kind == KIND_VAPOR_MIXING_RATIO ) then - ! First confirm that vapor mixing ratio is in the DART state vector - if ( wrf%dom(id)%n_moist >= 1 ) then - - ! This is for 3D vapor mixing ratio -- surface QV later - if(.not. surf_var) then + ! This is for 3D vapor mixing ratio -- surface QV later + if(.not. surf_var) then + ! First confirm that vapor mixing ratio is in the DART state vector + !if ( wrf%dom(id)%n_moist >= 1 ) then + if ( wrf%dom(id)%type_qv >= 0 ) then + ! Check to make sure retrieved integer gridpoints are in valid range if ( boundsCheck( i, wrf%dom(id)%periodic_x, id, dim=1, type=wrf%dom(id)%type_t ) .and. & boundsCheck( j, wrf%dom(id)%polar, id, dim=2, type=wrf%dom(id)%type_t ) .and. & @@ -1643,21 +1593,19 @@ fld(2) = dym*( dxm*x(ill) + dx*x(ilr) ) + dy*( dxm*x(iul) + dx*x(iur) ) - ! If the boundsCheck functions return an unsatisfactory integer index, then set - ! fld as missing data - else - - fld(:) = missing_r8 - end if + end if - ! This is for surface QV (Q2, which is added to dart_ind if surf_obs = .true.) - else @@ Diff output truncated at 40000 characters. @@ From nancy at ucar.edu Mon Aug 10 15:33:28 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Mon, 10 Aug 2009 15:33:28 -0600 (MDT) Subject: [Dart-dev] [3997] DART/trunk/observations/gps: Updated COSMIC GPS RO converter. Message-ID: <200908102133.n7ALXSQ7013039@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090810/ae51754c/attachment-0001.html -------------- next part -------------- Modified: DART/trunk/observations/gps/convert_cosmic_gps_cdf.f90 =================================================================== --- DART/trunk/observations/gps/convert_cosmic_gps_cdf.f90 2009-08-10 19:13:07 UTC (rev 3996) +++ DART/trunk/observations/gps/convert_cosmic_gps_cdf.f90 2009-08-10 21:33:27 UTC (rev 3997) @@ -1,3 +1,8 @@ +! Data Assimilation Research Testbed -- DART +! Copyright 2004-2008, Data Assimilation Research Section +! University Corporation for Atmospheric Research +! Licensed under the GPL -- www.gpl.org/licenses/gpl.html + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! convert_cosmic_gps_cdf - program that reads a COSMIC GPS observation @@ -7,70 +12,87 @@ ! created June 2008 Ryan Torn, NCAR/MMM ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + program convert_cosmic_gps_cdf use types_mod, only : r8 -use time_manager_mod, only : time_type, set_calendar_type, GREGORIAN, set_time, & - increment_time, get_time, set_date, operator(-) -use utilities_mod, only : initialize_utilities, find_namelist_in_file, & - check_namelist_read, nmlfileunit, do_output +use time_manager_mod, only : time_type, set_calendar_type, GREGORIAN, set_time,& + increment_time, get_time, set_date, operator(-), & + print_date +use utilities_mod, only : initialize_utilities, find_namelist_in_file, & + check_namelist_read, nmlfileunit, do_output, & + get_next_filename, error_handler, E_ERR, E_MSG, & + nc_check, find_textfile_dims use location_mod, only : VERTISHEIGHT, set_location -use obs_sequence_mod, only : obs_sequence_type, obs_type, read_obs_seq, & - static_init_obs_sequence, init_obs, write_obs_seq, & - append_obs_to_seq, init_obs_sequence, get_num_obs, & - set_copy_meta_data, set_qc_meta_data, set_qc, & +use obs_sequence_mod, only : obs_sequence_type, obs_type, read_obs_seq, & + static_init_obs_sequence, init_obs, destroy_obs, & + write_obs_seq, init_obs_sequence, get_num_obs, & + insert_obs_in_seq, destroy_obs_sequence, & + set_copy_meta_data, set_qc_meta_data, set_qc, & set_obs_values, set_obs_def, insert_obs_in_seq use obs_def_mod, only : obs_def_type, set_obs_def_time, set_obs_def_kind, & - set_obs_def_error_variance, set_obs_def_location, & + set_obs_def_error_variance, set_obs_def_location, & set_obs_def_key use obs_def_gps_mod, only : set_gpsro_ref use obs_kind_mod, only : GPSRO_REFRACTIVITY + use netcdf implicit none -character(len=19), parameter :: gpsro_netcdf_file = 'cosmic_gps_input.nc' -character(len=129), parameter :: gpsro_out_file = 'obs_seq.gpsro' +! version controlled file description for error handling, do not edit +character(len=128), parameter :: & + source = "$URL$", & + revision = "$Revision$", & + revdate = "$Date$" + integer, parameter :: num_copies = 1, & ! number of copies in sequence num_qc = 1 ! number of QC entries -character (len=129) :: meta_data +character (len=129) :: meta_data, msgstring, next_infile character (len=80) :: name character (len=19) :: datestr character (len=6) :: subset -integer :: rcode, ncid, varid, nlevels, k, & - aday, asec, dday, dsec, oday, osec, & - iyear, imonth, iday, ihour, imin, isec, & - glat, glon, zloc, obs_num, io, iunit, nobs -logical :: file_exist -real(r8) :: hght_miss, refr_miss, azim_miss, oerr, & - obs_window, qc, lato, lono, hghto, refro, azimo, wght, nx, ny, & - nz, ds, htop, rfict, obsval, phs, obs_val(1), qc_val(1), & - ref_obserr_kuo_percent, excess_obserr_percent +integer :: rcode, ncid, varid, nlevels, k, nfiles, num_new_obs, & + aday, asec, dday, dsec, oday, osec, & + iyear, imonth, iday, ihour, imin, isec, & + glat, glon, zloc, obs_num, io, iunit, nobs, filenum, dummy +logical :: file_exist, first_obs, did_obs, from_list = .false. +real(r8) :: hght_miss, refr_miss, azim_miss, oerr, & + qc, lato, lono, hghto, refro, azimo, wght, nx, ny, & + nz, ds, htop, rfict, obsval, phs, obs_val(1), qc_val(1) real(r8), allocatable :: lat(:), lon(:), hght(:), refr(:), azim(:), & hghtp(:), refrp(:) type(obs_def_type) :: obs_def type(obs_sequence_type) :: obs_seq -type(obs_type) :: obs +type(obs_type) :: obs, prev_obs type(time_type) :: time_obs, time_anal !------------------------------------------------------------------------ ! Declare namelist parameters !------------------------------------------------------------------------ -integer, parameter :: nmaxlevels = 200 ! maximum number of observation levels +integer, parameter :: nmaxlevels = 200 ! max number of observation levels logical :: local_operator = .true. +logical :: overwrite_time = .false. real(r8) :: obs_levels(nmaxlevels) = -1.0_r8 +real(r8) :: obs_window = 12.0 ! accept obs within +/- hours from anal time real(r8) :: ray_ds = 5000.0_r8 ! delta stepsize (m) along ray, nonlocal op real(r8) :: ray_htop = 15000.0_r8 ! max height (m) for nonlocal op +character(len=128) :: gpsro_netcdf_file = 'cosmic_gps_input.nc' +character(len=128) :: gpsro_netcdf_filelist = 'cosmic_gps_input_list' +character(len=128) :: gpsro_out_file = 'obs_seq.gpsro' namelist /convert_cosmic_gps_nml/ obs_levels, local_operator, obs_window, & - ray_ds, ray_htop + ray_ds, ray_htop, gpsro_netcdf_file, & + gpsro_netcdf_filelist, gpsro_out_file +! could add overwrite_time to namelist + ! initialize some values obs_num = 1 qc = 0.0_r8 @@ -96,6 +118,7 @@ ! Record the namelist values used for the run if (do_output()) write(nmlfileunit, nml=convert_cosmic_gps_nml) +! namelist checks for sanity ! count observation levels, make sure observation levels increase from 0 nlevels = 0 @@ -105,211 +128,271 @@ end do do k = 2, nlevels if ( obs_levels(k-1) >= obs_levels(k) ) then - write(6,*) 'Observation levels should increase' - stop + call error_handler(E_ERR, 'convert_cosmic_gps_cdf', & + 'Observation levels should increase', & + source, revision, revdate) end if end do ! should error check the window some if (obs_window <= 0.0_r8 .or. obs_window > 24.0_r8) then - write(6,*) 'Bad value for obs_window (hours)' - stop + call error_handler(E_ERR, 'convert_cosmic_gps_cdf', & + 'Bad value for obs_window (hours)', & + source, revision, revdate) else obs_window = obs_window * 3600.0_r8 endif -! open the occultation profile, check if it is within the window -rcode = nf90_open(gpsro_netcdf_file, nf90_nowrite, ncid) -call check( nf90_get_att(ncid, nf90_global, 'year', iyear) ) -call check( nf90_get_att(ncid, nf90_global, 'month', imonth) ) -call check( nf90_get_att(ncid, nf90_global, 'day', iday) ) -call check( nf90_get_att(ncid, nf90_global, 'hour', ihour) ) -call check( nf90_get_att(ncid, nf90_global, 'minute', imin) ) -call check( nf90_get_att(ncid, nf90_global, 'second', isec) ) -time_obs = set_date(iyear, imonth, iday, ihour, imin, isec) -call get_time(time_obs, osec, oday) +! cannot have both a single filename and a list; the namelist must +! shut one off. +if (gpsro_netcdf_file /= '' .and. gpsro_netcdf_filelist /= '') then + call error_handler(E_ERR, 'convert_cosmic_gps_cdf', & + 'One of gpsro_netcdf_file or filelist must be NULL', & + source, revision, revdate) +endif +if (gpsro_netcdf_filelist /= '') from_list = .true. -! time1-time2 is always positive no matter the relative magnitudes -call get_time(time_anal-time_obs,dsec,dday) -if ( real(dsec+dday*86400) > obs_window ) then - write(6,*) 'Observation is outside window' - stop -end if +! need to know a reasonable max number of obs that could be added here. +if (from_list) then + call find_textfile_dims(gpsro_netcdf_filelist, nfiles, dummy) + num_new_obs = nlevels * nfiles +else + num_new_obs = nlevels +endif -call check( nf90_inq_dimid(ncid, "MSL_alt", varid) ) -call check( nf90_inquire_dimension(ncid, varid, name, nobs) ) - -call check( nf90_get_att(ncid, nf90_global, 'lon', glon) ) -call check( nf90_get_att(ncid, nf90_global, 'lat', glat) ) -call check( nf90_get_att(ncid, nf90_global, 'rfict', rfict) ) -rfict = rfict * 1000.0_r8 - -allocate( lat(nobs)) ; allocate( lon(nobs)) -allocate(hght(nobs)) ; allocate(refr(nobs)) -allocate(azim(nobs)) - -! read the latitude array -call check( nf90_inq_varid(ncid, "Lat", varid) ) -call check( nf90_get_var(ncid, varid, lat) ) - -! read the latitude array -call check( nf90_inq_varid(ncid, "Lon", varid) ) -call check( nf90_get_var(ncid, varid, lon) ) - -! read the altitude array -call check( nf90_inq_varid(ncid, "MSL_alt", varid) ) -call check( nf90_get_var(ncid, varid, hght) ) -call check( nf90_get_att(ncid, varid, '_FillValue', hght_miss) ) - -! read the refractivity -call check( nf90_inq_varid(ncid, "Ref", varid) ) -call check( nf90_get_var(ncid, varid, refr) ) -call check( nf90_get_att(ncid, varid, '_FillValue', refr_miss) ) - -! read the dew-point temperature array -call check( nf90_inq_varid(ncid, "Azim", varid) ) -call check( nf90_get_var(ncid, varid, azim) ) -call check( nf90_get_att(ncid, varid, '_FillValue', azim_miss) ) - -call check( nf90_close(ncid) ) - ! either read existing obs_seq or create a new one call static_init_obs_sequence() call init_obs(obs, num_copies, num_qc) +call init_obs(prev_obs, num_copies, num_qc) inquire(file=gpsro_out_file, exist=file_exist) if ( file_exist ) then print *, "found existing obs_seq file, appending to ", trim(gpsro_out_file) - call read_obs_seq(gpsro_out_file, 0, 0, nlevels, obs_seq) + call read_obs_seq(gpsro_out_file, 0, 0, num_new_obs, obs_seq) else print *, "no existing obs_seq file, creating ", trim(gpsro_out_file) -print *, "max entries = ", nlevels - call init_obs_sequence(obs_seq, num_copies, num_qc, nlevels) +print *, "max entries = ", num_new_obs + call init_obs_sequence(obs_seq, num_copies, num_qc, num_new_obs) do k = 1, num_copies - meta_data = 'NCEP BUFR observation' + meta_data = 'COSMIC GPS observation' call set_copy_meta_data(obs_seq, k, meta_data) end do do k = 1, num_qc - meta_data = 'NCEP QC index' + meta_data = 'COSMIC QC' call set_qc_meta_data(obs_seq, k, meta_data) end do end if allocate(hghtp(nlevels)) ; allocate(refrp(nlevels)) -obsloop: do k = 1, nlevels +did_obs = .false. - call interp_height_wght(hght, obs_levels(k), nobs, zloc, wght) - if ( zloc < 1 ) cycle obsloop - hghtp(nlevels-k+1) = obs_levels(k) * 1000.0_r8 - refrp(nlevels-k+1) = exp( wght * log(refr(zloc)) + & - (1.0_r8 - wght) * log(refr(zloc+1)) ) * 1.0e-6_r8 +! main loop that does either a single file or a list of files -end do obsloop +filenum = 1 +fileloop: do ! until out of files -obsloop2: do k = 1, nlevels + ! get the single name, or the next name from a list + if (from_list) then + next_infile = get_next_filename(gpsro_netcdf_filelist, filenum) + else + next_infile = gpsro_netcdf_file + if (filenum > 1) next_infile = '' + endif + if (next_infile == '') exit fileloop + + ! open the occultation profile, check if it is within the window + call nc_check( nf90_open(next_infile, nf90_nowrite, ncid), 'file open', next_infile) + call nc_check( nf90_get_att(ncid,nf90_global,'year', iyear) ,'get_att year') + call nc_check( nf90_get_att(ncid,nf90_global,'month', imonth),'get_att month') + call nc_check( nf90_get_att(ncid,nf90_global,'day', iday) ,'get_att day') + call nc_check( nf90_get_att(ncid,nf90_global,'hour', ihour) ,'get_att hour') + call nc_check( nf90_get_att(ncid,nf90_global,'minute',imin) ,'get_att minute') + call nc_check( nf90_get_att(ncid,nf90_global,'second',isec) ,'get_att second') + + time_obs = set_date(iyear, imonth, iday, ihour, imin, isec) + call get_time(time_obs, osec, oday) + + ! time1-time2 is always positive no matter the relative magnitudes + call get_time(time_anal-time_obs,dsec,dday) + if ( real(dsec+dday*86400) > obs_window ) then + call print_date(time_obs, 'observation: ') + call print_date(time_anal, 'window center: ') + write(msgstring, *) 'Window width (hours): ', obs_window / 3600.0_r8 + call error_handler(E_MSG, 'convert_cosmic_gps_cdf', & + msgstring, source, revision, revdate) + call error_handler(E_ERR, 'convert_cosmic_gps_cdf', & + 'Observation is outside window', & + source, revision, revdate) + end if + + call nc_check( nf90_inq_dimid(ncid, "MSL_alt", varid), 'inq dimid MSL_alt') + call nc_check( nf90_inquire_dimension(ncid, varid, name, nobs), 'inq dim MSL_alt') + + call nc_check( nf90_get_att(ncid,nf90_global,'lon', glon) ,'get_att lon' ) + call nc_check( nf90_get_att(ncid,nf90_global,'lat', glat) ,'get_att lat' ) + call nc_check( nf90_get_att(ncid,nf90_global,'rfict',rfict),'get_att rfict') + rfict = rfict * 1000.0_r8 + + allocate( lat(nobs)) ; allocate( lon(nobs)) + allocate(hght(nobs)) ; allocate(refr(nobs)) + allocate(azim(nobs)) + + ! read the latitude array + call nc_check( nf90_inq_varid(ncid, "Lat", varid) ,'inq varid Lat') + call nc_check( nf90_get_var(ncid, varid, lat) ,'get var Lat') + + ! read the latitude array + call nc_check( nf90_inq_varid(ncid, "Lon", varid) ,'inq varid Lon') + call nc_check( nf90_get_var(ncid, varid, lon) ,'get var Lon') + + ! read the altitude array + call nc_check( nf90_inq_varid(ncid, "MSL_alt", varid) ,'inq varid MSL_alt') + call nc_check( nf90_get_var(ncid, varid, hght) ,'get_var MSL_alt') + call nc_check( nf90_get_att(ncid, varid, '_FillValue', hght_miss) ,'get_att _FillValue MSL_alt') + + ! read the refractivity + call nc_check( nf90_inq_varid(ncid, "Ref", varid) ,'inq varid Ref') + call nc_check( nf90_get_var(ncid, varid, refr) ,'get var Ref') + call nc_check( nf90_get_att(ncid, varid, '_FillValue', refr_miss) ,'get_att _FillValue Ref') + + ! read the dew-point temperature array + call nc_check( nf90_inq_varid(ncid, "Azim", varid) ,'inq varid Azim') + call nc_check( nf90_get_var(ncid, varid, azim) ,'get var Azim') + call nc_check( nf90_get_att(ncid, varid, '_FillValue', azim_miss) ,'get_att _FillValue Azim') + + call nc_check( nf90_close(ncid) , 'close file') + + obsloop: do k = 1, nlevels + + call interp_height_wght(hght, obs_levels(k), nobs, zloc, wght) + if ( zloc < 1 ) cycle obsloop + hghtp(nlevels-k+1) = obs_levels(k) * 1000.0_r8 + refrp(nlevels-k+1) = exp( wght * log(refr(zloc)) + & + (1.0_r8 - wght) * log(refr(zloc+1)) ) * 1.0e-6_r8 + + end do obsloop + + first_obs = .true. + + obsloop2: do k = 1, nlevels + + call interp_height_wght(hght, obs_levels(k), nobs, zloc, wght) + if ( zloc < 1 ) cycle obsloop2 + + lato = wght * lat(zloc) + (1.0_r8 - wght) * lat(zloc+1) + lono = wght * lon(zloc) + (1.0_r8 - wght) * lon(zloc+1) + if ( lono < 0.0_r8 ) lono = lono + 360.0_r8 + hghto = wght * hght(zloc) + (1.0_r8 - wght) * hght(zloc+1) + hghto = hghto * 1000.0_r8 + refro = wght * refr(zloc) + (1.0_r8 - wght) * refr(zloc+1) + azimo = wght * azim(zloc) + (1.0_r8 - wght) * azim(zloc+1) + + if ( local_operator ) then + + nx = 0.0_r8 + ny = 0.0_r8 + nz = 0.0_r8 + ray_ds = 0.0_r8 + ray_htop = 0.0_r8 + rfict = 0.0_r8 + + obsval = refro + oerr = 0.01_r8 * ref_obserr_kuo_percent(hghto * 0.001_r8) * obsval + subset = 'GPSREF' + + else + + ! compute tangent unit vector + call tanvec01(lono, lato, azimo, nx, ny, nz) + + ! compute the excess phase + call excess(refrp, hghtp, lono, lato, hghto, nx, & + ny, nz, rfict, ray_ds, ray_htop, phs, nlevels) + + ! if too high, phs will return as 0. cycle loop here. + if (phs <= 0) cycle obsloop2 + + obsval = phs + oerr = 0.01_r8 * excess_obserr_percent(hghto * 0.001_r8) * obsval + !print *, 'hghto,obsval,perc,err=', hghto, obsval, & + ! excess_obserr_percent(hghto * 0.001_r8), oerr + subset = 'GPSEXC' + + end if + + call set_gpsro_ref(obs_num, nx, ny, nz, rfict, ray_ds, ray_htop, subset) + call set_obs_def_location(obs_def,set_location(lono,lato,hghto,VERTISHEIGHT)) + call set_obs_def_kind(obs_def, GPSRO_REFRACTIVITY) + if (overwrite_time) then ! generally do not want to do this here. + call set_obs_def_time(obs_def, set_time(asec, aday)) + else + call set_obs_def_time(obs_def, set_time(osec, oday)) + endif + call set_obs_def_error_variance(obs_def, oerr * oerr) + call set_obs_def_key(obs_def, obs_num) + call set_obs_def(obs, obs_def) + + obs_val(1) = obsval + call set_obs_values(obs, obs_val) + qc_val(1) = qc + call set_qc(obs, qc_val) + + ! first one, insert with no prev. otherwise, since all times will be the + ! same for this column, insert with the prev obs as the starting point. + ! (this code used to call append, but calling insert makes it work even if + ! the input files are processed out of strict time order, which one message + ! i got seemed to indicate was happening...) + if (first_obs) then + call insert_obs_in_seq(obs_seq, obs) + first_obs = .false. + !print *, 'inserting first obs' + else + call insert_obs_in_seq(obs_seq, obs, prev_obs) + !print *, 'inserting other obs' + endif + obs_num = obs_num+1 + prev_obs = obs - call interp_height_wght(hght, obs_levels(k), nobs, zloc, wght) - if ( zloc < 1 ) cycle obsloop2 + if (.not. did_obs) did_obs = .true. + + end do obsloop2 - lato = wght * lat(zloc) + (1.0_r8 - wght) * lat(zloc+1) - lono = wght * lon(zloc) + (1.0_r8 - wght) * lon(zloc+1) - if ( lono < 0.0_r8 ) lono = lono + 360.0_r8 - hghto = wght * hght(zloc) + (1.0_r8 - wght) * hght(zloc+1) - hghto = hghto * 1000.0_r8 - refro = wght * refr(zloc) + (1.0_r8 - wght) * refr(zloc+1) - azimo = wght * azim(zloc) + (1.0_r8 - wght) * azim(zloc+1) + ! clean up and loop if there is another input file + deallocate( lat, lon, hght, refr, azim ) - if ( local_operator ) then + filenum = filenum + 1 - nx = 0.0_r8 - ny = 0.0_r8 - nz = 0.0_r8 - ds = 0.0_r8 - htop = 0.0_r8 - rfict = 0.0_r8 +end do fileloop - obsval = refro - oerr = 0.01_r8 * ref_obserr_kuo_percent(hghto * 0.001_r8) * obsval - subset = 'GPSREF' +! done with main loop. if we added any obs to the sequence, write it out. +if (did_obs) then +!print *, 'ready to write, nobs = ', get_num_obs(obs_seq) + if (get_num_obs(obs_seq) > 0) & + call write_obs_seq(obs_seq, gpsro_out_file) - else + ! minor stab at cleanup, in the off chance this will someday get turned + ! into a subroutine in a module. probably not all that needs to be done, + ! but a start. +!print *, 'calling destroy_obs' + call destroy_obs(obs) + call destroy_obs(prev_obs) +print *, 'skipping destroy_seq' + ! get core dumps here, not sure why? + !if (get_num_obs(obs_seq) > 0) call destroy_obs_sequence(obs_seq) +endif - ! compute tangent unit vector - call tanvec01(lono, lato, azimo, nx, ny, nz) +! END OF MAIN ROUTINE - ! compute the excess phase - call excess(refrp, hghtp, lono, lato, hghto, nx, & - ny, nz, rfict, ray_ds, ray_htop, phs, nlevels) +contains - ! if too high, phs will return as 0. cycle loop here. - if (phs <= 0) cycle +! local subroutines/functions follow - obsval = phs - oerr = 0.01_r8 * excess_obserr_percent(hghto * 0.001_r8) * obsval -!print *, 'hghto,obsval,perc,err=', hghto, obsval, & -! excess_obserr_percent(hghto * 0.001_r8), oerr - subset = 'GPSEXC' - - end if - - call set_gpsro_ref(obs_num, nx, ny, nz, rfict, ray_ds, ray_htop, subset) - call set_obs_def_location(obs_def,set_location(lono,lato,hghto,VERTISHEIGHT)) - call set_obs_def_kind(obs_def, GPSRO_REFRACTIVITY) - call set_obs_def_time(obs_def, set_time(osec, oday)) - call set_obs_def_error_variance(obs_def, oerr * oerr) - call set_obs_def_key(obs_def, obs_num) - call set_obs_def(obs, obs_def) - - obs_val(1) = obsval - call set_obs_values(obs, obs_val) - qc_val(1) = qc - call set_qc(obs, qc_val) - - ! if this gives an error, use insert instead. slower, but times do not - ! need to be monotonically increasing. - call append_obs_to_seq(obs_seq, obs) - ! this will speed up if we keep track of the previous time, and pass in an - ! existing obs to insert after. - !call insert_obs_in_seq(obs_seq, obs) - obs_num = obs_num+1 - -end do obsloop2 - -if ( get_num_obs(obs_seq) > 0 ) call write_obs_seq(obs_seq, gpsro_out_file) - -stop -end - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! -! check - subroutine that checks the flag from a netCDF function. If -! there is an error, the message is displayed. -! -! istatus - netCDF output flag -! -! created Dec. 2007 Ryan Torn, NCAR/MMM -! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -subroutine check( istatus ) - -use netcdf - -implicit none - -integer, intent (in) :: istatus - -if(istatus /= nf90_noerr) then - print*,'Netcdf error: ',trim(nf90_strerror(istatus)) - stop -end if -end subroutine check - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! ! excess - subroutine that computes the excess phase based on the ! method of Sergey et al. (2004), eq. 1 and 2 ! @@ -815,3 +898,5 @@ return end subroutine vprod + +end program Modified: DART/trunk/observations/gps/gps.html =================================================================== --- DART/trunk/observations/gps/gps.html 2009-08-10 19:13:07 UTC (rev 3996) +++ DART/trunk/observations/gps/gps.html 2009-08-10 21:33:27 UTC (rev 3997) @@ -35,6 +35,8 @@ OVERVIEW / DATA SOURCES / PROGRAMS / +MODULES USES / +NAMELIST / KNOWN BUGS / FUTURE PLANS @@ -52,7 +54,7 @@

GPS Radio Occultation data is being returned from a series of satellites as part of the -Cosmic +COSMIC project. The programs in this directory help to extract the data from the distribution files and put them into @@ -80,16 +82,24 @@

Data from -Cosmic +COSMIC is available by signing up on the data access web page. It is delivered in netCDF file format. +The files we use as input to these conversion programs are +the Level 2 data, Atmospheric Profiles (filenames include +the string 'atmPrf').

+Currently each vertical profile is stored in a separate file, +and there are between 1000-2000 profiles/day, so converting a day's +worth of observations involves downloading many individual files. +There are plans in place to bundle these profiles together in +a tar file to make it easier to download the raw data.

@@ -99,26 +109,176 @@

PROGRAMS

The data is distributed in netCDF -file format. -Both Fortran and -Matlab -programs are provided here to read the data and output -DART obs_seq file formats. +file format. DART requires all observations to be in a proprietary +format often called DART "obs_seq" format. +The files in this directory, a combination +of C shell scripts and a Fortran source executable, +do this data conversion.

+Optional namelist interface + &convert_cosmic_gps_nml +may be read from file input.nml. +

+

+The work directory contains several scripts, including one which downloads +the raw data files a day at a time (cosmic_download.csh), and one +which executes the conversion program (convert_script.csh). These +scripts make 6 hour files by default, but have options for other +times. The input files are downloaded a day at a time. Be aware +that each profile is stored in a separate netcdf file, and there +are between 1000-2000 files/day, so the download process can be +lengthy. You probably want to download as a separate preprocess step +and do not use the options to automatically delete the input files. +Keep the files around until you are sure you are satisified with the +output files and then delete them by hand. +

+

+The conversion executable, convert_cosmic_gps_cdf, reads the namelist +from the file 'input.nml', but also reads an analysis time from the +terminal or the standard input unit. This makes it simpler to convert +multiple files without editing the namelist. The program prompts for +the time string with the required time format, +yyyy-mm-dd_hh:mm:ss .

- + + +
+

MODULES USED

+
+types_mod
+time_manager_mod
+utilities_mod
+location_mod
+obs_sequence_mod
+obs_def_mod
+obs_def_gps_mod
+obs_kind_mod
+netcdf
+
+ + +


+

NAMELIST

+

We adhere to the F90 standard of starting a namelist with an ampersand + '&' and terminating with a slash '/'. +

+ namelist / convert_cosmic_gps_nml / 
+    obs_levels, local_operator, obs_window, &
+    ray_ds, ray_htop, gpsro_netcdf_file,    &
+    gpsro_netcdf_filelist, gpsro_out_file
+ 
+

Discussion

+

This namelist is read in a file called input.nml +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Contents Type Description
obs_levelsinteger(200)A series of heights, in kilometers, where observations + from this profile should be interpolated. (Note that + the other distances and heights in the namelist are + specified in meters.) The values should be listed in + increasing height order. + Default: none
local_operatorlogicalIf .true., compute the observation using a method + which assumes all effects occur at the tangent point. + If .false., integrate along the tangent line and do + ray-path reconstruction. + Default: .true.
obs_windowreal(r8)Accept and convert observations if they are within + plus or minus this number of hours from the analysis + time (which is read as an input from the terminal or + the standard input unit). + Default: 12.0
ray_dsreal(r8)For the non-local operator only, the delta stepsize, + in meters, to use for the along-path integration in + each direction out from the tangent point. + Default: 5000.0
ray_htopreal(r8)For the non-local operator only, stop the integration + when one of the endpoints of the next integration step + goes above this height. Specified in meters. + Default: 15000.0
gpsro_netcdf_filecharacter(len=128)The input filename when converting a single profile. + Only one of the 2 filenames can have a valid value, + so to use the single filename set the list name + ('gpsro_netcdf_filelist') to the empty string (''). + Default: 'cosmic_gps_input.nc'
gpsro_netcdf_filelistcharacter(len=128)To convert a series of profiles in a single execution + create a text file which contains each input file, + in ascii, one filename per line. Set this item to + the name of that file, and set 'gpsro_netcdf_file' to + the empty string (''). + Default: 'cosmic_gps_input_list'
gpsro_out_filecharacter(len=128)The output file to be created. Note that to be + compatible with earlier versions of this program, if + this file already exists it will be read in and the + new data will be inserted into that file. + Default: 'obs_seq.gpsro'
overwrite_timelogicalThis item is NOT in the standard namelist, but code + exists in the program to support the functionality + if the source is edited and this variable is added + to the namelist. If set to + .true., the output file will be created with all + observations marked with the specified analysis time + instead of the actual observation collection time. + This is generally not what you want, but might be + useful if you are binning observations by time to do + thinning or super-ob'ing data. + Default: .false.
+

+

+ + +


KNOWN BUGS

+Some COSMIC files seem to have internal times which differ from the +times encoded in the filenames by as much as 2-3 minutes. If it is +important to get all the observations within a particular time window +files with filenames from a few minutes before and after the window +should be converted. +Times really outside the window can be excluded either by setting +the 'obs_window' namelist variable, or can be trimmed later with the +obs_sequence_tool.

- + Modified: DART/trunk/observations/gps/work/convert_script.csh =================================================================== --- DART/trunk/observations/gps/work/convert_script.csh 2009-08-10 19:13:07 UTC (rev 3996) +++ DART/trunk/observations/gps/work/convert_script.csh 2009-08-10 21:33:27 UTC (rev 3997) @@ -3,20 +3,26 @@ # Main script: # generate multiple days of gps observations # -# calls the cosmic_to_obsseq script with a date, the working -# directory location, and whether to download the data automatically -# from the cosmic web site (downloading data requires signing up -# for a username/password to access the site, and then setting -# the username and password here before running this script.) +# calls the cosmic_to_obsseq script with 4 args: # +# - the date in YYYYMMDD format +# - the working directory location +# - whether to download the data automatically from the cosmic web site +# (downloading data requires signing up for a username/password to +# access the site, and then setting the username and password here +# before running this script.) set to no if the data has already been +# downloaded separately before now. +# - whether to delete the data automatically from the local disk after the +# conversion is done. +# setenv cosmic_user xxx setenv cosmic_pw yyy -./cosmic_to_obsseq.csh 20061101 .. yes -./cosmic_to_obsseq.csh 20061102 .. yes -./cosmic_to_obsseq.csh 20061103 .. yes -./cosmic_to_obsseq.csh 20061104 .. yes -./cosmic_to_obsseq.csh 20061105 .. yes -./cosmic_to_obsseq.csh 20061106 .. yes -./cosmic_to_obsseq.csh 20061107 .. yes +./cosmic_to_obsseq.csh 20061101 .. no no +./cosmic_to_obsseq.csh 20061102 .. no no +./cosmic_to_obsseq.csh 20061103 .. no no +./cosmic_to_obsseq.csh 20061104 .. no no +./cosmic_to_obsseq.csh 20061105 .. no no +./cosmic_to_obsseq.csh 20061106 .. no no +./cosmic_to_obsseq.csh 20061107 .. no no Added: DART/trunk/observations/gps/work/cosmic_download.csh =================================================================== --- DART/trunk/observations/gps/work/cosmic_download.csh (rev 0) +++ DART/trunk/observations/gps/work/cosmic_download.csh 2009-08-10 21:33:27 UTC (rev 3997) @@ -0,0 +1,153 @@ +#!/bin/csh +######################################################################## +# +# cosmic_download.csh - script that downloads COSMIC observations. +# then you can run cosmic_to_obsseq.csh with a third argument of +# 'no' so it does not re-download the same files. +# +# requires 2 args: +# $1 - analysis date (yyyymmdd format) +# $2 - base observation directory +# +# and update the 3 env settings at the top to match your system. +# +# created May 2009, nancy collins ncar/cisl +# converted from cosmic_to_obsseq.csh +# updated Aug 2009, nancy collins ncar/cisl +# +# from the cosmic web site about the use of 'wget' to download +# the many files needed to do this process: +# ------- +# Hints for using wget for fetching CDAAC files from CDAAC: +# +# Here is one recipe for fetching all cosmic real time atmPrf files for one day: +# +# wget -nd -np -r -l 10 -w 2 --http-user=xxxx --http-passwd=xxxx http://cosmic-io.cosmic.ucar.edu/cdaac/login/cosmicrt/level2/atmPrf/2009.007/ +# +# The option -np (no parents) is important. Without it, all manner of +# files from throughout the site will be loaded, I think due to the +# links back to the main page which are everywhere. +# +# The option -r (recursive fetch) is necessary unless there is just +# one file you want to fetch. +# +# The option -l 10 (limit of recursive depth to 10 levels) is necessary +# in order to get around the default 5 level depth. +# +# The option -nd dumps all fetched files into your current directory. +# Otherwise a directory hierarchy will be created: +# cosmic-io.cosmic.ucar.edu/cdaac/login/cosmic/level2/atmPrf/2006.207 +# +# The option -w 2 tells wget to wait two seconds between each file fetch +# so as to have pity on our poor web server. +# ------- +# +######################################################################## + +# should only have to set the DART_DIR and the rest should be in the +# right place relative to it. +setenv DART_DIR /home/user/dart +setenv cosmic_user xxx +setenv cosmic_pw yyy + +setenv DART_WORK_DIR ${DART_DIR}/observations/gps/work +setenv CONV_PROG convert_cosmic_gps_cdf +setenv DATE_PROG advance_time + +set chatty=yes +set downld=yes + +set datea = ${1} # target date, YYYYMMDD +set datadir = ${2} # where to process the files + +set assim_freq = 6 # hours, sets centers of windows. +set download_window = 3 # window half-width (some users choose 2 hours) +set gps_repository_path = 'http://cosmic-io.cosmic.ucar.edu/cdaac/login' +set wget_cmd = 'wget -q -nd -np -r -l 10 -w 1' + +# i've done this wrong enough times and wasted a lot of download time, +# so do a bunch of bullet-proofing here before going on. + +# verify the dirs all exist, the input.nml is in place. +if ( ! -d ${DART_WORK_DIR} ) then + echo 'work directory not found: ' ${DART_WORK_DIR} + exit +endif + +echo 'current dir is ' `pwd` +if ( `pwd` != ${DART_WORK_DIR} ) then + echo 'if not already there, changing directory to work dir.' + cd ${DART_WORK_DIR} + echo 'current dir now ' `pwd` +endif + +if ( ! -d ${datadir} ) then + echo 'data processing directory not found: ' ${datadir} + echo 'creating now.' + mkdir ${datadir} + ls -ld ${datadir} +endif + +if ( ! -e ${datadir}/${DATE_PROG} ) then + echo 'data processing directory does not contain the time converter' + echo 'copying from work dir to data proc dir' + echo `pwd`/${DATE_PROG} '->' ${datadir}/${DATE_PROG} + cp -f ./${DATE_PROG} ${datadir} +else + echo 'using time conversion program already found in data proc dir' +endif + +echo 'changing dir to data proc directory' +cd ${datadir} +echo 'current dir now ' `pwd` + + if ( ! $?cosmic_user || ! $?cosmic_pw ) then + echo "You must setenv cosmic_user to your username for the cosmic web site" + echo "and setenv cosmic_pw to your password. (or export cosmic_user=val for" + echo "ksh/bash users) then rerun this script. " + exit -1 + endif + +if ( $chatty == 'yes' ) then + echo 'starting raw file download at' `date` +endif + +set get = "${wget_cmd} --http-user=${cosmic_user} --http-passwd=${cosmic_pw}" + +set yyyy = `echo $datea | cut -b1-4` + +if ( ! -d ${datea} ) then + echo 'year/month/day directory not found: ' ${datea} + echo 'creating now.' + mkdir ${datea} +endif + +cd ${datea} + +echo $datea +set jyyyydd = `echo $datea 0 -j | ../${DATE_PROG}` +echo $jyyyydd +@ mday = $jyyyydd[2] + 1000 ; set mday = `echo $mday | cut -b2-4` +${get} ${gps_repository_path}/cosmic/level2/atmPrf/${yyyy}.${mday}/ +rm -f *.html *.txt +${get} ${gps_repository_path}/champ/level2/atmPrf/${yyyy}.${mday}/ +rm -f *.html *.txt + +set jyyyydd = `echo $datea 24 -j | ../${DATE_PROG}` +@ mday = $jyyyydd[2] + 1000 ; set mday = `echo $mday | cut -b2-4` +${get} ${gps_repository_path}/cosmic/level2/atmPrf/${yyyy}.${mday}/ +rm -f *.html *.txt +${get} ${gps_repository_path}/champ/level2/atmPrf/${yyyy}.${mday}/ +rm -f *.html *.txt + +if ( $chatty == 'yes' ) then + # the ls arg list line gets too long in some cases + echo `/bin/ls | grep _nc | wc -l` 'raw files' + echo 'all raw files download at ' `date` +endif + +cd .. + +exit 0 + + Property changes on: DART/trunk/observations/gps/work/cosmic_download.csh ___________________________________________________________________ Name: svn:executable + * Modified: DART/trunk/observations/gps/work/cosmic_to_obsseq.csh =================================================================== @@ Diff output truncated at 40000 characters. @@ From nancy at ucar.edu Mon Aug 10 16:25:58 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Mon, 10 Aug 2009 16:25:58 -0600 (MDT) Subject: [Dart-dev] [3998] DART/trunk/utilities/utilities_mod.html: Added missing doc for recently added subroutine. Message-ID: <200908102225.n7AMPwAl010439@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090810/01a43a16/attachment.html -------------- next part -------------- Modified: DART/trunk/utilities/utilities_mod.html =================================================================== --- DART/trunk/utilities/utilities_mod.html 2009-08-10 21:33:27 UTC (rev 3997) +++ DART/trunk/utilities/utilities_mod.html 2009-08-10 22:25:57 UTC (rev 3998) @@ -107,6 +107,7 @@  find_textfile_dims  file_to_text  is_longitude_betweenget_next_filename  set_tasknum  set_output  do_output @@ -492,6 +493,43 @@
+ + +


+
+ var = get_next_filename( listname, index ) + +
+ character(len=*),  intent(in) :: listname
+ integer,           intent(in) :: index
+ character(len=128)            :: get_next_filename
+ 
+

Description

+

+Returns the specified line of a text file, given a filename and a line number. +It returns an empty string when the line number is larger than the +number of lines in a file. +

+

+Intended as an easy way to process a list of files. Use a command +like 'ls > out' to +create a file containing the list, in order, of files to be processed. +Then call this function with an increasing index number until the return +value is empty. +

+ + + + + + + +
var An ascii string, up to 128 characters long, containing the + contents of line index of the input file.
listname The filename to open and read lines from.
index Integer line number, starting at 1. If larger than the + number of lines in the file, the empty string '' will be returned.
+
+ +


From nancy at ucar.edu Wed Aug 12 09:41:27 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Wed, 12 Aug 2009 09:41:27 -0600 (MDT) Subject: [Dart-dev] [4001] DART/trunk/diagnostics/matlab: These functions were deprecated a long time ago. Message-ID: <200908121541.n7CFfRPs027106@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090812/6c6adb0f/attachment-0001.html -------------- next part -------------- Deleted: DART/trunk/diagnostics/matlab/fit_ens_bias_vertical.m =================================================================== --- DART/trunk/diagnostics/matlab/fit_ens_bias_vertical.m 2009-08-11 16:29:29 UTC (rev 4000) +++ DART/trunk/diagnostics/matlab/fit_ens_bias_vertical.m 2009-08-12 15:41:26 UTC (rev 4001) @@ -1,245 +0,0 @@ -function fit_ens_bias_vertical(ddir) -% fit_ens_bias_vertical(ddir) -% -% Plots the RMS bias as a function of height for several regions. -% The bias is averaged over a time period. The bias and averaging -% is done by 'obs_diag' - which generates data files that are -% used by this plotting routine. -% -% the input data files are of the form *ges_ver_ave_bias.dat, -% where the 'ave' refers to averaging over time. The first part of -% the file name is the name of the variable contained in the file. -% -% 'obs_diag' also produces a matlab-compatible file of plotting attributes: -% ObsDiagAtts.m which specifies the run-time configuration of obs_diag. -% -% ddir is an optional argument specifying the directory containing -% the data files as preprocessed by the support routines. -% -% USAGE: -% -% fit_ens_bias_vertical('plot') -% -% Remember you can click and drag the legends ... - -% Data Assimilation Research Testbed -- DART -% Copyright 2004-2007, Data Assimilation Research Section -% University Corporation for Atmospheric Research -% Licensed under the GPL -- www.gpl.org/licenses/gpl.html -% -% -% $URL$ -% $Id$ -% $Revision$ -% $Date$ - -% Ensures the specified directory is searched first. -if ( nargin > 0 ) - startpath = addpath(ddir); -else - startpath = path; -end - -datafile = 'ObsDiagAtts'; -ptypes = {'gs-','bd-','ro-','k+-'}; % for each region - -%---------------------------------------------------------------------- -% Get plotting metadata from obs_diag run. -%---------------------------------------------------------------------- - -if ( exist(datafile) == 2 ) - - eval(datafile) - - if ( exist('plevel','var') == 0 ) - disp(sprintf('%s does not have multiple levels.', datafile)) - disp('It cannot be plotted with fit_ens_bias_vertical.') - return - end - -else - error(sprintf('%s cannot be found.', datafile)) -end - -% set up a structure with all static plotting components -skip_seconds = time_to_skip(4)*3600 + time_to_skip(5)*60 + time_to_skip(6); -iskip = time_to_skip(3) + skip_seconds/86400; - -plotdat.bin1 = datenum(first_bin_center); % a known date in matlab's time units -plotdat.toff = plotdat.bin1 - t1; % determine temporal offset (calendar base) -plotdat.day1 = datestr(t1+plotdat.toff+iskip,'yyyy-mm-dd HH'); -plotdat.dayN = datestr(tN+plotdat.toff,'yyyy-mm-dd HH'); -plotdat.linewidth = 2.0; - - -%---------------------------------------------------------------------- -% Loop around observation types -%---------------------------------------------------------------------- - -for ivar = 1:length(All_Level_Varnames), - - % set up a structure with all the plotting components - - plotdat.varname = All_Level_Varnames{ivar}; - - switch obs_select - case 1, - string1 = sprintf('%s Ens Mean (all data)', plotdat.varname); - case 2, - string1 = sprintf('%s Ens Mean (RaObs)', plotdat.varname); - otherwise, - string1 = sprintf('%s Ens Mean (ACARS,SATWND)', plotdat.varname); - end - - switch All_Level_Varnames{ivar} - case{'RADIOSONDE_TEMPERATURE'} - plotdat.xlabel = 'bias (degrees C)'; - case{'RADIOSONDE_V_WIND_COMPONENT'} - plotdat.xlabel = 'bias (m/s)'; - otherwise - plotdat.xlabel = 'bias'; - end - - plotdat.ges = sprintf('%s_ges_ver_ave_bias.dat',All_Level_Varnames{ivar}); - plotdat.anl = sprintf('%s_anl_ver_ave_bias.dat',All_Level_Varnames{ivar}); - plotdat.main = sprintf('%s %sZ -- %sZ',string1,plotdat.day1,plotdat.dayN); - plotdat = SetLevels(plotdat); - - % plot by region - - figure(ivar); orient landscape; clf; wysiwyg - - for iregion = 1:length(Regions), - plotdat.title = Regions{iregion}; - plotdat.region = iregion; - myplot(plotdat); - end - - CenterAnnotation(plotdat.main) - BottomAnnotation(plotdat.ges) - - psfname = sprintf('%s_bias.ps',plotdat.varname); - print(ivar,'-dpsc',psfname); - -end - -path(startpath); % restore MATLABPATH to original setting - -%---------------------------------------------------------------------- -% 'Helper' functions -%---------------------------------------------------------------------- - -function myplot(plotdat) -regionindex = 2 + 2*(plotdat.region - 1); -pv = load(plotdat.ges); -av = load(plotdat.anl); -p_v = SqueezeMissing(pv); -a_v = SqueezeMissing(av); -guessX = p_v(:,regionindex); -analyX = a_v(:,regionindex); -levels = plotdat.levels; - -% Try to figure out intelligent axis limits -indmax = size(p_v,2); -xdatarr = [p_v(:,2:2:indmax) a_v(:,2:2:indmax)]; % concatenate all data -xlims = [min(xdatarr(:)) max(xdatarr(:))]; % limits of all data -axlims = [floor(xlims(1)) ceil(xlims(2)) min(plotdat.ylims) max(plotdat.ylims)]; - -% sometimes there is no valid data, must patch axis limits -if (~isfinite(axlims(1))) - axlims(1) = -1; -end -if (~isfinite(axlims(2))) - axlims(2) = 1; -end - -subplot(2,2,plotdat.region) - plot(guessX,levels,'k+-',analyX,levels,'ro-','LineWidth',plotdat.linewidth) - axis(axlims) - grid - set(gca,'YDir', plotdat.ydir) - hold on; plot([0 0],[axlims(3) axlims(4)],'k-') - title( plotdat.title, 'Interpreter','none','FontSize', 12, 'FontWeight', 'bold' ) - ylabel(plotdat.ylabel, 'FontSize', 10) - xlabel(plotdat.xlabel, 'FontSize', 10) - h = legend('guess', 'analysis','Location','best'); - legend(h,'boxoff') - - - -function y = SqueezeMissing(x) - -missing = find(x < -98); % 'missing' is coded as -99 - -if isempty(missing) - y = x; -else - y = x; - y(missing) = NaN; -end - - - -function CenterAnnotation(main) -subplot('position',[0.48 0.48 0.04 0.04]) -axis off -h = text(0.5,0.5,main); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','bottom', ... - 'Interpreter','none', ... - 'FontSize',12, ... - 'FontWeight','bold') - - - -function BottomAnnotation(main) -% annotates the directory containing the data being plotted -subplot('position',[0.48 0.01 0.04 0.04]) -axis off -bob = which(main); -[pathstr,name,ext,versn] = fileparts(bob); -h = text(0.0,0.5,pathstr); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','middle',... - 'Interpreter','none',... - 'FontSize',8) - - - -function plotstruct = SetLevels(plotdat) - -if ( exist(plotdat.ges,'file') ~= 2 ) - error(sprintf('%s does not seem to exist.',plotdat.ges)) -end -if ( exist(plotdat.anl,'file') ~= 2 ) - error(sprintf('%s does not seem to exist.',plotdat.anl)) -end - -datmat = load(plotdat.ges); -guess = datmat(:,1); - -datmat = load(plotdat.anl); -anl = datmat(:,1); - -if (sum(abs(guess-anl)) > 0) - str1 = sprintf('levels in %s and %s do not match',plotdat.ges, plotdat.anl) - error(str1) -end - -levels = guess; clear guess anl - -plotstruct = plotdat; -plotstruct.levels = levels; -plotstruct.top = levels(1); -plotstruct.surface = levels(length(levels)); - -if ( plotstruct.top > plotstruct.surface ) - plotstruct.ylabel = 'height(m)'; - plotstruct.ydir = 'normal'; - plotstruct.ylims = [plotstruct.surface plotstruct.top]; -else - plotstruct.ylabel = 'Pressure (hPa)'; - plotstruct.ydir = 'reverse'; - plotstruct.ylims = [plotstruct.surface plotstruct.top]; -end - Deleted: DART/trunk/diagnostics/matlab/fit_ens_mean_time.m =================================================================== --- DART/trunk/diagnostics/matlab/fit_ens_mean_time.m 2009-08-11 16:29:29 UTC (rev 4000) +++ DART/trunk/diagnostics/matlab/fit_ens_mean_time.m 2009-08-12 15:41:26 UTC (rev 4001) @@ -1,221 +0,0 @@ -function fit_ens_mean_time(ddir) -% fit_ens_mean_time(ddir) -% -% Part of the observation-space diagnostics routines. -% -% Plots the spatial mean RMSE of the ensemble mean as a function of -% time for both the 'guess' and the 'analysis' at a single level. -% Several regions are plotted. This function simply plots the -% data in *ges_times.dat using metadata in ObsDiagAtts.m - both -% created by the executable 'obs_diag'. -% -% 'obs_diag' also produces a matlab-compatible file of plotting attributes: -% ObsDiagAtts.m which specifies the run-time configuration of obs_diag. -% -% ddir is an optional argument specifying the directory containing -% the data files as preprocessed by the support routines. -% -% USAGE: if the preprocessed data files are in a directory called 'plot' -% -% ddir = 'plot'; -% fit_ens_mean_time(ddir) -% -% USAGE: if the preprocessed data files are in the current directory -% -% fit_ens_mean_time - -% Data Assimilation Research Testbed -- DART -% Copyright 2004-2007, Data Assimilation Research Section -% University Corporation for Atmospheric Research -% Licensed under the GPL -- www.gpl.org/licenses/gpl.html -% -% -% $URL$ -% $Id$ -% $Revision$ -% $Date$ - -% Ensures the specified directory is searched first. -if ( nargin > 0 ) - startpath = addpath(ddir); -else - startpath = path; -end - -%---------------------------------------------------------------------- -% Defaults -%---------------------------------------------------------------------- - -datafile = 'ObsDiagAtts'; -ptypes = {'gs-','bd-','ro-','k+-'}; % for each region - -%---------------------------------------------------------------------- -% Get plotting metadata from obs_diag run. -%---------------------------------------------------------------------- - -if ( exist(datafile) == 2 ) - - eval(datafile) - - if ( exist('plevel','var') == 0 ) - plevel = 1; - iskip = iskip_days; - plotdat.toff = 0; - plotdat.bin1 = datenum(t1); - else % high dimensional models - % Coordinate between time types and dates - skip_seconds = time_to_skip(4)*3600 + time_to_skip(5)*60 + time_to_skip(6); - iskip = time_to_skip(3) + skip_seconds/86400; - plotdat.bin1 = datenum(first_bin_center); % a known date in matlab's time units - plotdat.toff = plotdat.bin1 - t1; - end - -else - error(sprintf('%s cannot be found.', datafile)) -end - -% Set up a structure with all the plotting components -plotdat.day1 = datestr(t1+plotdat.toff+iskip,'yyyy-mm-dd HH'); -plotdat.dayN = datestr(tN+plotdat.toff,'yyyy-mm-dd HH'); -plotdat.level = plevel; -plotdat.ylabel = 'RMSE'; -plotdat.nregions = length(Regions); -plotdat.nvars = length(One_Level_Varnames); -plotdat.flavor = 'Ens Mean'; - -%---------------------------------------------------------------------- -% Loop around observation types -%---------------------------------------------------------------------- - -for ivar = 1:plotdat.nvars, - - plotdat.varname = One_Level_Varnames{ivar}; - - switch obs_select - case 1, - string1 = sprintf('%s (all data)', plotdat.varname); - case 2, - string1 = sprintf('%s (RaObs)', plotdat.varname); - otherwise, - string1 = sprintf('%s (ACARS,SATWND)', plotdat.varname); - end - -% switch One_Level_Varnames{ivar} -% case{'P'} - ges = sprintf('%s_ges_times.dat',One_Level_Varnames{ivar}); - anl = sprintf('%s_anl_times.dat',One_Level_Varnames{ivar}); - main = sprintf('%s %s',plotdat.flavor,string1); -% otherwise -% ges = sprintf('%s_ges_times_%04dmb.dat',One_Level_Varnames{ivar}); -% anl = sprintf('%s_anl_times_%04dmb.dat',One_Level_Varnames{ivar}); -% main = sprintf('%s %s %d hPa',plotdat.flavor,string1,plotdat.level); -% end - - plotdat.ges = ges; - plotdat.anl = anl; - - % plot each region - - figure(ivar); orient tall; clf; wysiwyg - - for iregion = 1:length(Regions), - plotdat.title = Regions{iregion}; - plotdat.region = iregion; - myplot(plotdat); - end - - CenterAnnotation(main); % One title in the middle - BottomAnnotation(ges); % annotate filename at bottom - - % create a postscript file - - psfname = sprintf('%s_ens_mean_time.ps',plotdat.varname); - print(ivar,'-dpsc',psfname); - -end - -path(startpath); % restore MATLABPATH to original setting - -%---------------------------------------------------------------------- -% 'Helper' functions -%---------------------------------------------------------------------- - -function myplot(plotdat) -p1 = load(plotdat.ges); p = SqueezeMissing(p1); -a1 = load(plotdat.anl); a = SqueezeMissing(a1); - -% Make x axis plotting arrays in units of 'days' -xp = p(:,1) + p(:,2)/86400 + plotdat.toff; -xa = a(:,1) + a(:,2)/86400 + plotdat.toff; - -offset = 3; % columns 1,2 are time, 3=mean, 4=spread, 5=numobs - -count = offset+(plotdat.region-1)*3; -yp = p(:,count); -ya = a(:,count); - -gmean = mean(yp(isfinite(yp))); gstring = sprintf('guess; mean=%.3f',gmean); -amean = mean(ya(isfinite(ya))); astring = sprintf('analysis; mean=%.3f',amean); - -subplot(plotdat.nregions,1,plotdat.region) - - plot(xp,yp,'k+-',xa,ya,'ro-','LineWidth',1.5) - grid - ax = axis; ax(3) = 0.0; axis(ax); - ylabel(plotdat.ylabel, 'fontsize', 10); - title(plotdat.title, 'Interpreter','none','fontsize', 12,'FontWeight','bold') - h = legend(gstring, astring); - legend(h,'boxoff') - - % a slightly better way to annotate dates, etc. - ttot = max(xp) - min(xp) + 1; - if ((plotdat.bin1 > 1000) && (ttot > 32)); - datetick('x',6,'keeplimits','keepticks'); - monstr = datestr(xp(1),28); - xlabel(sprintf('month/day - %s start',monstr)) - elseif (plotdat.bin1 > 1000); - datetick('x',7); - monstr = datestr(xp(1),28); - xlabel(sprintf('day of month - %s start',monstr)) - else - xlabel('days') - end - - - -function y = SqueezeMissing(x) - -missing = find(x < -98); % 'missing' is coded as -99 - -if isempty(missing) - y = x; -else - y = x; - y(missing) = NaN; -end - - - -function CenterAnnotation(main) -subplot('position',[0.48 0.48 0.04 0.04]) -axis off -h = text(0.5,0.5,main); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','bottom', ... - 'Interpreter','none', ... - 'FontSize',12, ... - 'FontWeight','bold') - - - -function BottomAnnotation(main) -% annotates the directory containing the data being plotted -subplot('position',[0.48 0.01 0.04 0.04]) -axis off -bob = which(main); -[pathstr,name,ext,versn] = fileparts(bob); -h = text(0.0,0.5,pathstr); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','middle',... - 'Interpreter','none',... - 'FontSize',8) Deleted: DART/trunk/diagnostics/matlab/fit_ens_mean_vertical.m =================================================================== --- DART/trunk/diagnostics/matlab/fit_ens_mean_vertical.m 2009-08-11 16:29:29 UTC (rev 4000) +++ DART/trunk/diagnostics/matlab/fit_ens_mean_vertical.m 2009-08-12 15:41:26 UTC (rev 4001) @@ -1,243 +0,0 @@ -function fit_ens_mean_vertical(ddir) -% fit_ens_mean_vertical(ddir) -% -% Plots the RMS of the ensemble mean as a function of height for -% several regions. The ensemble mean is averaged over a time period. -% The calculations are done by 'obs_diag' - which generates data files -% that are used by this plotting routine. -% -% the input data files are of the form *ges_ver_ave.dat, -% where the 'ave' refers to averaging over time. The first part of -% the file name is the name of the variable contained in the file. -% -% 'obs_diag' also produces a matlab-compatible file of plotting attributes: -% ObsDiagAtts.m which specifies the run-time configuration of obs_diag. -% -% ddir is an optional argument specifying the directory containing -% the data files as preprocessed by the support routines. -% -% USAGE: if the preprocessed data files are in a directory called 'plot' -% -% ddir = 'plot'; -% fit_ens_mean_vertical(ddir) - -% Data Assimilation Research Testbed -- DART -% Copyright 2004-2007, Data Assimilation Research Section -% University Corporation for Atmospheric Research -% Licensed under the GPL -- www.gpl.org/licenses/gpl.html -% -% -% $URL$ -% $Id$ -% $Revision$ -% $Date$ - -% Ensures the specified directory is searched first. -if ( nargin > 0 ) - startpath = addpath(ddir); -else - startpath = path; -end - -%---------------------------------------------------------------------- -% Defaults -%---------------------------------------------------------------------- - -datafile = 'ObsDiagAtts'; -ptypes = {'gs-','bd-','ro-','k+-'}; % for each region - -%---------------------------------------------------------------------- -% Get plotting metadata from obs_diag run. -%---------------------------------------------------------------------- - -if ( exist(datafile) == 2 ) - - eval(datafile) - - if ( exist('plevel','var') == 0 ) - disp(sprintf('%s does not have multiple levels.', datafile)) - disp('It cannot be plotted with fit_ens_mean_vertical.') - return - end - -else - error(sprintf('%s cannot be found.', datafile)) -end - -% set up a structure with all static plotting components -skip_seconds = time_to_skip(4)*3600 + time_to_skip(5)*60 + time_to_skip(6); -iskip = time_to_skip(3) + skip_seconds/86400; - -plotdat.bin1 = datenum(first_bin_center); % a known date in matlab's time units -plotdat.toff = plotdat.bin1 - t1; % determine temporal offset (calendar base) -plotdat.day1 = datestr(t1+plotdat.toff+iskip,'yyyy-mm-dd HH'); -plotdat.dayN = datestr(tN+plotdat.toff,'yyyy-mm-dd HH'); -plotdat.xlabel = 'RMSE'; -plotdat.linewidth = 2.0; - -main = sprintf('Ensemble Mean %s - %s',plotdat.day1,plotdat.dayN); - -%---------------------------------------------------------------------- -% Loop around observation types -%---------------------------------------------------------------------- - -for ivar = 1:length(All_Level_Varnames), - - % set up a structure with all the plotting components - - plotdat.varname = All_Level_Varnames{ivar}; - - switch obs_select - case 1, - string1 = sprintf('%s Ens Mean (all data)', plotdat.varname); - case 2, - string1 = sprintf('%s Ens Mean (RaObs)', plotdat.varname); - otherwise, - string1 = sprintf('%s Ens Mean (ACARS,SATWND)', plotdat.varname); - end - - plotdat.ges = sprintf('%s_ges_ver_ave.dat',All_Level_Varnames{ivar}); - plotdat.anl = sprintf('%s_anl_ver_ave.dat',All_Level_Varnames{ivar}); - plotdat.main = sprintf('%s %sZ -- %sZ',string1,plotdat.day1,plotdat.dayN); - plotdat = SetLevels(plotdat); - - % plot by region - - figure(ivar); orient landscape; clf; wysiwyg - - for iregion = 1:length(Regions), - plotdat.title = Regions{iregion}; - plotdat.region = iregion; - myplot(plotdat); - end - - CenterAnnotation(plotdat.main) - BottomAnnotation(plotdat.ges) - - % create a postscript file - - psfname = sprintf('%s_vertical.ps',plotdat.varname); - print(ivar,'-dpsc',psfname); - -end - -path(startpath); % restore MATLABPATH to original setting - -%---------------------------------------------------------------------- -% 'Helper' functions -%---------------------------------------------------------------------- - -function myplot(plotdat) -regionindex = 2 + 2*(plotdat.region - 1); -pv = load(plotdat.ges); -av = load(plotdat.anl); -p_v = SqueezeMissing(pv); -a_v = SqueezeMissing(av); -guessX = p_v(:,regionindex); -analyX = a_v(:,regionindex); -levels = plotdat.levels; - -% Try to figure out intelligent axis limits -indmax = size(p_v,2); -xdatarr = [p_v(:,2:2:indmax) a_v(:,2:2:indmax)]; % concatenate all data -xlims = [0.0 max(xdatarr(:))]; % limits of all data -axlims = [floor(xlims(1)) ceil(xlims(2)) min(plotdat.ylims) max(plotdat.ylims)]; - -% sometimes there is no valid data, must patch axis limits -if (~isfinite(axlims(2))) - axlims(2) = 1; -end - -subplot(2,2,plotdat.region) - plot(guessX,levels,'k+-',analyX,levels,'ro-','LineWidth',plotdat.linewidth) - axis(axlims) - grid - set(gca,'YDir', plotdat.ydir) - title( plotdat.title, 'Interpreter', 'none', 'FontSize', 12, 'FontWeight', 'bold' ) - ylabel(plotdat.ylabel, 'FontSize', 10) - xlabel(plotdat.xlabel, 'FontSize', 10) - if isempty(strfind(lower(plotdat.varname),'w')) - h = legend('guess', 'analysis','Location','East'); - else - h = legend('guess', 'analysis','Location','SouthEast'); - end - legend(h,'boxoff'); - - - -function y = SqueezeMissing(x) - -missing = find(x < -98); % 'missing' is coded as -99 - -if isempty(missing) - y = x; -else - y = x; - y(missing) = NaN; -end - - - -function CenterAnnotation(main) -subplot('position',[0.48 0.48 0.04 0.04]) -axis off -h = text(0.5,0.5,main); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','bottom', ... - 'Interpreter','none', ... - 'FontSize',12, ... - 'FontWeight','bold') - - - -function BottomAnnotation(main) -% annotates the directory containing the data being plotted -subplot('position',[0.48 0.01 0.04 0.04]) -axis off -bob = which(main); -[pathstr,name,ext,versn] = fileparts(bob); -h = text(0.0,0.5,pathstr); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','middle',... - 'Interpreter','none',... - 'FontSize',8) - - - -function plotstruct = SetLevels(plotdat) - -if ( exist(plotdat.ges,'file') ~= 2 ) - error(sprintf('%s does not seem to exist.',plotdat.ges)) -end -if ( exist(plotdat.anl,'file') ~= 2 ) - error(sprintf('%s does not seem to exist.',plotdat.anl)) -end - -datmat = load(plotdat.ges); -guess = datmat(:,1); - -datmat = load(plotdat.anl); -anl = datmat(:,1); - -if (sum(abs(guess-anl)) > 0) - str1 = sprintf('levels in %s and %s do not match',plotdat.ges, plotdat.anl) - error(str1) -end - -levels = guess; clear guess anl - -plotstruct = plotdat; -plotstruct.levels = levels; -plotstruct.top = levels(1); -plotstruct.surface = levels(length(levels)); - -if ( plotstruct.top > plotstruct.surface ) - plotstruct.ylabel = 'height(m)'; - plotstruct.ydir = 'normal'; - plotstruct.ylims = [plotstruct.surface plotstruct.top]; -else - plotstruct.ylabel = 'Pressure (hPa)'; - plotstruct.ydir = 'reverse'; - plotstruct.ylims = [plotstruct.surface plotstruct.top]; -end - Deleted: DART/trunk/diagnostics/matlab/fit_ens_spread_time.m =================================================================== --- DART/trunk/diagnostics/matlab/fit_ens_spread_time.m 2009-08-11 16:29:29 UTC (rev 4000) +++ DART/trunk/diagnostics/matlab/fit_ens_spread_time.m 2009-08-12 15:41:26 UTC (rev 4001) @@ -1,230 +0,0 @@ -function fit_ens_spread_time(ddir) -% fit_ens_spread_time(ddir) -% -% Part of the observation-space diagnostics routines. -% -% Plots the spatial mean RMS of the spread of the ensemble as a function -% of time for both the 'guess' and the 'analysis' at a single level. -% Several regions are plotted. This function simply plots the -% data in *ges_times.dat using metadata in ObsDiagAtts.m - both -% created by the executable 'obs_diag'. -% -% 'obs_diag' also produces a matlab-compatible file of plotting attributes: -% ObsDiagAtts.m which specifies the run-time configuration of obs_diag. -% -% The figures are automatically saved as postscript files. -% -% ddir is an optional argument specifying the directory containing -% the data files as preprocessed by the support routines. -% -% USAGE: if the preprocessed data files are in a directory called 'plot' -% -% fit_ens_spread_time('plot') -% -% USAGE: if the preprocessed data files are in the current directory -% -% fit_ens_spread_time - -% Data Assimilation Research Testbed -- DART -% Copyright 2004-2007, Data Assimilation Research Section -% University Corporation for Atmospheric Research -% Licensed under the GPL -- www.gpl.org/licenses/gpl.html -% -% -% $URL$ -% $Id$ -% $Revision$ -% $Date$ - -% Ensures the specified directory is searched first. -if ( nargin > 0 ) - startpath = addpath(ddir); -else - startpath = path; -end - -%---------------------------------------------------------------------- -% Defaults -%---------------------------------------------------------------------- - -datafile = 'ObsDiagAtts'; -ptypes = {'gs-','bd-','ro-','k+-'}; % for each region - -%---------------------------------------------------------------------- -% Get plotting metadata from obs_diag run. -%---------------------------------------------------------------------- - -if ( exist(datafile) == 2 ) - - eval(datafile) - - if ( exist('plevel','var') == 0 ) - plevel = 1; - iskip = iskip_days; - plotdat.toff = 0; - plotdat.bin1 = datenum(t1); - else % high dimensional models - % set up a structure with all static plotting components - % Coordinate between time types and dates - skip_seconds = time_to_skip(4)*3600 + time_to_skip(5)*60 + time_to_skip(6); - iskip = time_to_skip(3) + skip_seconds/86400; - plotdat.bin1 = datenum(first_bin_center); % a known date in matlab's time units - plotdat.toff = plotdat.bin1 - t1; % determine temporal offset (calendar base) - end - -else - error(sprintf('%s cannot be found.', datafile)) -end - -% set up a structure with all static plotting components -plotdat.day1 = datestr(t1+plotdat.toff+iskip,'yyyy-mm-dd HH'); -plotdat.dayN = datestr(tN+plotdat.toff,'yyyy-mm-dd HH'); -plotdat.level = plevel; -plotdat.ylabel = 'RMS'; -plotdat.nregions = length(Regions); -plotdat.nvars = length(One_Level_Varnames); -plotdat.flavor = 'Ens Spread'; -plotdat.linewidth = 2.0; - -%---------------------------------------------------------------------- -% Loop around observation types -%---------------------------------------------------------------------- - -for ivar = 1:plotdat.nvars, - - plotdat.varname = One_Level_Varnames{ivar}; - - switch obs_select - case 1, - obsstring = sprintf('%s (all data)', plotdat.varname); - case 2, - obsstring = sprintf('%s (RaObs)', plotdat.varname); - otherwise, - obsstring = sprintf('%s (ACARS,SATWND)', plotdat.varname); - end - -% switch One_Level_Varnames{ivar} -% case{'P'} - ges = sprintf('%s_ges_times.dat',One_Level_Varnames{ivar}); - anl = sprintf('%s_anl_times.dat',One_Level_Varnames{ivar}); - main = sprintf('%s %s',plotdat.flavor,obsstring); -% otherwise -% ges = sprintf('%s_ges_times_%04dmb.dat',One_Level_Varnames{ivar},plotdat.level); -% anl = sprintf('%s_anl_times_%04dmb.dat',One_Level_Varnames{ivar},plotdat.level); -% main = sprintf('%s %s %d hPa',plotdat.flavor,obsstring,plotdat.level); -% end - - plotdat.ges = ges; - plotdat.anl = anl; - - % plot each region - - figure(ivar); orient tall; clf; wysiwyg - - for iregion = 1:length(Regions), - plotdat.title = Regions{iregion}; - plotdat.region = iregion; - Myplot(plotdat) - end - - CenterAnnotation(main); % One title in the middle - BottomAnnotation(ges); % directory in middle, bottom - - % create a postscript file - - psfname = sprintf('%s_ens_spread_time.ps',plotdat.varname); - print(ivar,'-dpsc',psfname); - -end - -path(startpath); % restore MATLABPATH to original setting - -%---------------------------------------------------------------------- -% 'Helper' functions -%---------------------------------------------------------------------- - - -function Myplot(plotdat) -% -% After the first column, each set of 3 columns -% represents a different region. -% Depends on the format written by obs_diag.f90 -% -p1 = load(plotdat.ges); p = SqueezeMissing(p1); -a1 = load(plotdat.anl); a = SqueezeMissing(a1); - -xp = p(:,1) + p(:,2)./86400 + plotdat.toff; -xa = a(:,1) + a(:,2)./86400 + plotdat.toff; - -offset = 4; % columns 1,2 are time, 3=mean, 4=spread, 5=numobs - -count = offset+(plotdat.region-1)*3; -yp_spread = p(:,count); -ya_spread = a(:,count); - -gmean = mean(yp_spread(isfinite(yp_spread))); gstring = sprintf('guess; mean=%.3f',gmean); -amean = mean(ya_spread(isfinite(ya_spread))); astring = sprintf('analysis; mean=%.3f',amean); - -subplot(plotdat.nregions,1,plotdat.region) - - plot(xp, yp_spread, 'k+-', xa, ya_spread, 'ro-', 'LineWidth', 1.5) - grid - ax = axis; ax(3) = 0.0; axis(ax) - ylabel(plotdat.ylabel, 'fontsize', 10) - title(plotdat.title,'Interpreter', 'none', 'fontsize', 12, 'FontWeight', 'bold') - h = legend(gstring, astring); - legend(h,'boxoff') - - % a slightly better way to annotate dates, etc. - ttot = max(xp) - min(xp) + 1; - if ((plotdat.bin1 > 1000) && (ttot > 32)); - datetick('x',6,'keeplimits','keepticks'); - monstr = datestr(xp(1),28); - xlabel(sprintf('month/day - %s start',monstr)) - elseif (plotdat.bin1 > 1000); - datetick('x',7); - monstr = datestr(xp(1),28); - xlabel(sprintf('day of month - %s start',monstr)) - else - xlabel('days') - end - - - - -function y = SqueezeMissing(x) - -missing = find(x < -98); % 'missing' is coded as -99 - -if isempty(missing) - y = x; -else - y = x; - y(missing) = NaN; -end - - - -function CenterAnnotation(main) -subplot('position',[0.48 0.48 0.04 0.04]) -axis off -h = text(0.5,0.5,main); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','bottom', ... - 'Interpreter','none', ... - 'FontSize',12, ... - 'FontWeight','bold') - - - -function BottomAnnotation(main) -% annotates the directory containing the data being plotted -subplot('position',[0.48 0.01 0.04 0.04]) -axis off -bob = which(main); -[pathstr,name,ext,versn] = fileparts(bob); -h = text(0.0,0.5,pathstr); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','middle',... - 'Interpreter','none',... - 'FontSize',8) Deleted: DART/trunk/diagnostics/matlab/fit_mean_spread_time.m =================================================================== --- DART/trunk/diagnostics/matlab/fit_mean_spread_time.m 2009-08-11 16:29:29 UTC (rev 4000) +++ DART/trunk/diagnostics/matlab/fit_mean_spread_time.m 2009-08-12 15:41:26 UTC (rev 4001) @@ -1,238 +0,0 @@ -function fit_mean_spread_time(ddir) -% fit_mean_spread_time(ddir) -% -% Part of the observation-space diagnostics routines. -% -% Plots the spatial mean RMSE of the ensemble mean and -% RMS of the ensemble spread as a function of time at a single -% level for several regions. This function simply plots the -% data in *ges_times_*mb.dat using metadata in ObsDiagAtts.m - both -% created by the executable 'obs_diag'. -% -% 'obs_diag' also produces a matlab-compatible file of plotting attributes: -% ObsDiagAtts.m which specifies the run-time configuration of obs_diag. -% -% ddir is an optional argument specifying the directory containing -% the data files as preprocessed by the support routines. -% -% USAGE: if the preprocessed data files are in a directory called 'plot' -% -% ddir = 'plot'; -% fit_mean_spread_time(ddir) -% -% USAGE: if the preprocessed data files are in the current directory -% -% fit_mean_spread_time - -% Data Assimilation Research Testbed -- DART -% Copyright 2004-2007, Data Assimilation Research Section -% University Corporation for Atmospheric Research -% Licensed under the GPL -- www.gpl.org/licenses/gpl.html -% -% -% $URL$ -% $Id$ -% $Revision$ -% $Date$ - -% Ensures the specified directory is searched first. -if ( nargin > 0 ) - startpath = addpath(ddir); -else - startpath = path; -end - -%---------------------------------------------------------------------- -% Defaults -%---------------------------------------------------------------------- - -datafile = 'ObsDiagAtts'; -ptypes = {'gs-','bd-','ro-','k+-'}; % for each region - -%---------------------------------------------------------------------- -% Get plotting metadata from obs_diag run. -%---------------------------------------------------------------------- - -if ( exist(datafile) == 2 ) - - eval(datafile) - - if ( exist('plevel','var') == 0 ) - plevel = 1; - iskip = iskip_days; - plotdat.toff = 0; - plotdat.bin1 = datenum(t1); - else % high dimensional models - % Coordinate between time types and dates - skip_seconds = time_to_skip(4)*3600 + time_to_skip(5)*60 + time_to_skip(6); - iskip = time_to_skip(3) + skip_seconds/86400; - plotdat.bin1 = datenum(first_bin_center); % a known date in matlab's time units - plotdat.toff = plotdat.bin1 - t1; % determine temporal offset (calendar base) - end - -else - error(sprintf('%s cannot be found.', datafile)) -end - -% set up a structure with all static plotting components -plotdat.day1 = datestr(t1+plotdat.toff+iskip,'yyyy-mm-dd HH'); -plotdat.dayN = datestr(tN+plotdat.toff,'yyyy-mm-dd HH'); -plotdat.level = plevel; -plotdat.ylabel = 'RMSE'; -plotdat.nregions = length(Regions); -plotdat.nvars = length(One_Level_Varnames); -plotdat.linewidth = 2.0; - -%---------------------------------------------------------------------- -% Loop around observation types -%---------------------------------------------------------------------- - -for ivar = 1:plotdat.nvars, - - plotdat.varname = One_Level_Varnames{ivar}; - - switch obs_select - case 1, - string1 = sprintf('%s (all data)', plotdat.varname); - case 2, - string1 = sprintf('%s (RaObs)', plotdat.varname); - otherwise, - string1 = sprintf('%s (ACARS,SATWND)', plotdat.varname); - end - -% switch One_Level_Varnames{ivar} -% case{'P'} - ges = sprintf('%s_ges_times.dat',One_Level_Varnames{ivar}); - anl = sprintf('%s_anl_times.dat',One_Level_Varnames{ivar}); - main = sprintf('%s',string1); -% otherwise -% ges = sprintf('%s_ges_times_%04dmb.dat',One_Level_Varnames{ivar},plotdat.level); -% anl = sprintf('%s_anl_times_%04dmb.dat',One_Level_Varnames{ivar},plotdat.level); -% main = sprintf('%s %d hPa',string1,plotdat.level); -% end - - plotdat.ges = ges; - plotdat.anl = anl; - - % plot by region - - figure(ivar); orient tall; clf; wysiwyg - - for iregion = 1:plotdat.nregions, - plotdat.title = Regions{iregion}; - plotdat.region = iregion; - myplot(plotdat); - end - - CenterAnnotation(main) - BottomAnnotation(ges) - - % create a postscript file - - psfname = sprintf('%s_mean_spread_time.ps',plotdat.varname); - print(ivar,'-dpsc',psfname); - -end - -path(startpath); % restore MATLABPATH to original setting - -%---------------------------------------------------------------------- -% 'Helper' functions -%---------------------------------------------------------------------- - -function myplot(plotdat) -p1 = load(plotdat.ges); p = SqueezeMissing(p1); -a1 = load(plotdat.anl); a = SqueezeMissing(a1); - -x = [1:2*size(p,1)]; % Each time has a guess and analysis -ens_mean = x; -ens_spread = x; - -countm = 3+(plotdat.region-1)*3; % pick off region mean -counts = 4+(plotdat.region-1)*3; % pick off region spread - -for itime = 1:size(p,1) - - obsT1 = p(itime,1) + p(itime,2)/86400 + plotdat.toff; - obsT2 = a(itime,1) + a(itime,2)/86400 + plotdat.toff; - x(2*itime-1) = obsT1; - x(2*itime ) = obsT2; - - ens_mean( 2*itime-1) = p(itime,countm); - ens_spread(2*itime-1) = p(itime,counts); - - ens_mean( 2*itime ) = a(itime,countm); - ens_spread(2*itime ) = a(itime,counts); -end - -subplot(plotdat.nregions,1,plotdat.region) - - % Since the mean and the spread are getting plotted - % on the same figure, we should have two axes ... - % bias on left, spread on right, for example. no time now ... - - gmean = mean(ens_mean( isfinite(ens_mean ))); - amean = mean(ens_spread(isfinite(ens_spread))); - gstring = sprintf('Ens. mean; mean=%.3f',gmean); - astring = sprintf('Ens. spread; mean=%.3f',amean); - - plot(x,ens_mean,'k+-',x,ens_spread,'ro-','LineWidth',1.5) - grid - ylabel(plotdat.ylabel, 'fontsize', 10); - title(plotdat.title, 'Interpreter', 'none', ... - 'Fontsize', 12, 'FontWeight', 'bold') - h = legend(gstring, astring); - legend(h,'boxoff') - - % a slightly better way to annotate dates, etc. - ttot = max(x) - min(x) + 1; - if ((plotdat.bin1 > 1000) && (ttot > 32)); - datetick('x',6,'keeplimits','keepticks'); - monstr = datestr(x(1),28); - xlabel(sprintf('month/day - %s start',monstr)) - elseif (plotdat.bin1 > 1000); - datetick('x',7); - monstr = datestr(x(1),28); - xlabel(sprintf('day of month - %s start',monstr)) - else - xlabel('days') - end - - - -function y = SqueezeMissing(x) - -missing = find(x < -98); % 'missing' is coded as -99 - -if isempty(missing) - y = x; -else - y = x; - y(missing) = NaN; -end - - - -function CenterAnnotation(main) -subplot('position',[0.48 0.48 0.04 0.04]) -axis off -h = text(0.5,0.5,main); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','bottom', ... - 'Interpreter','none', ... - 'FontSize',12, ... - 'FontWeight','bold') - - - -function BottomAnnotation(main) -% annotates the directory containing the data being plotted -subplot('position',[0.48 0.01 0.04 0.04]) -axis off -bob = which(main); -[pathstr,name,ext,versn] = fileparts(bob); -h = text(0.0,0.5,pathstr); -set(h,'HorizontalAlignment','center', ... - 'VerticalAlignment','middle',... - 'Interpreter','none',... - 'FontSize',8) From nancy at ucar.edu Wed Aug 12 10:51:20 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Wed, 12 Aug 2009 10:51:20 -0600 (MDT) Subject: [Dart-dev] [4002] DART/trunk: Move the contents of the top level 'converters' directory to a subdirectory Message-ID: <200908121651.n7CGpKum015438@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090812/dd392f5b/attachment-0001.html -------------- next part -------------- Deleted: DART/trunk/converters/README =================================================================== --- DART/trunk/converters/README 2009-08-12 15:41:26 UTC (rev 4001) +++ DART/trunk/converters/README 2009-08-12 16:51:20 UTC (rev 4002) @@ -1,9 +0,0 @@ - -These are conversion programs to and from Dart observation -sequence files and 3D-Var and little-r observation formats. - -Whether they work with the latest 3D-Var format is untested -at this point. Please contact the DART Development group if -you are interested in using these tools. - - Deleted: DART/trunk/converters/littler_tf_dart.f90 =================================================================== --- DART/trunk/converters/littler_tf_dart.f90 2009-08-12 15:41:26 UTC (rev 4001) +++ DART/trunk/converters/littler_tf_dart.f90 2009-08-12 16:51:20 UTC (rev 4002) @@ -1,1194 +0,0 @@ -! Data Assimilation Research Testbed -- DART -! Copyright 2004-2007, Data Assimilation Research Section -! University Corporation for Atmospheric Research -! Licensed under the GPL -- www.gpl.org/licenses/gpl.html - -PROGRAM littler_tf_dart - -! -! $URL$ -! $Id$ -! $Revision$ -! $Date$ - -use types_mod, only : r8, DEG2RAD, RAD2DEG, MISSING_I, MISSING_R8 -use utilities_mod, only : open_file, close_file, file_exist, & - get_unit, initialize_utilities, & - register_module, error_handler, E_ERR, E_MSG, & - timestamp, logfileunit -use obs_sequence_mod, only : obs_type, obs_sequence_type, init_obs_sequence, & - insert_obs_in_seq, write_obs_seq, read_obs_seq, & - set_qc, set_obs_values, set_copy_meta_data, & - assignment(=), get_obs_time_range, & - init_obs, static_init_obs_sequence, get_num_qc, set_obs_def, & - get_num_obs, get_max_num_obs, get_obs_values, & - get_time_range_keys, get_obs_from_key, get_obs_def, get_qc -use obs_def_mod, only : copy_obs_def, obs_def_type, & - get_obs_def_time, get_obs_def_location, & - get_obs_def_error_variance, get_obs_kind, & - set_obs_def_kind, set_obs_def_location, set_obs_def_time, & - set_obs_def_error_variance -use obs_kind_mod, only : RADIOSONDE_U_WIND_COMPONENT, & - RADIOSONDE_V_WIND_COMPONENT, & - RADIOSONDE_SURFACE_PRESSURE, & - RADIOSONDE_TEMPERATURE, & - RADIOSONDE_SPECIFIC_HUMIDITY, & - max_obs_kinds, get_obs_kind_name, map_def_index -use location_mod, only : location_type, get_location, query_location, set_location -use time_manager_mod, only : time_type, get_time, set_calendar_type, GREGORIAN, get_date, & - set_date, operator(/=), set_time - -implicit none - -! version controlled file description for error handling, do not edit -character(len=128), parameter :: & - source = "$URL$", & - revision = "$Revision$", & - revdate = "$Date$" - -type(obs_sequence_type) :: dart_seq -type(obs_type) :: obs, prev_obs -type(obs_def_type) :: obs_def -type(location_type) :: location -type(time_type) :: time, stime, ftime - -INTEGER :: iunit, end_of_file - -integer :: key_bounds(2), obs_kind, which_vert, pwhich_vert -real(r8) :: obs_value(1), qc(1), erms -real(r8), dimension(3) :: loc, sloc, floc -real(r8) :: lon, lat, vloc, pvloc - -integer :: is, ie, iobs, k -integer :: num_obs, num_copies, num_qc, max_num_obs, dart_seq_num_obs, num_obs_in_set -integer, allocatable :: keys(:) - -character(len = 32) :: obs_name, obs_no_support(max_obs_kinds) -character(len = 129) :: msgstring - -integer :: n_no_support - -character(len = 129) :: dart_file_name = 'obs_seq.out', & - littler_file_name = 'little-r.dat', & - copy_meta_data - -integer :: calendar_type = GREGORIAN - -character *20 :: date_char -CHARACTER *120 :: rpt_format -CHARACTER *120 :: meas_format -CHARACTER *120 :: end_format -character *40 :: tst_id, tst_name, tst_pltfrm, tst_src -real(r8) :: tst_ter, tst_slp, tst_xlat, tst_xlon, tst_Psfc -integer :: kx, iseq_num, tst_sut, tst_julian -logical :: tst_sound, tst_bogus, tst_discard -integer :: i1,i2,i3,i4,i5,i6,i7,i8,i9,i10 -integer :: i11,i12,i13,i14,i15,i16,i17,i18 -real(r8) :: f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12 - -integer, parameter :: n_wind_pres = 26, n_pres = 15 -real(r8) :: wind_error(n_wind_pres) -real(r8) :: temp_error(n_pres), specific_humidity_error(n_pres) - -! Observational errors are contained in a separate file 'obserr.txt' - -CHARACTER (LEN=80) :: filein != 'obserr.txt' -CHARACTER (LEN=80) :: platform != 'RAOBS' -CHARACTER (LEN=80) :: sensor_name != 'WIND SENSOR ERRORS' - -integer :: wind_pressures(n_wind_pres) -data wind_pressures / 10, 20, 30, 40, 50, 100, 150, & - 200, 250, 300, 350, 400, 450, 500, & - 550, 600, 650, 700, 750, 800, 850, & - 900, 950, 1000, 1050, 1100/ - -integer :: pressure_levels(n_pres) -data pressure_levels / 1000, 850, 700, 500, 400, & - 300, 250, 200, 150, 100, & - 70, 50, 30, 20, 10/ - - -real(r8), allocatable :: z(:),t(:),td(:),spd(:),dir(:), & - uu(:), vv(:), p(:), cld(:), ciel(:) -integer, allocatable :: zpp_qc(:), tt_qc(:), td_qc(:), & - zuu_qc(:), zvv_qc(:), p_qc(:), & - spd_qc(:), dir_qc(:), cld_qc(:), ciel_qc(:) - -logical :: littler_to_dart, out_of_range - -!------------------------------------------------------------------------------ - -rpt_format = ' ( 2f20.5 , 4a40 , f20.5 , 5i10 , 3L10 , ' & - // ' 2i10 , a20 , 13( f13.5 , i7 ) ) ' -meas_format = ' ( 10( f13.5 , i7 ) ) ' -end_format = ' ( 3 ( i7 ) ) ' - -call initialize_utilities('littler_tf_dart') -call register_module(source, revision, revdate) - -call set_calendar_type(calendar_type) - -write(*,*) 'littler to DART (.true./T) or DART to littler (.false./F)?' - -read(*,*) littler_to_dart - -tst_id = 'dart_id' -tst_name = 'dart_name' -tst_pltfrm = 'dart_pltfrm' -tst_src = 'dart_src' -tst_ter = MISSING_R8 -tst_bogus = .false. -tst_discard = .false. -tst_slp = MISSING_R8 -i1 = 0 -i2 = 0 -iseq_num = 0 -i3 = 0 -tst_sut = MISSING_I -tst_julian = MISSING_I -i6 = 0 -i7 = 0 -i8 = 0 -i9 = 0 -i10 = 0 -i11 = 0 -i12 = 0 -i13 = 0 -i14 = 0 -i15 = 0 -i16 = 0 -i17 = 0 -i18 = 0 -f1 = MISSING_R8 -f2 = MISSING_R8 -f3 = MISSING_R8 -f4 = MISSING_R8 -f5 = MISSING_R8 -f6 = MISSING_R8 -f7 = MISSING_R8 -f8 = MISSING_R8 -f9 = MISSING_R8 -f10 = MISSING_R8 -f11 = MISSING_R8 -f12 = MISSING_R8 -wind_error(:) = -1.0_R8 -temp_error(:) = -1.0_R8 -specific_humidity_error(:) = -1.0_R8 -n_no_support = 0 - -call static_init_obs_sequence() - -num_copies = 1 -num_qc = 0 - -! must use read_obs_seq_header - -call init_obs(obs, num_copies, num_qc) - -! ------------------------------------------------------------------- -! Initialize the counter: - -num_obs = 0 - -if(.not. littler_to_dart) then - - ! Conversion from DART to littler format. - ! littler format needs soundings - - call read_obs_seq(dart_file_name, 0, 0, 0, dart_seq) - - dart_seq_num_obs = get_num_obs(dart_seq) - stime = set_time(0, 0) - ftime = set_time(0, 200000) - call get_obs_time_range(dart_seq, stime, ftime, key_bounds, num_obs_in_set, & - out_of_range) - if(num_obs_in_set /= dart_seq_num_obs) then - write(msgstring, *) 'Did not get all obs. Got ',num_obs_in_set, & - '. In file: ',dart_seq_num_obs - call error_handler(E_ERR,'littler_tf_dart', & - msgstring,source,revision,revdate) - endif - allocate(keys(dart_seq_num_obs)) - - call get_time_range_keys(dart_seq, key_bounds, dart_seq_num_obs, keys) - - ! This should be get_first_obs(), get_last_obs() - - print*,'First obs key: ',keys(1) - print*,'Last obs key: ',keys(dart_seq_num_obs) - print*,'Number of obs: ',dart_seq_num_obs - - iunit = get_unit() - open(unit=iunit,file=littler_file_name,status='new') - - is = 1 - ie = 1 - do while (ie <= dart_seq_num_obs+1) - - call get_obs_from_key(dart_seq, keys(is), obs) - call get_obs_def(obs, obs_def) - - sloc = get_location(get_obs_def_location(obs_def)) - stime = get_obs_def_time(obs_def) - - if(ie <= dart_seq_num_obs) then - call get_obs_from_key(dart_seq, keys(ie), obs) - call get_obs_def(obs, obs_def) - endif - - floc = get_location(get_obs_def_location(obs_def)) - ftime = get_obs_def_time(obs_def) - - ! Write to littler file when a full sounding has been read. - - if ( ftime /= stime .or. sloc(1) /= floc(1) .or. & - sloc(2) /= floc(2) .or. ie == dart_seq_num_obs+1) then - - tst_Psfc = MISSING_R8 - - kx = 1 - call get_obs_from_key(dart_seq, keys(is), obs) - call get_obs_def(obs, obs_def) - location = get_obs_def_location(obs_def) - loc = get_location(location) - pwhich_vert = nint(query_location(location,'which_vert')) - pvloc = loc(3) - - ! Count the number of pressure levels. - - do iobs = is+1, ie-1 - call get_obs_from_key(dart_seq, keys(iobs), obs) - call get_obs_def(obs, obs_def) - location = get_obs_def_location(obs_def) - loc = get_location(location) - which_vert = nint(query_location(location,'which_vert')) - -!!$ if (which_vert == -1) then -!!$ obs_kind = map_def_index(get_obs_kind(obs_def)) -!!$ if (obs_kind == RADIOSONDE_SURFACE_PRESSURE) then -!!$ call get_obs_values(obs, obs_value, 1) -!!$ tst_Psfc = obs_value(1) -!!$ endif -!!$ endif - - if (loc(3) /= pvloc .and. which_vert == pwhich_vert) kx = kx + 1 - pvloc = loc(3) - pwhich_vert = which_vert - enddo - -!!$ if (kx > 1) then - obs_kind = map_def_index(get_obs_kind(obs_def)) - obs_name = get_obs_kind_name(obs_kind) - if ( obs_name(1:10) == 'RADIOSONDE' ) then - tst_sound = .true. - tst_pltfrm = 'FM-35 TEMP' -!!$ else -!!$ tst_sound = .false. - endif - - call set_str_date(date_char, stime) - - ! In littler format, longitude is defined within [-180,180]. - - tst_xlat = loc(2) - tst_xlon = loc(1) - if (tst_xlon > 180.0_r8) tst_xlon = tst_xlon - 360.0_r8 - - ! Now the header can be written. - - WRITE ( UNIT = iunit , ERR = 19 , FMT = rpt_format ) & - tst_xlat, tst_xlon, tst_id , tst_name, & - tst_pltfrm, tst_src, tst_ter, kx, i1, i2, iseq_num, i3, & - tst_sound, tst_bogus, tst_discard, tst_sut, tst_julian, date_char, & - tst_slp, i6, f1, i7, f2, i8, f3, i9, tst_Psfc, i10, & - f5, i11, f6, i12, f7, i13, f8, i14, f9, i15, & - f10, i16, f11, i17, f12, i18 - - allocate(p(kx),p_qc(kx), z(kx),zpp_qc(kx), t(kx),tt_qc(kx), td(kx),td_qc(kx), & - spd(kx),spd_qc(kx), dir(kx),dir_qc(kx), & - uu(kx),zuu_qc(kx), vv(kx),zvv_qc(kx), cld(kx),cld_qc(kx), & - ciel(kx),ciel_qc(kx)) - - p(:) = MISSING_R8 - z(:) = MISSING_R8 - t(:) = MISSING_R8 - td(:) = MISSING_R8 - spd(:) = MISSING_R8 - dir(:) = MISSING_R8 - uu(:) = MISSING_R8 - vv(:) = MISSING_R8 - cld(:) = MISSING_R8 - ciel(:) = MISSING_R8 - - p_qc(:) = 0 - zpp_qc(:) = 0 - tt_qc(:) = 0 - td_qc(:) = 0 - spd_qc(:) = 0 - dir_qc(:) = 0 - zuu_qc(:) = 0 - zvv_qc(:) = 0 - cld_qc(:) = 0 - ciel_qc(:) = 0 - - ! Write data at each (pressure) level. - - k = 1 - call get_obs_from_key(dart_seq, keys(is), obs) - call get_obs_def(obs, obs_def) - location = get_obs_def_location(obs_def) - loc = get_location(location) - pwhich_vert = nint(query_location(location,'which_vert')) - pvloc = loc(3) - do iobs = is, ie-1 - call get_obs_from_key(dart_seq, keys(iobs), obs) - call get_obs_def(obs, obs_def) - location = get_obs_def_location(obs_def) - loc = get_location(location) - which_vert = nint(query_location(location,'which_vert')) - - if (loc(3) /= pvloc .and. which_vert == pwhich_vert) k = k + 1 - pvloc = loc(3) - pwhich_vert = which_vert - - if(which_vert == 2) then - p(k) = loc(3) -!-------------------------------------------------------------------------- -! Flaging all data above 100 hPa. -!-------------------------------------------------------------------------- -!!$ if(p(k) < 10000.0_r8) then -!!$ p_qc(k) = MISSING_I -!!$ zpp_qc(k) = MISSING_I -!!$ tt_qc(k) = MISSING_I -!!$ td_qc(k) = MISSING_I -!!$ spd_qc(k) = MISSING_I -!!$ dir_qc(k) = MISSING_I -!!$ zuu_qc(k) = MISSING_I -!!$ zvv_qc(k) = MISSING_I -!!$ cld_qc(k) = MISSING_I -!!$ ciel_qc(k) = MISSING_I -!!$ endif - elseif(which_vert == 3) then - z(k) = loc(3) - endif - - obs_kind = map_def_index(get_obs_kind(obs_def)) - - call get_obs_values(obs, obs_value, 1) - if(obs_kind == RADIOSONDE_U_WIND_COMPONENT) then - num_obs = num_obs + 1 - uu(k) = obs_value(1) - elseif(obs_kind == RADIOSONDE_V_WIND_COMPONENT) then - num_obs = num_obs + 1 - vv(k) = obs_value(1) - if(p(k) /= MISSING_R8) then - call StoreObsErr(get_obs_def_error_variance(obs_def), & - nint(0.01_r8 * p(k)), wind_pressures, n_wind_pres, wind_error) - endif - elseif(obs_kind == RADIOSONDE_TEMPERATURE) then - num_obs = num_obs + 1 - t(k) = obs_value(1) - if(p(k) /= MISSING_R8) then - call StoreObsErr(get_obs_def_error_variance(obs_def), & - nint(0.01_r8 * p(k)), pressure_levels, n_pres, temp_error) - endif -!!$ elseif(obs_kind == RADIOSONDE_SPECIFIC_HUMIDITY) then -!!$ num_obs = num_obs + 1 -!!$ t(k) = obs_value(1) -!!$ if(p(k) /= MISSING_R8) then -!!$ call StoreObsErr(1.0e6_r8*get_obs_def_error_variance(obs_def), & -!!$ nint(0.01_r8 * p(k)), pressure_levels, n_pres, specific_humidity_error) -!!$ endif -!!$ elseif(obs_kind == RADIOSONDE_SURFACE_PRESSURE) then -!!$ num_obs = num_obs + 1 - else - if (n_no_support == 0) then - n_no_support = n_no_support + 1 - obs_no_support(n_no_support) = get_obs_kind_name(obs_kind) - elseif (obs_no_support(n_no_support) /= get_obs_kind_name(obs_kind)) then - n_no_support = n_no_support + 1 - obs_no_support(n_no_support) = get_obs_kind_name(obs_kind) - endif - endif - enddo - - do k = 1 , kx - - ! Convert zonal and meridional wind components to - ! wind speed and direction. - - if (uu(k) /= missing_r8 .and. vv(k) /= missing_r8) then - - spd(k) = sqrt(uu(k)*uu(k) + vv(k)*vv(k)) - - if (spd(k) /= 0.0_r8) then - - if (vv(k) == 0.0_r8) then - - if (uu(k) > 0.0_r8) dir(k) = 270.0_r8 - if (uu(k) < 0.0_r8) dir(k) = 90.0_r8 - - else - - dir(k) = atan(uu(k)/vv(k))*RAD2DEG - - if (vv(k) >= 0.0_r8) then - dir(k) = dir(k) + 180.0_r8 - else - if (uu(k) >= 0.0_r8) dir(k) = dir(k) + 360.0_r8 - endif - - endif - - else - - dir(k) = 0.0_r8 - - endif - - endif - - WRITE ( UNIT = iunit , ERR = 20 , FMT = meas_format ) & - p(k),0, z(k),zpp_qc(k), t(k),tt_qc(k),td(k),td_qc(k), & - spd(k),zvv_qc(k), dir(k),zuu_qc(k), & - uu(k),zuu_qc(k), vv(k),zvv_qc(k), MISSING_R8,0, MISSING_R8,0 - - enddo - - ! Write "footer" of the sounding. - - WRITE ( UNIT = iunit , ERR = 21 , FMT = meas_format ) & - -777777.,0, -777777.,0,float(kx),0, & - MISSING_R8,0, MISSING_R8,0, MISSING_R8,0, & - MISSING_R8,0, MISSING_R8,0, MISSING_R8,0, MISSING_R8,0 - - WRITE ( UNIT = iunit , ERR = 21 , FMT = end_format ) kx, 0, 0 - - deallocate(p,p_qc, z,zpp_qc, t,tt_qc, td,td_qc, & - spd,spd_qc, dir,dir_qc, & - uu,zuu_qc, vv,zvv_qc, cld,cld_qc, & - ciel,ciel_qc) - - is = ie - - endif - - ie = ie + 1 - - enddo - - deallocate(keys) - - close(iunit) - - ! Write out the obserr.txt. - - open(unit=iunit,file='obserr.txt',status='new') - - write(iunit, FMT = ' ( 7f6.1 , " BOGUS WIND SENSOR ERRORS" ) ') wind_error(1:7) - write(iunit, FMT = ' ( 7f6.1 , " :" ) ') wind_error(8:14) - write(iunit, FMT = ' ( 7f6.1 , " :" ) ') wind_error(15:21) - write(iunit, FMT = ' ( 7f6.1 , " :" ) ') wind_error(22:26),wind_error(26),wind_error(26) - write(iunit, FMT = ' ( 7f6.1 , " RAOBS" ) ') wind_error(1:7) - write(iunit, FMT = ' ( 7f6.1 , " :" ) ') wind_error(8:14) - write(iunit, FMT = ' ( 7f6.1 , " :" ) ') wind_error(15:21) - write(iunit, FMT = ' ( 7f6.1 , " :" ) ') wind_error(22:26),wind_error(26),wind_error(26) - write(iunit, FMT = ' ( 5f6.1 , " BOGUS TEMP SENSOR ERRORS" ) ') temp_error(1:5) - write(iunit, FMT = ' ( 5f6.1 , " :" ) ') temp_error(6:10) - write(iunit, FMT = ' ( 5f6.1 , " :" ) ') temp_error(11:15) - write(iunit, FMT = ' ( 5f6.1 , " RAOBS" ) ') temp_error(1:5) - write(iunit, FMT = ' ( 5f6.1 , " :" ) ') temp_error(6:10) - write(iunit, FMT = ' ( 5f6.1 , " :" ) ') temp_error(11:15) - write(iunit, FMT = ' ( 5f6.2 , " BOGUS SPECIFIC HUMIDITY SENSOR ERRORS" ) ') specific_humidity_error(1:5) - write(iunit, FMT = ' ( 5f6.2 , " :" ) ') specific_humidity_error(6:10) - write(iunit, FMT = ' ( 5f6.2 , " :" ) ') specific_humidity_error(11:15) - write(iunit, FMT = ' ( 5f6.2 , " RAOBS" ) ') specific_humidity_error(1:5) - write(iunit, FMT = ' ( 5f6.2 , " :" ) ') specific_humidity_error(6:10) - write(iunit, FMT = ' ( 5f6.2 , " :" ) ') specific_humidity_error(11:15) - - close(iunit) - - if (n_no_support /= 0) then - - write(*,*) 'Observations not supported yet:' - do k = 1 , n_no_support - write(*,*) k,'. ',trim(adjustl(obs_no_support(k))) - enddo - - endif - -else - - ! Conversion from littler to DART format. - - ! Read in the observational errors from file 'obserr.txt'. - - filein = 'obserr.txt' - platform = 'RAOBS' - sensor_name = 'WIND SENSOR ERRORS' - call READ_OBSERR (filein, platform, sensor_name, wind_error, n_wind_pres) - sensor_name = 'TEMP SENSOR ERRORS' - call READ_OBSERR (filein, platform, sensor_name, temp_error, n_pres) - - max_num_obs = 500000 - - ! Initialize an obs_sequence structure - call init_obs_sequence(dart_seq, num_copies, num_qc, max_num_obs) - - copy_meta_data = 'littler observations' - call set_copy_meta_data(dart_seq, 1, copy_meta_data) - - iunit = open_file(littler_file_name, action = 'read') - - end_of_file=0 - - ! Read littler until end of file. - - do while (end_of_file == 0) - - ! Read header of sounding. - - READ ( UNIT=iunit,ERR=19,FMT=rpt_format,iostat=end_of_file,end=25 ) & - tst_xlat, tst_xlon, tst_id, tst_name, & - tst_pltfrm, tst_src, tst_ter, kx, i1, i2, iseq_num, i3, & - tst_sound, tst_bogus, tst_discard, tst_sut, tst_julian, date_char, & - tst_slp, i6, f1,i7, f2,i8, f3,i9, tst_Psfc,i10, f5,i11, & - f6,i12, f7,i13, f8,i14, f9,i15, f10,i16, f11,i17, f12,i18 - - allocate(p(kx),p_qc(kx), z(kx),zpp_qc(kx), t(kx),tt_qc(kx), td(kx),td_qc(kx), & - spd(kx),spd_qc(kx), dir(kx),dir_qc(kx), & - uu(kx),zuu_qc(kx), vv(kx),zvv_qc(kx), cld(kx),cld_qc(kx), & - ciel(kx),ciel_qc(kx)) - - if (.not. tst_sound ) kx = 1 - - ! Read each level of the sounding. - - do k = 1 , kx - READ (UNIT=iunit,ERR=20,FMT=meas_format,iostat=end_of_file,end=25) & - p(k),p_qc(k), z(k),zpp_qc(k), t(k),tt_qc(k), & - td(k),td_qc(k), & - spd(k),spd_qc(k), dir(k),dir_qc(k), & - uu(k),zuu_qc(k), vv(k),zvv_qc(k), cld(k),cld_qc(k), & - ciel(k),ciel_qc(k) - - if (p(k) /= missing_r8) then - - vloc = p(k) - which_vert = 2 - -!!$ elseif (z(k)/= missing_r8) then -!!$ -!!$ vloc = p(k) -!!$ which_vert = 3 -!!$ - else - - call error_handler(E_ERR,'littler_tf_dart', & - 'No vertical coordinate.', source, revision, revdate) - - endif - - ! In DART format, longitude is defined within [0, 360]. - - if(tst_xlon < 0.0_r8) tst_xlon = tst_xlon + 360.0_r8 - lon = tst_xlon - lat = tst_xlat - - location = set_location(lon, lat, vloc, which_vert) - call set_obs_def_location(obs_def, location) - - call set_dart_time(date_char, time) - call set_obs_def_time(obs_def, time) - - ! Insert obs into DART obs sequence. - - ! Observational errors are interpolated from data - ! in obserr.txt - - if (t(k) /= missing_r8) then - - if (tst_pltfrm == 'FM-35 TEMP') then - - num_obs = num_obs + 1 - - call set_obs_def_kind(obs_def, RADIOSONDE_TEMPERATURE) - - erms = intplog (p(k)*0.01_r8, pressure_levels, temp_error) - - call set_obs_def_error_variance(obs_def, erms*erms) - - call set_obs_def(obs, obs_def) - - obs_value(1) = t(k) - call set_obs_values(obs, obs_value) -!!$ qc(1) = tt_qc(k) -!!$ call set_qc(obs, qc) - - if(num_obs == 1) then - call insert_obs_in_seq(dart_seq, obs) - else - call insert_obs_in_seq(dart_seq, obs, prev_obs) - endif - - prev_obs = obs - - endif - - endif - - ! Littler may carry wind speed and direction: - ! convert to zonal and meridional wind components. - - if (uu(k) == missing_r8 .and. vv(k) == missing_r8 .and. & - spd(k) /= missing_r8 .and. dir(k) /= missing_r8) then - - dir(k) = dir(k)*DEG2RAD - uu(k) = -spd(k)*SIN(dir(k)) - vv(k) = -spd(k)*COS(dir(k)) - - endif - - if (uu(k) /= missing_r8) then - - if (tst_pltfrm == 'FM-35 TEMP') then - - num_obs = num_obs + 1 - - call set_obs_def_kind(obs_def, RADIOSONDE_U_WIND_COMPONENT) - - erms = intplin (p(k)*0.01_r8, wind_pressures, wind_error) - - call set_obs_def_error_variance(obs_def, erms*erms) - - call set_obs_def(obs, obs_def) - - obs_value(1) = uu(k) - call set_obs_values(obs, obs_value) -!!$ qc(1) = zuu_qc(k) -!!$ call set_qc(obs, qc) - - if(num_obs == 1) then - call insert_obs_in_seq(dart_seq, obs) - else - call insert_obs_in_seq(dart_seq, obs, prev_obs) - endif - - prev_obs = obs - - endif - - endif - - if (vv(k) /= missing_r8) then - - if (tst_pltfrm == 'FM-35 TEMP') then - - num_obs = num_obs + 1 - - call set_obs_def_kind(obs_def, RADIOSONDE_V_WIND_COMPONENT) - - erms = intplin (p(k)*0.01_r8, wind_pressures, wind_error) - - call set_obs_def_error_variance(obs_def, erms*erms) - - call set_obs_def(obs, obs_def) - - obs_value(1) = vv(k) - call set_obs_values(obs, obs_value, 1) -!!$ qc(1) = zvv_qc(k) -!!$ call set_qc(obs, qc) - - if(num_obs == 1) then - call insert_obs_in_seq(dart_seq, obs) - else - call insert_obs_in_seq(dart_seq, obs, prev_obs) - endif - - prev_obs = obs - - endif - - endif - - enddo - - deallocate(p,p_qc, z,zpp_qc, t,tt_qc, td,td_qc, & - spd,spd_qc, dir,dir_qc, & - uu,zuu_qc, vv,zvv_qc, cld,cld_qc, & - ciel,ciel_qc) - - READ ( UNIT = iunit , ERR = 21 , FMT = meas_format ) & - f1,i1, f2,i2, f3,i3, f4,i4, f5,i5, f6,i6, & - f7,i7, f8,i8, f9,i9, f10,i10 - - READ ( UNIT = iunit , ERR = 21 , FMT = end_format ) kx, i1, i2 - - enddo - -25 print*,"FOUND END" - - close(iunit) - -! Write out the sequence - call write_obs_seq(dart_seq, dart_file_name) - -endif - -write(unit=*, fmt='(5x,a,i7)') & - 'Total number of observations: ', num_obs - -goto 26 - -! These are for error messages when regarding littler files. - -19 continue -call error_handler(E_ERR,'littler_tf_dart', & - 'Error when reading or writing header of sounding.', source, revision, revdate) -20 continue -call error_handler(E_ERR,'littler_tf_dart', & - 'Error when reading or writing sounding.', source, revision, revdate) -21 continue -call error_handler(E_ERR,'littler_tf_dart', & - 'Error when reading or writing footer of the sounding.', source, revision, revdate) - -26 continue - -write(logfileunit,*)'FINISHED littler_tf_dart.' -write(logfileunit,*) - -call timestamp(source,revision,revdate,'end') ! That closes the log file, too. - -contains - -!####################################################### - -subroutine set_str_date(timestring, dart_time) - -implicit none - -type(time_type), intent(in) :: dart_time -character(len=20), intent(out) :: timestring - -integer :: year, month, day, hour, minute, second - -character(len=4) :: ch_year -character(len=2) :: ch_month, ch_day, ch_hour, ch_minute, ch_second - -call get_date(dart_time, year, month, day, hour, minute, second) - -write(ch_year,'(i4)') year -write(ch_month,'(i2.2)') month -write(ch_day,'(i2.2)') day -write(ch_hour,'(i2.2)') hour -write(ch_minute,'(i2.2)') minute -write(ch_second,'(i2.2)') second - -timestring(1:6) = " " -timestring(7:10) = ch_year -timestring(11:12) = ch_month -timestring(13:14) = ch_day -timestring(15:16) = ch_hour -timestring(17:18) = ch_minute -timestring(19:20) = ch_second - -end subroutine set_str_date - -!####################################################### - -subroutine set_dart_time(tstring, dart_time) - -implicit none - -type(time_type), intent(out) :: dart_time -character(len=20), intent(in) :: tstring - -integer :: year, month, day, hour, minute, second - -read(tstring(7:10),'(i4)') year -read(tstring(11:12),'(i2)') month -read(tstring(13:14),'(i2)') day -read(tstring(15:16),'(i2)') hour -read(tstring(17:18),'(i2)') minute -read(tstring(19:20),'(i2)') second - -dart_time = set_date(year, month, day, hour, minute, second) - -end subroutine set_dart_time - -!####################################################### - -Subroutine StoreObsErr(obs_err_var, pres, plevel, nlev, obs_err_std) - -implicit none - -integer, intent(in) :: nlev, pres -real(r8), intent(in) :: obs_err_var -integer, intent(in) :: plevel(nlev) -real(r8), intent(inout) :: obs_err_std(nlev) - -integer :: level_index - - -level_index = GetClosestLevel(pres, plevel, nlev) - -if ( plevel(level_index) == pres ) then - if ( obs_err_std(level_index) == -1.0_R8 ) then - obs_err_std(level_index) = sqrt(obs_err_var) - elseif (obs_err_std(level_index) /= sqrt(obs_err_var)) then - print*,'Various observation errors at same level: ', & - obs_err_std(level_index), sqrt(obs_err_var), ' level = ',pres - endif -endif - -end Subroutine StoreObsErr - -!####################################################### - -Function GetClosestLevel(ilev, vlev, nlev) result (level_index) - -implicit none - -integer, intent(in) :: nlev, ilev -integer, intent(in) :: vlev(nlev) - -integer :: level_index, a(1) -integer, dimension(nlev) :: dx - -dx = abs(ilev - vlev) -a = minloc(dx) -level_index = a(1) - -end Function GetClosestLevel - -!####################################################### - -SUBROUTINE READ_OBSERR (filein, platform, sensor_name, err, nlevels) -!------------------------------------------------------------------------------! -! -! Read observational error on pressure levels (in hPa) -! -!------------------------------------------------------------------------------! - IMPLICIT NONE -!------------------------------------------------------------------------------! - - CHARACTER (LEN=80), intent(in) :: filein != 'obserr.txt' - CHARACTER (LEN=80), intent(in) :: platform != 'RAOBS' - CHARACTER (LEN=80), intent(in) :: sensor_name != 'WIND SENSOR ERRORS' - INTEGER, intent(in) :: nlevels - - REAL(r8), intent(out) :: err(nlevels) - - character(len=129) :: msgstring - INTEGER :: io_error, i, iunit, ncol - CHARACTER (LEN=80) :: fmt_err != '(5(1X,F5.1))' - CHARACTER (LEN=80) :: line1, line2, line3, line4 - LOGICAL :: sensor_found, found - -!------------------------------------------------------------------------------! - -! 1. OPEN INPUT FILE -! =================== - - iunit = get_unit() - OPEN (UNIT = iunit , FILE = filein , FORM = 'FORMATTED' , & - ACTION = 'READ' , STATUS = 'OLD', IOSTAT = io_error) - - IF (io_error /= 0) THEN - write(msgstring, *) 'Unable to open input observational error file ',TRIM (filein) - call error_handler(E_ERR,'READ_OBSERR', & - msgstring, source, revision, revdate) - ENDIF - - -! 2. READ DATA -! ============= - -! Read file until sensor_name is found - found = .FALSE. - sensor_found = .FALSE. - io_error= 0 - - DO WHILE (io_error == 0.) - - READ (UNIT = iunit, IOSTAT = io_error, FMT = '(A)') line1 - ! Exit when error or at end of file - - IF (io_error /= 0 .OR. (line1 (1:2) == '*.')) EXIT - - IF (TRIM (sensor (line1)) == 'BOGUS') THEN - - IF (TRIM (obstype (line1)) == TRIM (sensor_name)) sensor_found = .TRUE. - - ENDIF - - IF (sensor_found .and. (TRIM (sensor (line1)) == TRIM (platform))) THEN - - found = .TRUE. - READ (UNIT = iunit, IOSTAT = io_error, FMT = '(A)') line2 - READ (UNIT = iunit, IOSTAT = io_error, FMT = '(A)') line3 - IF (TRIM (sensor_name) == 'WIND SENSOR ERRORS') & - READ (UNIT = iunit, IOSTAT = io_error, FMT = '(A)') line4 - EXIT - - ELSE - - ! If obstype is not found, keep on reading - - CYCLE - - ENDIF - - ENDDO - - IF (found) THEN - - ! Sensor_name has been found, Error at mandatory pressure levels follow - ! Break down data upon obs type - - SELECT CASE (TRIM (sensor_name)) - CASE ('WIND SENSOR ERRORS') - ncol = 7 - fmt_err = '(7(1X,F5.1))' - CASE ('RH SENSOR ERRORS') - ncol = 5 - fmt_err = '(5(1X,F5.2))' - CASE DEFAULT - ncol = 5 - fmt_err = '(5(1X,F5.1))' - END SELECT - - READ (line1, fmt_err) (err (i), i = 1, ncol) - READ (line2, fmt_err) (err (i), i = ncol+1, 2*ncol) - READ (line3, fmt_err) (err (i), i = 2*ncol+1, 3*ncol) - ! Winds are given over 4 lines, any other data are given over 3 lines - IF (TRIM (sensor_name) == 'WIND SENSOR ERRORS') & - READ (line4, fmt_err) (err (i), i = 3*ncol+1, min(4*ncol,nlevels)) - - ELSE - - WRITE (*, FMT = '(/,A,A,A,/)') TRIM (sensor_name), & - ' were not found in file ', TRIM (filein) - - ENDIF - - -! 3. CLOSE INPUT FILE -! ==================== - - CLOSE (UNIT = iunit) - -END SUBROUTINE READ_OBSERR - -!####################################################### - -FUNCTION obstype (line) RESULT (f_obstype) -!------------------------------------------------------------------------------! - - ! Read in a line the string present after keyword 'BOGUS' - -!------------------------------------------------------------------------------! - IMPLICIT NONE - CHARACTER (LEN= 80), intent(in) :: line - - CHARACTER (LEN= 80) :: f_obstype - INTEGER :: b,c -!------------------------------------------------------------------------------! - -! Find keyword bogus - - DO c = 1, LEN_TRIM (line) - 5 - IF (line (c:c+4) == 'BOGUS') EXIT - ENDDO - - c = c + 5 - -! Skip blank until next word - - DO b = c, LEN_TRIM (line) - IF (line (b:b) /= ' ') EXIT - ENDDO - -! String follows - - f_obstype = TRIM (line (b:LEN_TRIM (line))) - -END FUNCTION obstype - -!####################################################### - -FUNCTION sensor (line) RESULT (f_sensor) - - ! Read first in a string after numbers - -!------------------------------------------------------------------------------! - IMPLICIT NONE - CHARACTER (LEN= 80), intent(in) :: line - - CHARACTER (LEN= 80) :: f_sensor - INTEGER :: b,c -!------------------------------------------------------------------------------! - -! Find the first non-blank, non point and non-number character - - DO c = 1, LEN_TRIM (line) - IF (((iachar (line(c:c)) /= 32) .AND. & - (iachar (line(c:c)) /= 46)) .AND. & - ((iachar (line(c:c)) .LT. 48) .OR. & - (iachar (line(c:c)) .GT. 57))) & - EXIT - ENDDO - - DO b = c, LEN_TRIM (line) - IF (line (b:b) == ' ') EXIT - ENDDO - - f_sensor = line (c:b-1) - -END FUNCTION sensor - -!####################################################### - -FUNCTION intplin (x,xx,yy) RESULT (val) -!------------------------------------------------------------------------------! - IMPLICIT NONE - - INTEGER, DIMENSION (:), intent(in) :: xx - REAL(r8), DIMENSION (:), intent(in) :: yy - REAL(r8), intent(in) :: x - - REAL(r8) :: val - - INTEGER :: n,m,jl -!------------------------------------------------------------------------------! - - n = size (xx) - m = size (yy) - - IF (n /= m) THEN - call error_handler(E_ERR,'intplin', & - 'arrays xx and yy must have same size', source,revision,revdate) - ENDIF - - jl = locate (x,xx) - - IF (jl .LE. 0) THEN - if (yy (1) >= 0.0_r8) then - val = yy (1) - else - call error_handler(E_ERR,'intplin', & - 'bad value in yy(1)', source,revision,revdate) - endif - ELSE IF (jl .GE. n) THEN - if (yy (n) >= 0.0_r8) then - val = yy (n) - else - call error_handler(E_ERR,'intplin', & - 'bad value in yy(n)', source,revision,revdate) - endif - ELSE - if (yy (jl) >= 0.0_r8 .and. yy (jl+1) >= 0.0_r8) then - val = (xx (jl+1) - x) * yy (jl) + (x - xx (jl)) * yy (jl+1) - val = val / (xx (jl+1) - xx (jl)) - else - call error_handler(E_ERR,'intplin', & - 'bad value in yy(jl) or yy(jl+1)', source,revision,revdate) - endif - ENDIF - -END FUNCTION intplin - -!####################################################### - -FUNCTION intplog (x,xx,yy) RESULT (val) -!------------------------------------------------------------------------------! - IMPLICIT NONE - - INTEGER, DIMENSION (:), intent(in) :: xx - REAL(r8), DIMENSION (:), intent(in) :: yy - REAL(r8), intent(in) :: x - - REAL(r8) :: val - - INTEGER :: n,m,jl -!------------------------------------------------------------------------------! - - n = size (xx) - m = size (yy) - - IF (n /= m) THEN - call error_handler(E_ERR,'intplog', & - 'arrays xx and yy must have same size', source,revision,revdate) - ENDIF - - jl = locate (x,xx) - - IF (jl .LE. 0) THEN - if (yy (1) >= 0.0_r8) then - val = yy (1) - else - call error_handler(E_ERR,'intplog', & - 'bad value in yy(1)', source,revision,revdate) - endif - ELSE IF (jl .GE. n) THEN - if (yy (n) >= 0.0_r8) then - val = yy (n) - else - call error_handler(E_ERR,'intplog', & - 'bad value in yy(n)', source,revision,revdate) - endif - ELSE - if (yy (jl) >= 0.0_r8 .and. yy (jl+1) >= 0.0_r8) then - val = log (real(xx(jl+1)) / x) * yy (jl) + log (x / real(xx(jl))) * yy (jl+1) - val = val / log (real(xx(jl+1)) / real(xx(jl))) - else - call error_handler(E_ERR,'intplog', & - 'bad value in yy(jl) or yy(jl+1)', source,revision,revdate) - endif - ENDIF - -END FUNCTION intplog - -FUNCTION locate (x,xx) RESULT (level_index) -!------------------------------------------------------------------------------! - IMPLICIT NONE - - INTEGER, DIMENSION (:), intent(in) :: xx - REAL(r8), intent(in) :: x - - INTEGER :: level_index - - INTEGER :: n,jl,jm,ju - LOGICAL :: ascnd -!------------------------------------------------------------------------------! - - n = size (xx) - ascnd = (xx (n) >= xx (1)) ! True if ascending order, false otherwise - jl = 0 ! Initialize lower limit - ju = n+1 ! Initialize upper limit - - DO - - IF (ju-jl <= 1) EXIT ! Repeat until this condition is satisfied - - jm = (ju+jl) / 2. ! Compute a mid point - - IF (ascnd .EQV. (x >= xx (jm))) THEN - jl = jm ! Replace mid point by lower limit - ELSE - ju = jm ! Replace mid point by upper limit - ENDIF - - ENDDO - - IF (x == xx (1)) THEN ! Set the output, being carefull with endpoints - level_index = 1 - ELSE IF (x == xx (n)) THEN - level_index = n-1 - ELSE - level_index = jl - ENDIF - -END FUNCTION LOCATE - -END PROGRAM littler_tf_dart Deleted: DART/trunk/converters/littler_tf_dart.html =================================================================== --- DART/trunk/converters/littler_tf_dart.html 2009-08-12 15:41:26 UTC (rev 4001) +++ DART/trunk/converters/littler_tf_dart.html 2009-08-12 16:51:20 UTC (rev 4002) @@ -1,404 +0,0 @@ - - -program littler_tf_dart - - - -

PROGRAM restart_file_tool

- - - - - - -
Contact: Jeff Anderson
Revision: $Revision$
Source: $URL$
Change Date: $Date$
Change history: try "svn log" or "svn diff"
- +

OVERVIEW

Utility program to alter the data timestamp in a DART restart file, -to add or remove a model-advance time, to convert from ascii to binary +to add or remove a model-advance time, to convert from ASCII to binary or back, and to either split or combine ensemble restarts into one or multiple files.

@@ -93,16 +85,28 @@

-Optional namelist interface +Namelist interface &restart_file_tool_nml -may be read from file input.nml. +must be read from file input.nml.

+

+ASCII restart files are portable across different hardware architectures +(these days, most notably between IBM PowerX chip-based systems and anything +else including all Intel/AMD systems). +However, they are larger in size, and can lose precision +when converting from binary to ASCII and back. Binary restart files can +be moved even between incompatible systems by using the 'swabrestart' utility +found in the $DART/utilities directory. See the extensive comment section +at the top of that file for an explanation of the details of moving binary +files between incompatible systems. +

+ - +


-

OTHER MODULES USED

+

MODULES USED

 types_mod
 time_manager_mod
@@ -113,19 +117,6 @@
 mpi_utilities_mod
 
- - - - -


-

PUBLIC INTERFACE

- -

NOTES

- -

-

- -


@@ -137,7 +128,7 @@ input_file_name, output_file_name, ens_size, single_restart_file_in, single_restart_file_out, write_binary_restart_files, overwrite_data_time, new_data_days, new_data_secs, input_is_model_advance_file, output_is_model_advance_file, - overwrite_advance_time, new_advance_days, new_advance_secs, gregorian_cal / + overwrite_advance_time, new_advance_days, new_advance_secs, gregorian_cal @@ -169,7 +160,7 @@ Default "filter_updated_restart" ens_size integer - Number of ensemble members. + Total number of ensemble members. Default 1 single_restart_file_in logical @@ -183,21 +174,22 @@ Default .true. write_binary_restart_files logical - Whether to write the data in ascii or binary. The + Whether to write the data in ASCII or binary. The format of the input file will be detected automatically. Default .true. overwrite_data_time logical Whether to replace the timestamp in the input with a - new time. If true, new_data_days and new_data_secs must be set to valid values. + new time. If true, new_data_days and new_data_secs must both be set + to valid values. Default .false. new_data_days integer - Day number if replacing the timestamp in the file. + Day number if replacing the data timestamp in the file. Default -1 new_data_secs integer - Seconds if replacing the timestamp in the file. + Seconds if replacing the data timestamp in the file. Default -1 input_is_model_advance_file logical @@ -206,34 +198,37 @@ Default .false. output_is_model_advance_file logical - Whether to write a file with two timestamps as output. + Whether to write a file with two timestamps in output. Default .false. overwrite_advance_time logical - Replace existing advance time. + Replace existing advance timestamp, or add an + advance timestamp if output_is_model_advance_file is true. + If true, new_advance_days and new_advance_secs must both be set + to valid values. Default .false. new_advance_days integer - If overwrite_advance_time is true, replace time with this value. + Day number if replacing or adding a model advance + timestamp in the file. Default -1 new_advance_secs integer - Seconds for replacement time. + Seconds if replacing or adding a model advance + timestamp in the file. Default -1 gregorian_cal logical - If model uses the gregorian calendar, this program will + If model uses the Gregorian calendar, this program will print out the date in both day number and seconds, but also in calendar year/month/date etc format. Set to false if this model does not use this - calendar. - Default .true. + calendar. Does not affect the timestamps in the file, only the + printout for user. Default .true. print_only logical If .true., do not create the output file. Only print the model size and existing time information in - the input file. If .false., create the output and change - any requested timestamps in the file(s). - Default .false. + the input file. Default .false.
@@ -327,27 +322,20 @@


FUTURE PLANS

+

Discussion

- - - - -


-

PRIVATE COMPONENTS

+
+ + + + + + +
Contact: Jeff Anderson
Revision: $Revision$
Source: $URL$
Change Date: $Date$
Change history: try "svn log" or "svn diff"
- - - - - - - - -

Discussion

-
From nancy at ucar.edu Tue Aug 25 11:59:26 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 11:59:26 -0600 (MDT) Subject: [Dart-dev] [4006] DART/trunk/utilities/restart_file_tool.html: Missed that the namelist name was missing the trailing _nml, and removed Message-ID: <200908251759.n7PHxQjV005246@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/2ecc17c2/attachment.html -------------- next part -------------- Modified: DART/trunk/utilities/restart_file_tool.html =================================================================== --- DART/trunk/utilities/restart_file_tool.html 2009-08-25 17:50:43 UTC (rev 4005) +++ DART/trunk/utilities/restart_file_tool.html 2009-08-25 17:59:25 UTC (rev 4006) @@ -105,7 +105,7 @@ -


+

MODULES USED

 types_mod
@@ -119,12 +119,12 @@
 
 
  
-


+

NAMELIST

We adhere to the F90 standard of starting a namelist with an ampersand '&' and terminating with a slash '/'.

- namelist / restart_file_tool /  
+ namelist / restart_file_tool_nml /  
    input_file_name, output_file_name, ens_size, single_restart_file_in,
    single_restart_file_out, write_binary_restart_files, overwrite_data_time,
    new_data_days, new_data_secs, input_is_model_advance_file, output_is_model_advance_file,
@@ -136,7 +136,6 @@
  

Discussion

The namelist sets the behavior of this tool. -

This namelist is read in a file called input.nml

@@ -240,7 +239,7 @@ -


+

FILES

  • inputfile (filter_restart)
  • restart_file_tool.nml @@ -252,7 +251,7 @@ -


    +

    REFERENCES

    @@ -310,7 +309,7 @@ -


    +

    KNOWN BUGS

    @@ -320,7 +319,7 @@ -


    +

    FUTURE PLANS

    Discussion

    From nancy at ucar.edu Tue Aug 25 13:16:14 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 13:16:14 -0600 (MDT) Subject: [Dart-dev] [4007] DART/trunk/models/coamps/templates/EXAMPLE.input.nml: the COAMPS model no longer requires changes to the obs_kind file, Message-ID: <200908251916.n7PJGEPj025226@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/055e7999/attachment.html -------------- next part -------------- Modified: DART/trunk/models/coamps/templates/EXAMPLE.input.nml =================================================================== --- DART/trunk/models/coamps/templates/EXAMPLE.input.nml 2009-08-25 17:59:25 UTC (rev 4006) +++ DART/trunk/models/coamps/templates/EXAMPLE.input.nml 2009-08-25 19:16:11 UTC (rev 4007) @@ -80,7 +80,7 @@ write_binary_obs_sequence = .false. / &preprocess_nml - input_obs_kind_mod_file = '../../../obs_kind/DEFAULT_coamps_obs_kind_mod.F90', + input_obs_kind_mod_file = '../../../obs_kind/DEFAULT_obs_kind_mod.F90', output_obs_kind_mod_file = '../../../obs_kind/obs_kind_mod.f90', input_obs_def_mod_file = '../../../obs_def/DEFAULT_obs_def_mod.F90', output_obs_def_mod_file = '../../../obs_def/obs_def_mod.f90', From nancy at ucar.edu Tue Aug 25 15:18:03 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 15:18:03 -0600 (MDT) Subject: [Dart-dev] [4008] DART/trunk/models/wrf/model_mod.f90: Allow the radar obs_def to ask for KIND_POWER_WEIGHTED_FALL_SPEED to be Message-ID: <200908252118.n7PLI3fv012118@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/3b92039b/attachment.html -------------- next part -------------- Modified: DART/trunk/models/wrf/model_mod.f90 =================================================================== --- DART/trunk/models/wrf/model_mod.f90 2009-08-25 19:16:11 UTC (rev 4007) +++ DART/trunk/models/wrf/model_mod.f90 2009-08-25 21:18:02 UTC (rev 4008) @@ -54,7 +54,7 @@ KIND_ICE_NUMBER_CONCENTRATION, KIND_GEOPOTENTIAL_HEIGHT, & KIND_POTENTIAL_TEMPERATURE, KIND_SOIL_MOISTURE, & KIND_VORTEX_LAT, KIND_VORTEX_LON, & - KIND_RADAR_REFLECTIVITY, & + KIND_RADAR_REFLECTIVITY, KIND_POWER_WEIGHTED_FALL_SPEED,& KIND_VORTEX_PMIN, KIND_VORTEX_WMAX, & get_raw_obs_kind_index, get_num_raw_obs_kinds, & get_raw_obs_kind_name @@ -6016,7 +6016,9 @@ ! way to interpolate it even if it is not in the state vector. if this ! is not allowed it will error exit instead of returning with an invalid istatus ! to indicate to the caller that the interpolation failed. +! ditto for power weighted fall speed. in_state_vector(KIND_RADAR_REFLECTIVITY) = .true. +in_state_vector(KIND_POWER_WEIGHTED_FALL_SPEED) = .true. ! FIXME: i was going to suggest nuking this routine all together because it makes ! the default behavior be to exit with an error when requesting to interpolate an From nancy at ucar.edu Tue Aug 25 16:22:57 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 16:22:57 -0600 (MDT) Subject: [Dart-dev] [4009] DART/trunk/models/POP/matlab/Check_ud.m: checks the conversion of the pop_to_dart.f90 program Message-ID: <200908252222.n7PMMvWw006910@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/e155e52d/attachment.html -------------- next part -------------- Added: DART/trunk/models/POP/matlab/Check_ud.m =================================================================== --- DART/trunk/models/POP/matlab/Check_ud.m (rev 0) +++ DART/trunk/models/POP/matlab/Check_ud.m 2009-08-25 22:22:56 UTC (rev 4009) @@ -0,0 +1,100 @@ +function [dart pop] = Check_ud(dartfile,popfile) +% Check_ud : check the conversion of a POP restart to a DART state vector. +% dartfile = 'assim_model_state_ud'; +% popfile = 'pop.r.nc' +% x = Check_ud(dartfile,popfile); +% +% +% dartfile = '/fs/image/home/thoar/SVN/DART/models/POP/work/assim_model_state_ud'; +% popfile = '/fs/image/home/thoar/SVN/DART/models/POP/work/cx3.dart.001.pop.r.0002-01-01-00000.nc'; +% [dart pop] = Check_ud(dartfile,popfile); +% + +% Read the original POP file values. +% The nc_varget() function returns the variables with the fastest +% varying dimension on the right. This is opposite to the Fortran +% convention of the fastest varying dimension on the left ... so +% one of the variables must be permuted in order to be compared. + +pop.S = nc_varget(popfile, 'SALT_CUR'); +pop.T = nc_varget(popfile, 'TEMP_CUR'); +pop.U = nc_varget(popfile, 'UVEL_CUR'); +pop.V = nc_varget(popfile, 'VVEL_CUR'); +pop.PSURF = nc_varget(popfile, 'PSURF_CUR'); + +[nz ny nx] = size(pop.U); +fprintf('vert dimension size is %d\n',nz) +fprintf('N-S dimension size is %d\n',ny) +fprintf('E-W dimension size is %d\n',nx) + +modelsize = nz*ny*nx; + +% filesize = S,T,U,V * (nx*ny*nz) + SSH * (nx*ny) +storage = 8; +size2d = nx*ny; +size3d = nx*ny*nz; +n2ditems = 1*size2d; +n3ditems = 4*size3d; +rec1size = 4+(4+4)+4; % time stamps ... +rec2size = 4+(n3ditems*storage + n2ditems*storage)+4; + +fsize = rec1size + rec2size; +disp(sprintf('with a modelsize of %d the file size should be %d bytes', ... + modelsize,fsize)) + +% Open and read timetag for state +fid = fopen(dartfile,'rb','ieee-le'); +trec1 = fread(fid,1,'int32'); +seconds = fread(fid,1,'int32'); +days = fread(fid,1,'int32'); +trecN = fread(fid,1,'int32'); + +if (trec1 ~= trecN) + error('first record mismatch') +end + +% Successively read state vector variables. +rec1 = fread(fid, 1, 'int32'); +dart.S = get_3D_permuted(fid, [nx ny nz], 'float64'); +dart.T = get_3D_permuted(fid, [nx ny nz], 'float64'); +dart.U = get_3D_permuted(fid, [nx ny nz], 'float64'); +dart.V = get_3D_permuted(fid, [nx ny nz], 'float64'); +dart.SSH = get_2D_permuted(fid, [nx ny ], 'float64'); +recN = fread(fid, 1, 'int32'); +fclose(fid); + +fprintf(' shape of DART variables is %d \n',size(dart.S)) + +% The POP restart file has PSURF ... DART drags around SSH +% SSH = psurf/980.6; + +dart.PSURF = dart.SSH * 980.6; + +if (rec1 ~= recN) + error('second record mismatch') +end + +dart.dartfile = dartfile; +dart.seconds = seconds; +dart.days = days; + +% Find the range of the mismatch + +Sdiff = pop.S - dart.S; [min( Sdiff(:)) max( Sdiff(:))] +Tdiff = pop.T - dart.T; [min( Tdiff(:)) max( Tdiff(:))] +Udiff = pop.U - dart.U; [min( Udiff(:)) max( Udiff(:))] +Vdiff = pop.V - dart.V; [min( Vdiff(:)) max( Vdiff(:))] +PSURFdiff = pop.PSURF - dart.PSURF; [min(PSURFdiff(:)) max(PSURFdiff(:))] + + +function C = get_3D_permuted(fid, shape, typestr) +datasize = prod(shape); +A = fread(fid, prod(shape), typestr); +B = reshape(A, shape); +C = permute(B, [3 2 1]); + +function C = get_2D_permuted(fid, shape, typestr) +datasize = prod(shape); +A = fread(fid, prod(shape), typestr); +B = reshape(A, shape); +C = permute(B, [2 1]); Property changes on: DART/trunk/models/POP/matlab/Check_ud.m ___________________________________________________________________ Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Revision Author HeadURL Id Name: svn:eol-style + native From nancy at ucar.edu Tue Aug 25 16:54:27 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 16:54:27 -0600 (MDT) Subject: [Dart-dev] [4010] DART/trunk/perfect_model_obs/perfect_model_obs.f90: Important bug fix: correct the standard deviation passed into Message-ID: <200908252254.n7PMsR9N001446@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/da19fbfa/attachment.html -------------- next part -------------- Modified: DART/trunk/perfect_model_obs/perfect_model_obs.f90 =================================================================== --- DART/trunk/perfect_model_obs/perfect_model_obs.f90 2009-08-25 22:22:56 UTC (rev 4009) +++ DART/trunk/perfect_model_obs/perfect_model_obs.f90 2009-08-25 22:54:27 UTC (rev 4010) @@ -350,17 +350,8 @@ ! If observation is not being evaluated or assimilated, skip it ! Ends up setting a 1000 qc field so observation is not used again. if(istatus == 0 .and. (assimilate_this_ob .or. evaluate_this_ob)) then - ! DEBUG: try this out to see if it's useful. if the incoming error - ! variance is negative, add no noise to the values, but do switch the - ! sign on the error so the file is useful in subsequent runs. - errvar = get_obs_def_error_variance(obs_def) - if (errvar > 0.0_r8) then - obs_value(1) = random_gaussian(random_seq, true_obs(1), errvar) - else - obs_value(1) = true_obs(1) - call set_obs_def_error_variance(obs_def, -errvar) - call set_obs_def(obs, obs_def) - endif + obs_value(1) = random_gaussian(random_seq, true_obs(1), & + sqrt(get_obs_def_error_variance(obs_def))) ! Set qc to 0 if none existed before if(cnum_qc == 0) then From nancy at ucar.edu Tue Aug 25 17:04:35 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 17:04:35 -0600 (MDT) Subject: [Dart-dev] [4011] DART/trunk: GUI presentation of fundamental assimilation concepts Message-ID: <200908252304.n7PN4Z4k006613@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/07a8a1fd/attachment-0001.html -------------- next part -------------- Added: DART/trunk/DART_LAB/matlab/advance_oned.m =================================================================== --- DART/trunk/DART_LAB/matlab/advance_oned.m (rev 0) +++ DART/trunk/DART_LAB/matlab/advance_oned.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,25 @@ +function x_new = advance_oned(x, alpha) + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +x_new = x + comp_dt(x, alpha); +end + +%--------------------------------------------------- + +% Internal function comp_dt +function dx = comp_dt(x, alpha) + +% Compute the time tendency; alpha controls nonlinearity +dx = x + alpha .* x .* abs(x); + +end Property changes on: DART/trunk/DART_LAB/matlab/advance_oned.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/comp_cov_factor.m =================================================================== --- DART/trunk/DART_LAB/matlab/comp_cov_factor.m (rev 0) +++ DART/trunk/DART_LAB/matlab/comp_cov_factor.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,26 @@ +function cov_factor = comp_cov_factor(z_in, c) +% Gaspari Cohn cutoff, z_in is the distance while c is the cutoff + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +z = abs(z_in); + +if( z >= c*2.0) + cov_factor = 0; +elseif( z <= c ) + r = z / c; + cov_factor = ((( -0.25*r +0.5)*r +0.625)*r -5.0/3.0)*r^2 + 1.0; +else + r = z / c; + cov_factor = ((((r/12 -0.5)*r +0.625)*r +5.0/3.0)*r -5.0)*r + 4.0 - 2.0 / (3.0 * r); +end + Property changes on: DART/trunk/DART_LAB/matlab/comp_cov_factor.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/g_prod_plot.m =================================================================== --- DART/trunk/DART_LAB/matlab/g_prod_plot.m (rev 0) +++ DART/trunk/DART_LAB/matlab/g_prod_plot.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,107 @@ +function [prior_mean, prior_sd, obs_mean, obs_err_sd, is_err] = g_prod_plot(h) +% Updates the plot of the prior and observation gaussians + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Successful return as defaul t +is_err = false; + +% Default failed returns for other quantities +prior_mean = 0; prior_sd = -1; +obs_mean = 0; obs_err_sd = -1; + +h_prior_mean = get(h.edit1); +prior_mean = str2double(h_prior_mean.String); +% The mean must be a number +if(isnan(prior_mean)) + error_banner(h, 'Prior Mean must be a number'); + is_err = true; + return +end + +h_prior_sd = get(h.edit2); +prior_sd = str2double(h_prior_sd.String); + +% Prior sd must be a number +if(isnan(prior_sd)) + error_banner(h, 'Prior SD must be a postive number'); + is_err = true; + return +end + +% Prior sd must also be positive +if(prior_sd <= 0) + error_banner(h, 'Prior SD must be positive') + is_err = true; + return +end + +hold off +prior_handle = plot_gaussian(prior_mean, prior_sd, 1); +set(prior_handle, 'Color', [0 0.73 0], 'LineWidth', 2); +hold on + +h_obs_mean = get(h.edit3); +obs_mean = str2double(h_obs_mean.String); + +% Obs value must be a number +if(isnan(obs_mean)) + error_banner(h, 'Obs value must be a number'); + is_err = true; + return +end + +h_obs_err_sd = get(h.edit4); +obs_err_sd = str2double(h_obs_err_sd.String); + +% Obs error sd must be a positive number +if(isnan(obs_err_sd)) + error_banner(h, 'Obs Error SD must be a positive number'); + is_err = true; + return +end + +if(obs_err_sd <= 0) + error_banner(h, 'Obs Error SD must be positive'); + is_err = true; + return +end + +obs_handle = plot_gaussian(obs_mean, obs_err_sd, 1); +set(obs_handle, 'Color', 'r', 'LineStyle', '--', 'LineWidth', 2); + +% Put on a legend +legend('Prior', 'Obs. Likelihood'); + +end + +%--------------------------------------------------------- + +% Internal function to write error banner +function error_banner(h, message) + + hold off + x= [1 2]; + plot(x, 'Visible', 'off') + h_fig = get(h.figure1); + x_limits = get(h_fig.CurrentAxes, 'Xlim'); + y_limits = get(h_fig.CurrentAxes, 'Ylim'); + text(x_limits(1) * 7/8 + x_limits(2) / 8, mean(y_limits), ... + message, 'fontsize', 16, 'Color', 'r'); + + % While we're at it, clear out the values for posterior, too + set(h.text7, 'String', 'Posterior Mean = '); + set(h.text8, 'String', 'Posterior SD = '); + set(h.text9, 'String', 'Weight = '); + return; + +end Property changes on: DART/trunk/DART_LAB/matlab/g_prod_plot.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/gaussian_product.fig =================================================================== (Binary files differ) Property changes on: DART/trunk/DART_LAB/matlab/gaussian_product.fig ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: DART/trunk/DART_LAB/matlab/gaussian_product.m =================================================================== --- DART/trunk/DART_LAB/matlab/gaussian_product.m (rev 0) +++ DART/trunk/DART_LAB/matlab/gaussian_product.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,214 @@ +function varargout = gaussian_product(varargin) +% GAUSSIAN_PRODUCT demonstrates the product of two gaussian distributions. +% +% This is fundamental to ensemble data assimilation. Change the +% parameters of the gaussian for the Prior (green) and the Observation +% (red) and click on 'Plot Posterior'. +% +% The product of the two gaussians is a gaussian - in this case, +% the 'Posterior'. If the parameters of the two gaussians are known, +% the parameters of the resulting gaussian can be calculated. +% +% See also: oned_model, oned_ensemble, twod_ensemble, run_lorenz_63, +% run_lorenz_96 + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Last Modified by GUIDE v2.5 21-Mar-2009 22:11:31 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @gaussian_product_OpeningFcn, ... + 'gui_OutputFcn', @gaussian_product_OutputFcn, ... + 'gui_LayoutFcn', [] , ... + 'gui_Callback', []); +if nargin && ischar(varargin{1}) + gui_State.gui_Callback = str2func(varargin{1}); +end + +if nargout + [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); +else + gui_mainfcn(gui_State, varargin{:}); +end +% End initialization code - DO NOT EDIT + + +% --- Executes just before gaussian_product is made visible. +function gaussian_product_OpeningFcn(hObject, eventdata, handles, varargin) +% This function has no output args, see OutputFcn. +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +% varargin command line arguments to gaussian_product (see VARARGIN) + +help gaussian_product + +% Choose default command line output for gaussian_product +handles.output = hObject; + +% Update handles structure +guidata(hObject, handles); + +% Plot the initial prior and observation likelihood pdf's +h = guihandles; +g_prod_plot(h); + +% UIWAIT makes gaussian_product wait for user response (see UIRESUME) +% uiwait(handles.figure1); + + +% --- Outputs from this function are returned to the command line. +function varargout = gaussian_product_OutputFcn(hObject, eventdata, handles) +% varargout cell array for returning output args (see VARARGOUT); +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Get default command line output from handles structure +varargout{1} = handles.output; + + + +function edit1_Callback(hObject, eventdata, handles) +% hObject handle to edit1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit1 as text +% str2double(get(hObject,'String')) returns contents of edit1 as a double + +g_prod_plot(handles); + + +% --- Executes during object creation, after setting all properties. +function edit1_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + +function edit2_Callback(hObject, eventdata, handles) +% hObject handle to edit2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit2 as text +% str2double(get(hObject,'String')) returns contents of edit2 as a double + +g_prod_plot(handles); + + +% --- Executes during object creation, after setting all properties. +function edit2_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + + +function edit3_Callback(hObject, eventdata, handles) +% hObject handle to edit3 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit3 as text +% str2double(get(hObject,'String')) returns contents of edit3 as a double + +g_prod_plot(handles); + + +% --- Executes during object creation, after setting all properties. +function edit3_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit3 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + + +function edit4_Callback(hObject, eventdata, handles) +% hObject handle to edit4 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit4 as text +% str2double(get(hObject,'String')) returns contents of edit4 as a double + +g_prod_plot(handles); + + +% --- Executes during object creation, after setting all properties. +function edit4_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit4 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + +% --- Executes on button press in pushbutton1. +function pushbutton1_Callback(hObject, eventdata, handles) +% hObject handle to pushbutton1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Need to replot prior and obs, then compute posterior and plot +[prior_mean, prior_sd, obs_mean, obs_err_sd, is_err] = g_prod_plot(handles); + +% If there is an error, don't try to do posterior computation +% But do zero out the posterior text values +if(is_err) return; + set(handles.text7, 'String', strcat('Posterior Mean = ')); + set(handles.text8, 'String', strcat('Posterior SD = ')); + set(handles.text9, 'String', strcat('Weight = ')); +end + +% Compute the posterior mean, sd and weight +[post_mean, post_sd, weight] = ... + product_of_gaussians(prior_mean, prior_sd, obs_mean, obs_err_sd); +post_handle = plot_gaussian(post_mean, post_sd, 1); +set(post_handle, 'Color', 'b', 'LineWidth', 2); + +% Print values +set(handles.text7, 'String', ['Posterior Mean = ', num2str(post_mean)]); +set(handles.text8, 'String', ['Posterior SD = ', num2str(post_sd)]); + +% Also plot the weighted posterior as dashed +post_handle = plot_gaussian(post_mean, post_sd, weight); +set(post_handle, 'Color', 'b', 'Linestyle', '--'); +set(handles.text9, 'String', ['Weight = ', num2str(weight)]); + +legend('Prior', 'Obs. Likelihood', 'Posterior', 'Weighted Posterior'); + + Property changes on: DART/trunk/DART_LAB/matlab/gaussian_product.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/get_ens_rank.m =================================================================== --- DART/trunk/DART_LAB/matlab/get_ens_rank.m (rev 0) +++ DART/trunk/DART_LAB/matlab/get_ens_rank.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,25 @@ +function [rank] = get_ens_rank(ens, x) + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +s_ens = sort(ens); + +for i = 1 : size(ens, 2) + if(x < s_ens(1, i)) + rank = i; + return; + end +end + +rank = size(ens, 2) + 1; + +end Property changes on: DART/trunk/DART_LAB/matlab/get_ens_rank.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/get_state_increments.m =================================================================== --- DART/trunk/DART_LAB/matlab/get_state_increments.m (rev 0) +++ DART/trunk/DART_LAB/matlab/get_state_increments.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,21 @@ +function [state_incs] = get_state_increments(state_ens, obs_ens, obs_incs) +% Computes state increments given observation increments and +% the state and obs prior ensembles + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Compute state variance and covariance +covar = cov(state_ens, obs_ens); + + +state_incs = obs_incs * covar(1, 2) / covar(2, 2); + Property changes on: DART/trunk/DART_LAB/matlab/get_state_increments.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/lorenz_63_adv_1step.m =================================================================== --- DART/trunk/DART_LAB/matlab/lorenz_63_adv_1step.m (rev 0) +++ DART/trunk/DART_LAB/matlab/lorenz_63_adv_1step.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,51 @@ +function[x_new, time_new] = lorenz_63_adv_1step(x, time) +% Does a single time step advance for lorenz convective 3 variable model +% using two step runge-kutta time step +% +% x is the 3-vector state, time is the 2-vector days and seconds time + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2007, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +global DELTAT + +% Set the fraction for the rk-2 time step +fract = 1; + +% Compute the first intermediate step +dx = comp_dt(x); +x1 = x + fract * DELTAT * dx; + +% Compute the second intermediate step +dx = comp_dt(x1); +x2 = x1 + fract * DELTAT * dx; + +% New value for x is average of original value and second intermediate +x_new = (x + x2) / 2; + +% Update the time ; Non-dimensional single unit for development +time_new = time + 1; + +end + + +function[dt] = comp_dt(x) + +global SIGMA +global R +global B + +dt(1) = SIGMA * (x(2) - x(1)); +dt(2) = -1 * x(1)*x(3) + R*x(1) - x(2); +dt(3) = x(1)*x(2) - B*x(3); + +end + Property changes on: DART/trunk/DART_LAB/matlab/lorenz_63_adv_1step.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/lorenz_63_static_init_model.m =================================================================== --- DART/trunk/DART_LAB/matlab/lorenz_63_static_init_model.m (rev 0) +++ DART/trunk/DART_LAB/matlab/lorenz_63_static_init_model.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,39 @@ +% Initializes class data for L63, sets up global storage +% and reads in control data from input file + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Lorenz-63 model parameters +global SIGMA +global R +global B +global DELTAT +global TIME_STEP_DAYS +global TIME_STEP_SECONDS + +% Set default values for the model parameters +SIGMA = 10; +R = 28; +B = 8/3; +DELTAT = 0.01; +TIME_STEP_DAYS = 0; +TIMES_STEP_SECONDS = 0; + + +% Lorenz-63 fixed model parameters +global MODEL_SIZE + +MODEL_SIZE = 3; + +global STATE_LOC + +STATE_LOC = (0:2) / 3; Property changes on: DART/trunk/DART_LAB/matlab/lorenz_63_static_init_model.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/lorenz_96_adv_1step.m =================================================================== --- DART/trunk/DART_LAB/matlab/lorenz_96_adv_1step.m (rev 0) +++ DART/trunk/DART_LAB/matlab/lorenz_96_adv_1step.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,66 @@ +function[x_new, time_new] = lorenz_96_adv_1step(x, time) +% Does a single time step advance for lorenz_96 40-variable model using four step runge-kutta time step +% +% x is the 40-vector state, time is the 2-vector days and seconds time + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +global DELTA_T + +% Compute first intermediate step +dx = comp_dt(x); +x1 = DELTA_T * dx; +inter = x + x1 / 2; + +% Compute second intermediate step +dx = comp_dt(inter); +x2 = DELTA_T * dx; +inter = x + x2 / 2; + +% Compute third intermediate step +dx = comp_dt(inter); +x3 = DELTA_T * dx; +inter = x + x3; + +% Compute fourth intermediate step +dx = comp_dt(inter); +x4 = DELTA_T * dx; + +% Compute new value for x +x_new = x + x1/6 + x2/3 + x3/3 + x4/6; + +% Increment time step +time_new = time + 1; + + +end + +%------------------------------------------------------------------------------ + +function[dt] = comp_dt(x) + +global FORCING +global MODEL_SIZE + +for j = 1:MODEL_SIZE + jp1 = j + 1; + if(jp1 > MODEL_SIZE) jp1 = 1; end + jm2 = j - 2; + if(jm2 < 1) jm2 = MODEL_SIZE + jm2; end + jm1 = j - 1; + if(jm1 < 1) jm1 = MODEL_SIZE; end + + dt(j) = (x(jp1) - x(jm2)) * x(jm1) - x(j) + FORCING; +end + +end + Property changes on: DART/trunk/DART_LAB/matlab/lorenz_96_adv_1step.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/lorenz_96_static_init_model.m =================================================================== --- DART/trunk/DART_LAB/matlab/lorenz_96_static_init_model.m (rev 0) +++ DART/trunk/DART_LAB/matlab/lorenz_96_static_init_model.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,35 @@ +% Initializes class data for L96, sets up global storage +% and reads in control data from input file + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Lorenz-96 model parameters +global FORCING +global DELTA_T +global TIME_STEP_DAYS +global TIME_STEP_SECONDS + +% Set default values for the model parameters +FORCING = 8; +DELTA_T = 0.05; +TIME_STEP_DAYS = 0; +TIMES_STEP_SECONDS = 0; + + +% Lorenz-96 fixed model parameters +global MODEL_SIZE + +MODEL_SIZE = 40; + +global STATE_LOC + +STATE_LOC = (0:MODEL_SIZE - 1) / MODEL_SIZE; Property changes on: DART/trunk/DART_LAB/matlab/lorenz_96_static_init_model.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/obs_increment_eakf.m =================================================================== --- DART/trunk/DART_LAB/matlab/obs_increment_eakf.m (rev 0) +++ DART/trunk/DART_LAB/matlab/obs_increment_eakf.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,58 @@ +function [obs_increments, err] = obs_increment_eakf(ensemble, observation, obs_error_var) +% Computes increments for an ensemble adjustment filter + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Set error return to default successful +err = 0; + +% Compute prior ensemble mean and variance +prior_mean = mean(ensemble); +prior_var = var(ensemble); + +% If both prior and observation error variance are return error +if(prior_var <= 0 && obs_error_var <= 0) + err = 1; + return; +end + +% Compute the posterior mean and variance +% If prior variance is 0, posterior mean is prior_mean and variance is 0 +if(prior_var == 0) + post_mean = prior_mean; + post_var = 0; +elseif(obs_error_var == 0) +% If obs_error_var is 0, posterior mean is observation and variance is 0 + post_mean = observation; + post_var = 0; +else +% Use product of gaussians + % Compute the posterior variance + post_var = 1 / (1 / prior_var + 1 / obs_error_var); + + % Compute posterior mean + post_mean = post_var * (prior_mean / prior_var + observation / obs_error_var); +end + + +% Shift the prior ensemble to have the posterior mean +updated_ensemble = ensemble - prior_mean + post_mean; + +% Contract the ensemble to have the posterior_variance +var_ratio = post_var / prior_var; +updated_ensemble = sqrt(var_ratio) * (updated_ensemble - post_mean) + post_mean; + +% Compute the increments +obs_increments = updated_ensemble - ensemble; + + + Property changes on: DART/trunk/DART_LAB/matlab/obs_increment_eakf.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/obs_increment_enkf.m =================================================================== --- DART/trunk/DART_LAB/matlab/obs_increment_enkf.m (rev 0) +++ DART/trunk/DART_LAB/matlab/obs_increment_enkf.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,74 @@ +function [obs_increments, err] = obs_increment_eakf(ensemble, observation, obs_error_var) +% Computes increments for an ensemble Kalman filter with perturbed obs mean correction. + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Set error return to default successful +err = 0; + +% Compute prior ensemble mean and variance +prior_mean = mean(ensemble); +prior_var = var(ensemble); + +% If both prior and observation error variance are zero return error +if(prior_var <= 0 && obs_error_var <= 0) + err = 1; + return; +end + +% Compute the posterior mean and variance +% If prior variance is 0, posterior mean is prior_mean and variance is 0 +if(prior_var == 0) + post_mean = prior_mean; + post_var = 0; +elseif(obs_error_var == 0) +% If obs_error_var is 0, posterior mean is observation and variance is 0 + post_mean = observation; + post_var = 0; +else +% Use product of gaussians + % Compute the posterior variance + post_var = 1 / (1 / prior_var + 1 / obs_error_var); + + % Compute posterior mean + post_mean = post_var * (prior_mean / prior_var + observation / obs_error_var); +end + +% Generate the perturbed observations by adding +% draw from Normal(0, obs_error_sd) +temp_obs = observation + sqrt(obs_error_var) * randn(size(ensemble)); + +% Adjust so that perturbed observations have mean = to observation +% This is technically an enhancement of earliest EnKFs +temp_obs = temp_obs - mean(temp_obs) + observation; + +% Compute new ensemble members by taking product of prior ensemble +% members and perturbed obs pairs +updated_ens = post_var * (ensemble / prior_var + temp_obs / obs_error_var); + +% Increments are difference between updated and original ensemble +obs_increments = updated_ens - ensemble; + +% Following are enhancements that change characteristics of EnKF +% Coding is not finalized so do NOT just uncomment +% Could also adjust the mean and variance of the final sample; +% This can greatly improve and change the behavior +% Shift the prior ensemble to have the posterior mean +%%%updated_ensemble = ensemble - prior_mean + post_mean; + +% Contract the ensemble to have the posterior_variance +%%%var_ratio = post_var / prior_var; +%%%updated_ensemble = sqrt(var_ratio) * (updated_ensemble - post_mean) + post_mean; + +% Compute the increments +%%%obs_increments = updated_ensemble - ensemble; + Property changes on: DART/trunk/DART_LAB/matlab/obs_increment_enkf.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/obs_increment_rhf.m =================================================================== --- DART/trunk/DART_LAB/matlab/obs_increment_rhf.m (rev 0) +++ DART/trunk/DART_LAB/matlab/obs_increment_rhf.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,177 @@ +function [obs_increments, err] = obs_increment_eakf(ensemble, observation, obs_error_var) +% Computes increments for a rank histogram filter +% Need to discuss the available options eventually +% For now this implements the default options + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Set error return to default successful +err = 0; + +% Get the ensemble size +ens_size = size(ensemble, 2); +prior_sd = std(ensemble); +prior_var = prior_sd^2; + +% Sort the ensemble members and keep the indices +[x, e_ind] = sort(ensemble); + +% Compute the likelihood of each member given the observation +like = exp(-1 * (x - observation).^2 / (2 * obs_error_var)); + +% Compute the mean likelihood density in each interior bin +for i = 2:ens_size + like_dense(i) = (like(i - 1) + like(i)) / 2; +end + +% For unit normal, find distance from mean to where cdf is 1/(n+1) +dist_for_unit_sd = -1 * weighted_norm_inv(1, 0, 1, 1/(ens_size + 1)); + +% Variance of tails is just sample prior variance +% Mean is adjusted so that 1/(ens_size + 1) is outside +left_mean = x(1) + dist_for_unit_sd * prior_sd; +left_var = prior_var; +left_sd = prior_sd; + +% Same for the right tail +right_mean = x(ens_size) - dist_for_unit_sd * prior_sd; +right_var = prior_var; +right_sd = prior_sd; + +% Eventually want to support options, for now +gaussian_likelihood_tails = false; + +if(gaussian_likelihood_tails) + % Need to fill this in +else + % Block to do flat tails for likelihood follows + % This removes assumptions about likelihood and cuts cost + new_var_left = left_var; + new_sd_left = left_sd; + new_mean_left = left_mean; + prod_weight_left = like(1); + mass(1) = like(1) / (ens_size + 1); + + % Same for right tail + new_var_right = right_var; + new_sd_right = right_sd; + new_mean_right = right_mean; + prod_weight_right = like(ens_size); + mass(ens_size + 1) = like(ens_size) / (ens_size + 1); + % End block for flat tail likelihood +end + +% The mass in each interior box is the height times the width +% The height of the likelihood is like_dense +% For the prior, mass is 1 / ((n+1) width), and mass = height x widt so +% The height of the prior is 1 / ((n+1) width); Multiplying by width leaves 1/(n+1) + +% In prior, have 1/(n+1) mass in each bin, multiply by mean likelihood +% density to get approximate mass in updated bin +for i = 2:ens_size + mass(i) = like_dense(i) / (ens_size + 1); + % Height of prior in this bin is mass/width; Only needed for trapezoidal + % If two ensemble members are the same, set height to -1 as flag + if(x(i) == x(i-1)) + height(i) = -1; + else + height(i) = 1 / ((ens_size + 1) * (x(i) - x(i-1))); + end +end + +% Now normalize the mass in the different bins to get a pdf +mass_sum = sum(mass); +nmass = mass / mass_sum; + +% Get the weight for the final normalized tail gaussians +% This is the same as left_amp=(ens_size + 1)*nmass(1) +left_amp = prod_weight_left / mass_sum; +% This is the same as right_amp=(ens_size + 1)*nmass(ens_size+1) +right_amp = prod_weight_right / mass_sum; + +% Find cumulative mass at each box boundary and middle boundary +cumul_mass(1) = 0; +for i = 1:ens_size + 1 + cumul_mass(i+1) = cumul_mass(i) + nmass(i); +end + +% Begin internal box search at bottom of lowest box +lowest_box = 1; + +% Find each new ensemble member's location +for i = 1:ens_size + % Each update ensemble member has 1/(n+1) mass before it + umass = i / (ens_size + 1); + + % If it is in the inner or outer range have to use normal + if(umass < cumul_mass(2)) + % It is in the left tail + % Get position of x in weighted gaussian where the cdf has value umass + new_ens(i) = weighted_norm_inv(left_amp, new_mean_left, ... + new_sd_left, umass); + elseif (umass > cumul_mass(ens_size + 1)) + % It's in the right tail + % Get the position of x in weighted gaussian where the cdf has value umass + new_ens(i) = weighted_norm_inv(right_amp, new_mean_right, ... + new_sd_right, 1 - umass); + % Coming in from the right, use symmetry after pretending it's on left + new_ens(i) = new_mean_right + (new_mean_right - new_ens(i)); + else + % In one of the inner boxes + for j = lowest_box:ens_size - 1 + % Find the box that this mass is in + if(umass >= cumul_mass(j+1) && umass <= cumul_mass(j+2)) + + % Only rectangular is implemented for now + rectangular_quadrature = true; + + if(rectangular_quadrature) + % Rectangular quadrature block first + % Linearly interpolate in mass + new_ens(i) = x(j) + ((umass - cumul_mass(j+1)) / ... + (cumul_mass(j+2) - cumul_mass(j+1))) * (x(j+1) - x(j)); + else + % Trapezoidal interpolation block goes here + end + + % Don't need to search lower boxes again + lowest_box = j; + break + end + end + end +end + +% Convert to increments for unsorted +for i = 1:ens_size + obs_increments(e_ind(i)) = new_ens(i) - x(i); +end + + +%----------------------------------------------- + + +function [x] = weighted_norm_inv(alpha, mean, sd, p) + +% Find the value of x for which the cdf of a N(mean, sd) +% multiplied times alpha has value p. + +% Can search in a standard normal, then multiply by sd at end and add mean +% Divide p by alpha to get the right place for weighted normal +np = p / alpha; + +% Find spot in standard normal +x = norminv(np, 0, 1); + +% Add in the mean and normalize by sd +x = mean + x * sd; + Property changes on: DART/trunk/DART_LAB/matlab/obs_increment_rhf.m ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-matlab Name: svn:keywords + Date Rev Author URL Id Name: svn:eol-style + native Added: DART/trunk/DART_LAB/matlab/oned_ensemble.fig =================================================================== (Binary files differ) Property changes on: DART/trunk/DART_LAB/matlab/oned_ensemble.fig ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: DART/trunk/DART_LAB/matlab/oned_ensemble.m =================================================================== --- DART/trunk/DART_LAB/matlab/oned_ensemble.m (rev 0) +++ DART/trunk/DART_LAB/matlab/oned_ensemble.m 2009-08-25 23:04:35 UTC (rev 4011) @@ -0,0 +1,473 @@ +function varargout = oned_ensemble(varargin) +% ONED_ENSEMBLE explore the details of ensemble data assimilation for a scalar. +% +% Click on the 'Create New Ensemble' button to activate the interactive +% observation generation mechanism and lay down a set of 'observations' +% representative of your ensemble. (Think: Some H() operator has +% converted the model state to an expected observation.) +% +% After you have an ensemble and an observation, choose an assimilation +% algorithm and click 'Update Ensemble'. The algorithm is applied and the +% Posterior (blue) is plotted below the Prior (green). Choose 'EAKF' +% and click 'Update' ... multiple times. Do the same for 'EnKF' and +% 'RHF'. Hmnnnn .... +% +% change the Observation Error SD, lay down an ensemble pretty far away +% from the observation - have fun with it. +% +% See also: gaussian_product, oned_model, twod_ensemble, run_lorenz_63, +% run_lorenz_96 + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2009, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ + +% Last Modified by GUIDE v2.5 25-Mar-2009 14:34:04 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @oned_ensemble_OpeningFcn, ... + 'gui_OutputFcn', @oned_ensemble_OutputFcn, ... + 'gui_LayoutFcn', [] , ... + 'gui_Callback', []); +if nargin && ischar(varargin{1}) + gui_State.gui_Callback = str2func(varargin{1}); +end + +if nargout + [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); +else + gui_mainfcn(gui_State, varargin{:}); +end +% End initialization code - DO NOT EDIT + + +% --- Executes just before oned_ensemble is made visible. +function oned_ensemble_OpeningFcn(hObject, eventdata, handles, varargin) +% This function has no output args, see OutputFcn. +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +% varargin command line arguments to oned_ensemble (see VARARGIN) + +help oned_ensemble + +% Choose default command line output for oned_ensemble +handles.output = hObject; + +% Insert the ensemble structure into this +handles.ens_size = 0; +handles.ens_members = 0; +handles.h_obs_plot = 0; +handles.h_update_ens = 0; +handles.h_ens_member = 0; +handles.h_obs_ast = 0; + +% Update handles structure +guidata(hObject, handles); + +% Go ahead and plot the initial observational error distribution +h_observation = get(handles.edit1); +h_obs_error_sd = get(handles.edit2); +observation = str2double(h_observation.String); +obs_error_sd = str2double(h_obs_error_sd.String); +handles.h_obs_plot = plot_gaussian(observation, obs_error_sd, 1); +set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); +hold on + +% Plot an asterisk +handles.h_obs_ast = plot(observation, 0, 'r*', 'MarkerSize', 16); + +% Set a basic plotting domain range that includes mean +/- 3 obs SDs +lower = observation - 3*obs_error_sd; +upper = observation + 3*obs_error_sd; +axis([lower upper -0.2 1]); + + +set(gca, 'YTick', [0 0.2 0.4 0.6 0.8]); +set(gca, 'YTickLabel', [0 0.2 0.4 0.6 0.8]); + +hold on +plot([lower upper], [0 0], 'k', 'Linewidth', 2); + +% Update handles structure +guidata(hObject, handles); + + +% UIWAIT makes oned_ensemble wait for user response (see UIRESUME) +% uiwait(handles.figure1); + + +%---------------------------------------------------------------------- + + +% --- Outputs from this function are returned to the command line. +function varargout = oned_ensemble_OutputFcn(hObject, eventdata, handles) +% varargout cell array for returning output args (see VARARGOUT); +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Get default command line output from handles structure +varargout{1} = handles.output; + + +%---------------------------------------------------------------------- + + +% --- Executes on button press in pushbutton1. @@ Diff output truncated at 40000 characters. @@ From nancy at ucar.edu Tue Aug 25 17:22:31 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Tue, 25 Aug 2009 17:22:31 -0600 (MDT) Subject: [Dart-dev] [4012] DART/trunk/models/POP/matlab/Check_ud.m: Better output format for reporting differences. Message-ID: <200908252322.n7PNMVna015519@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090825/a2e73222/attachment.html -------------- next part -------------- Modified: DART/trunk/models/POP/matlab/Check_ud.m =================================================================== --- DART/trunk/models/POP/matlab/Check_ud.m 2009-08-25 23:04:35 UTC (rev 4011) +++ DART/trunk/models/POP/matlab/Check_ud.m 2009-08-25 23:22:31 UTC (rev 4012) @@ -1,14 +1,24 @@ -function [dart pop] = Check_ud(dartfile,popfile) -% Check_ud : check the conversion of a POP restart to a DART state vector. +function [dart pop] = Check_ud(popfile,dartfile) +% Check_ud : check pop_to_dart.f90 ... the conversion of a POP restart to a DART state vector file. +% +% popfile = 'pop.r.nc' % dartfile = 'assim_model_state_ud'; -% popfile = 'pop.r.nc' -% x = Check_ud(dartfile,popfile); +% x = Check_ud(popfile, dartfile); % -% -% dartfile = '/fs/image/home/thoar/SVN/DART/models/POP/work/assim_model_state_ud'; % popfile = '/fs/image/home/thoar/SVN/DART/models/POP/work/cx3.dart.001.pop.r.0002-01-01-00000.nc'; -% [dart pop] = Check_ud(dartfile,popfile); +% dartfile = '/fs/image/home/thoar/SVN/DART/models/POP/work/perfect_ics'; +% [dart pop] = Check_ud(popfile, dartfile); + +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2007, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html % +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ % Read the original POP file values. % The nc_varget() function returns the variables with the fastest @@ -80,13 +90,47 @@ % Find the range of the mismatch -Sdiff = pop.S - dart.S; [min( Sdiff(:)) max( Sdiff(:))] -Tdiff = pop.T - dart.T; [min( Tdiff(:)) max( Tdiff(:))] -Udiff = pop.U - dart.U; [min( Udiff(:)) max( Udiff(:))] -Vdiff = pop.V - dart.V; [min( Vdiff(:)) max( Vdiff(:))] -PSURFdiff = pop.PSURF - dart.PSURF; [min(PSURFdiff(:)) max(PSURFdiff(:))] +d = pop.S - dart.S; disp(sprintf('S diffs are %0.8g %0.8g',min(d(:)),max(d(:)))) +d = pop.T - dart.T; disp(sprintf('T diffs are %0.8g %0.8g',min(d(:)),max(d(:)))) +d = pop.U - dart.U; disp(sprintf('U diffs are %0.8g %0.8g',min(d(:)),max(d(:)))) +d = pop.V - dart.V; disp(sprintf('V diffs are %0.8g %0.8g',min(d(:)),max(d(:)))) +d = pop.PSURF - dart.PSURF; disp(sprintf('PSURF diffs are %0.8g %0.8g',min(d(:)),max(d(:)))) +% As an added bonus, we create an 'assim_model_state_ic' file with an +% advance-to-time one day in the future. +% Open and read timetag for state +fid = fopen(dartfile,'rb','ieee-le'); +trec1 = fread(fid,1,'int32'); +seconds = fread(fid,1,'int32'); +days = fread(fid,1,'int32'); +trecN = fread(fid,1,'int32'); + +% read state vector variables. +rec1 = fread(fid, 1, 'int32'); +datvec = fread(fid, n3ditems+n2ditems, 'float64'); +recN = fread(fid, 1, 'int32'); +fclose(fid); + +% Open and write advance_to_time +fid = fopen('test.ic','wb','ieee-le'); +fwrite(fid, trec1,'int32'); +fwrite(fid,seconds,'int32'); +fwrite(fid, days,'int32'); +fwrite(fid, trecN,'int32'); + +fwrite(fid, trec1,'int32'); +fwrite(fid,seconds,'int32'); +fwrite(fid, days+1,'int32'); +fwrite(fid, trecN,'int32'); + +% read state vector variables. +fwrite(fid, rec1, 'int32'); +fwrite(fid, datvec, 'float64'); +fwrite(fid, recN, 'int32'); +fclose(fid); + + function C = get_3D_permuted(fid, shape, typestr) datasize = prod(shape); A = fread(fid, prod(shape), typestr); From nancy at ucar.edu Thu Aug 27 14:08:07 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:08:07 -0600 (MDT) Subject: [Dart-dev] [4013] DART/trunk/shell_scripts: Template files which have the right syntax for various shells. Message-ID: <200908272008.n7RK87A8011275@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/c8f29612/attachment.html -------------- next part -------------- Added: DART/trunk/shell_scripts/day_template.bash =================================================================== --- DART/trunk/shell_scripts/day_template.bash (rev 0) +++ DART/trunk/shell_scripts/day_template.bash 2009-08-27 20:08:07 UTC (rev 4013) @@ -0,0 +1,85 @@ +#!/bin/bash + +# this is a template for a shell script that can loop +# over multiple days and roll over month boundaries +# or even year boundaries. see the section inside the loop +# for the 'your code goes here' part. look for the string ADDME. +# this script requires the executable 'advance_time' to be +# built and exist in the current directory, and advance_time +# requires an input.nml namelist file. + +# it computes the gregorian day if useful, and makes sure +# the days and months are always 2 digits long. + +# set the first and last days. can roll over month and year boundaries. +let start_year=2006 +let start_month=1 +let start_day=31 + +let end_year=2006 +let end_month=2 +let end_day=3 + +# put more stuff here if you have user settable options + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. + +# the output of advance time with the -g input is: +# gregorian_day_number seconds +# use ${var[0]} to return just the day number + +mon2=`printf %02d $end_month` +day2=`printf %02d $end_day` +end_d=(`echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time`) + +mon2=`printf %02d $start_month` +day2=`printf %02d $start_day` +start_d=(`echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time`) + +# the output of this call is a string YYYYMMDDHH +# see below for help in how to easily parse this up into words +curday=`echo ${start_year}${mon2}${day2}00 0 | ./advance_time` + +# how many total days are going to be processed (for the loop counter) +let totaldays=${end_d[0]}-${start_d[0]} +let totaldays=$totaldays+1 + +# loop over each day +let d=1 +while (( d <= totaldays)) ; do + + # parse out the parts from a string which is YYYYMMDDHH + # use cut with the byte option to pull out columns 1-4, 5-6, and 7-8 + year=`echo $curday | cut -b1-4` + month=`echo $curday | cut -b5-6` + day=`echo $curday | cut -b7-8` + + # compute the equivalent gregorian day here. + g=(`echo ${year}${month}${day}00 0 -g | ./advance_time`) + greg=${g[0]} + + # status/debug - comment in or out as desired. + echo starting processing for ${year} ${month} ${day} + echo which is gregorian day: $greg + + + # your code goes here. + # use $year, $month, $day, and $greg as needed + + + # advance the day; the output is YYYYMMDD00 + curday=`echo ${year}${month}${day}00 +1d | ./advance_time` + + # advance the loop counter + let d=d+1 + +done + +exit 0 + Property changes on: DART/trunk/shell_scripts/day_template.bash ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/shell_scripts/day_template.csh =================================================================== --- DART/trunk/shell_scripts/day_template.csh (rev 0) +++ DART/trunk/shell_scripts/day_template.csh 2009-08-27 20:08:07 UTC (rev 4013) @@ -0,0 +1,87 @@ +#!/bin/csh + +# this is a template for a shell script that can loop +# over multiple days and roll over month boundaries +# or even year boundaries. see the section inside the loop +# for the 'your code goes here' part. look for the string ADDME. +# this script requires the executable 'advance_time' to be +# built and exist in the current directory, and advance_time +# requires an input.nml namelist file. + +# it computes the gregorian day if useful, and makes sure +# the days and months are always 2 digits long. + +# set the first and last days. can roll over month and year boundaries. +set start_year=2006 +set start_month=10 +set start_day=31 + +set end_year=2006 +set end_month=11 +set end_day=3 + +# put more stuff here if you have user settable options + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. + +# the output of advance time with the -g input is: +# gregorian_day_number seconds +# use $var[1] to return just the day number + +set mon2=`printf %02d $end_month` +set day2=`printf %02d $end_day` +set end_d=(`echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time`) + +set mon2=`printf %02d $start_month` +set day2=`printf %02d $start_day` +set start_d=(`echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time`) + +# the output of this call is a string YYYYMMDDHH +# see below for help in how to easily parse this up into words +set curday=`echo ${start_year}${mon2}${day2}00 0 | ./advance_time` + +# how many total days are going to be processed (for the loop counter) +# note that the parens below are necessary; otherwise the computation +# does total = end - (start+1), or total = end - start - 1, which is +# not how elementary math is supposed to work. +@ totaldays = ( $end_d[1] - $start_d[1] ) + 1 + +# loop over each day +set d=1 +while ( $d <= $totaldays ) + + # parse out the parts from a string which is YYYYMMDDHH + # use cut with the byte option to pull out columns 1-4, 5-6, and 7-8 + set year=`echo $curday | cut -b1-4` + set month=`echo $curday | cut -b5-6` + set day=`echo $curday | cut -b7-8` + + # compute the equivalent gregorian day here. + set g=(`echo ${year}${month}${day}00 0 -g | ./advance_time`) + set greg=$g[1] + + # status/debug - comment in or out as desired. + echo starting processing for ${year} ${month} ${day} + echo which is gregorian day: $greg + + + # your code goes here. + # use $year, $month, $day, and $greg as needed. + + + # advance the day; the output is YYYYMMDD00 + set curday=`echo ${year}${month}${day}00 +1d | ./advance_time` + + # advance the loop counter + @ d += 1 + +end + +exit 0 + Property changes on: DART/trunk/shell_scripts/day_template.csh ___________________________________________________________________ Name: svn:executable + * Name: svn:keywords + Date Revision Author HeadURL Id Added: DART/trunk/shell_scripts/day_template.ksh =================================================================== --- DART/trunk/shell_scripts/day_template.ksh (rev 0) +++ DART/trunk/shell_scripts/day_template.ksh 2009-08-27 20:08:07 UTC (rev 4013) @@ -0,0 +1,84 @@ +#!/bin/ksh + +# this is a template for a shell script that can loop +# over multiple days and roll over month boundaries +# or even year boundaries. see the section inside the loop +# for the 'your code goes here' part. look for the string ADDME. +# this script requires the executable 'advance_time' to be +# built and exist in the current directory, and advance_time +# requires an input.nml namelist file. + +# it computes the gregorian day if useful, and makes sure +# the days and months are always 2 digits long. + +# set the first and last days. can roll over month and year boundaries. +let start_year=2006 +let start_month=1 +let start_day=31 + +let end_year=2006 +let end_month=2 +let end_day=3 + +# put more stuff here if you have user settable options + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. + +# the output of advance time with the -g input is: +# gregorian_day_number seconds +# use ${var[0]} to return just the day number + +mon2=`printf %02d $end_month` +day2=`printf %02d $end_day` +set -A end_d `echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time` + +mon2=`printf %02d $start_month` +day2=`printf %02d $start_day` +set -A start_d `echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time` + +# the output of this call is a string YYYYMMDDHH +# see below for help in how to easily parse this up into words +curday=`echo ${start_year}${mon2}${day2}00 0 | ./advance_time` + +# how many total days are going to be processed (for the loop counter) +let totaldays=${end_d[0]}-${start_d[0]}+1 + +# loop over each day +let d=1 +while (( d <= totaldays)) ; do + + # parse out the parts from a string which is YYYYMMDDHH + # use cut with the byte option to pull out columns 1-4, 5-6, and 7-8 + year=`echo $curday | cut -b1-4` + month=`echo $curday | cut -b5-6` + day=`echo $curday | cut -b7-8` + + # compute the equivalent gregorian day here. + set -A g `echo ${year}${month}${day}00 0 -g | ./advance_time` + greg=${g[0]} + + # status/debug - comment in or out as desired. + echo starting processing for ${year} ${month} ${day} + echo which is gregorian day: $greg + + + # your code goes here. + # use $year, $month, $day, and $greg as needed + + + # advance the day; the output is YYYYMMDD00 + curday=`echo ${year}${month}${day}00 +1d | ./advance_time` + + # advance the loop counter + let d=d+1 + +done + +exit 0 + Property changes on: DART/trunk/shell_scripts/day_template.ksh ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/shell_scripts/day_template.zsh =================================================================== --- DART/trunk/shell_scripts/day_template.zsh (rev 0) +++ DART/trunk/shell_scripts/day_template.zsh 2009-08-27 20:08:07 UTC (rev 4013) @@ -0,0 +1,84 @@ +#!/bin/zsh + +# this is a template for a shell script that can loop +# over multiple days and roll over month boundaries +# or even year boundaries. see the section inside the loop +# for the 'your code goes here' part. look for the string ADDME. +# this script requires the executable 'advance_time' to be +# built and exist in the current directory, and advance_time +# requires an input.nml namelist file. + +# it computes the gregorian day if useful, and makes sure +# the days and months are always 2 digits long. + +# set the first and last days. can roll over month and year boundaries. +let start_year=2006 +let start_month=1 +let start_day=31 + +let end_year=2006 +let end_month=2 +let end_day=3 + +# put more stuff here if you have user settable options + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. + +# the output of advance time with the -g input is: +# gregorian_day_number seconds +# use ${var[0]} to return just the day number + +mon2=`printf %02d $end_month` +day2=`printf %02d $end_day` +set -A end_d `echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time` + +mon2=`printf %02d $start_month` +day2=`printf %02d $start_day` +set -A start_d `echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time` + +# the output of this call is a string YYYYMMDDHH +# see below for help in how to easily parse this up into words +curday=`echo ${start_year}${mon2}${day2}00 0 | ./advance_time` + +# how many total days are going to be processed (for the loop counter) +let totaldays=${end_d[0]}-${start_d[0]}+1 + +# loop over each day +let d=1 +while (( d <= totaldays)) ; do + + # parse out the parts from a string which is YYYYMMDDHH + # use cut with the byte option to pull out columns 1-4, 5-6, and 7-8 + year=`echo $curday | cut -b1-4` + month=`echo $curday | cut -b5-6` + day=`echo $curday | cut -b7-8` + + # compute the equivalent gregorian day here. + set -A g `echo ${year}${month}${day}00 0 -g | ./advance_time` + greg=${g[0]} + + # status/debug - comment in or out as desired. + echo starting processing for ${year} ${month} ${day} + echo which is gregorian day: $greg + + + # your code goes here. + # use $year, $month, $day, and $greg as needed + + + # advance the day; the output is YYYYMMDD00 + curday=`echo ${year}${month}${day}00 +1d | ./advance_time` + + # advance the loop counter + let d=d+1 + +done + +exit 0 + Property changes on: DART/trunk/shell_scripts/day_template.zsh ___________________________________________________________________ Name: svn:executable + * From nancy at ucar.edu Thu Aug 27 14:08:40 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:08:40 -0600 (MDT) Subject: [Dart-dev] [4014] DART/trunk/observations/gps/work/path_names_advance_time: Fix the name of the utilities_mod file. Message-ID: <200908272008.n7RK8e0U011871@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/19958cb3/attachment.html -------------- next part -------------- Modified: DART/trunk/observations/gps/work/path_names_advance_time =================================================================== --- DART/trunk/observations/gps/work/path_names_advance_time 2009-08-27 20:08:07 UTC (rev 4013) +++ DART/trunk/observations/gps/work/path_names_advance_time 2009-08-27 20:08:40 UTC (rev 4014) @@ -1,6 +1,6 @@ time_manager/advance_time.f90 time_manager/time_manager_mod.f90 common/types_mod.f90 -utilities/utilities_lite_mod.f90 +utilities/utilities_mod.f90 utilities/parse_args_mod.f90 mpi_utilities/null_mpi_utilities_mod.f90 From nancy at ucar.edu Thu Aug 27 14:13:52 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:13:52 -0600 (MDT) Subject: [Dart-dev] [4015] DART/trunk/models/wrf/work: Add mkmf and path_names files for the time utility which uses the DART Message-ID: <200908272013.n7RKDqMb016947@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/b121a68f/attachment.html -------------- next part -------------- Added: DART/trunk/models/wrf/work/mkmf_advance_time =================================================================== --- DART/trunk/models/wrf/work/mkmf_advance_time (rev 0) +++ DART/trunk/models/wrf/work/mkmf_advance_time 2009-08-27 20:13:51 UTC (rev 4015) @@ -0,0 +1,15 @@ +#!/bin/csh +# +# Data Assimilation Research Testbed -- DART +# Copyright 2004-2007, Data Assimilation Research Section +# University Corporation for Atmospheric Research +# Licensed under the GPL -- www.gpl.org/licenses/gpl.html +# +# +# $URL: http://subversion.ucar.edu/DAReS/DART/trunk/models/bgrid_solo/work/mkmf_merge_obs_seq $ +# $Id: mkmf_merge_obs_seq 2691 2007-03-11 18:18:09Z thoar $ +# $Revision: 2691 $ +# $Date: 2007-03-11 12:18:09 -0600 (Sun, 11 Mar 2007) $ +# +../../../mkmf/mkmf -p advance_time -t ../../../mkmf/mkmf.template -c"-Duse_netCDF" \ + -a "../../.." path_names_advance_time Property changes on: DART/trunk/models/wrf/work/mkmf_advance_time ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/models/wrf/work/path_names_advance_time =================================================================== --- DART/trunk/models/wrf/work/path_names_advance_time (rev 0) +++ DART/trunk/models/wrf/work/path_names_advance_time 2009-08-27 20:13:51 UTC (rev 4015) @@ -0,0 +1,6 @@ +time_manager/advance_time.f90 +time_manager/time_manager_mod.f90 +common/types_mod.f90 +utilities/utilities_mod.f90 +utilities/parse_args_mod.f90 +mpi_utilities/null_mpi_utilities_mod.f90 From nancy at ucar.edu Thu Aug 27 14:15:42 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:15:42 -0600 (MDT) Subject: [Dart-dev] [4016] DART/trunk/observations/AIRS/airs_obs_mod.f90: Use the parameter defined in a standard module to set the length of the Message-ID: <200908272015.n7RKFgkx018893@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/43aaeae2/attachment-0001.html -------------- next part -------------- Modified: DART/trunk/observations/AIRS/airs_obs_mod.f90 =================================================================== --- DART/trunk/observations/AIRS/airs_obs_mod.f90 2009-08-27 20:13:51 UTC (rev 4015) +++ DART/trunk/observations/AIRS/airs_obs_mod.f90 2009-08-27 20:15:42 UTC (rev 4016) @@ -11,7 +11,7 @@ ! $Revision: 3809 $ ! $Date: 2009-04-13 10:21:33 -0600 (Mon, 13 Apr 2009) $ -use types_mod, only : r4, r8, digits12, deg2rad, rad2deg +use types_mod, only : r4, r8, digits12, deg2rad, rad2deg, metadatalength use obs_def_mod, only : obs_def_type, get_obs_def_time, read_obs_def, & write_obs_def, destroy_obs_def, & @@ -61,7 +61,7 @@ logical :: DEBUG = .false. -real(r8), parameter :: mb_to_hPa = 100.0 ! millibars to hectopascals +real(r8), parameter :: mb_to_Pa = 100.0 ! millibars to pascals ! the sizes of the Temperature arrays are: ! (AIRS_RET_STDPRESSURELAY, AIRS_RET_GEOXTRACK, AIRS_RET_GEOTRACK) @@ -126,7 +126,7 @@ type(time_type) :: obs_time, base_time, pre_time, time -character(len = 129) :: meta_data +character(len = metadatalength) :: meta_data if ( .not. module_initialized ) call initialize_module @@ -260,7 +260,7 @@ obs_var = granule%TAirStdErr(ivert, icol, irow) * & granule%TAirStdErr(ivert, icol, irow) - vloc = granule%pressStd(ivert) * mb_to_hPa + vloc = granule%pressStd(ivert) * mb_to_Pa call real_obs(num_copies, num_qc, obs, olon, olat, vloc, obs_value, & obs_var, tqc, AIRS_TEMPERATURE, which_vert, seconds, days) @@ -299,7 +299,7 @@ obs_value = Q(ivert, icol, irow) obs_var = Q_err(ivert, icol, irow) * Q_err(ivert, icol, irow) - vloc = granule%pressH2O(ivert) * mb_to_hPa + vloc = granule%pressH2O(ivert) * mb_to_Pa call real_obs(num_copies, num_qc, obs, olon, olat, vloc, obs_value, & obs_var, qqc, AIRS_SPECIFIC_HUMIDITY, which_vert, seconds, days) From nancy at ucar.edu Thu Aug 27 14:17:01 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:17:01 -0600 (MDT) Subject: [Dart-dev] [4017] DART/trunk/observations/AIRS/work: Add mkmf and path_names files to build the obs_seq tool in Message-ID: <200908272017.n7RKH1nD020140@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/ad69b411/attachment.html -------------- next part -------------- Added: DART/trunk/observations/AIRS/work/mkmf_obs_sequence_tool =================================================================== --- DART/trunk/observations/AIRS/work/mkmf_obs_sequence_tool (rev 0) +++ DART/trunk/observations/AIRS/work/mkmf_obs_sequence_tool 2009-08-27 20:17:01 UTC (rev 4017) @@ -0,0 +1,15 @@ +#!/bin/csh +# +# Data Assimilation Research Testbed -- DART +# Copyright 2004-2007, Data Assimilation Research Section +# University Corporation for Atmospheric Research +# Licensed under the GPL -- www.gpl.org/licenses/gpl.html +# +# +# $URL: https://subversion.ucar.edu/DAReS/DART/trunk/observations/utilities/threed_sphere/mkmf_obs_sequence_tool $ +# $Id: mkmf_obs_sequence_tool 3836 2009-05-01 00:25:15Z thoar $ +# $Revision: 3836 $ +# $Date: 2009-04-30 18:25:15 -0600 (Thu, 30 Apr 2009) $ +# +../../../mkmf/mkmf -p obs_sequence_tool -t ../../../mkmf/mkmf.template -c"-Duse_netCDF" \ + -a "../../.." path_names_obs_sequence_tool Property changes on: DART/trunk/observations/AIRS/work/mkmf_obs_sequence_tool ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/observations/AIRS/work/path_names_obs_sequence_tool =================================================================== --- DART/trunk/observations/AIRS/work/path_names_obs_sequence_tool (rev 0) +++ DART/trunk/observations/AIRS/work/path_names_obs_sequence_tool 2009-08-27 20:17:01 UTC (rev 4017) @@ -0,0 +1,13 @@ +assim_model/assim_model_mod.f90 +common/types_mod.f90 +location/threed_sphere/location_mod.f90 +models/template/model_mod.f90 +mpi_utilities/null_mpi_utilities_mod.f90 +obs_def/obs_def_mod.f90 +obs_kind/obs_kind_mod.f90 +obs_sequence/obs_sequence_mod.f90 +obs_sequence/obs_sequence_tool.f90 +random_nr/random_nr_mod.f90 +random_seq/random_seq_mod.f90 +time_manager/time_manager_mod.f90 +utilities/utilities_mod.f90 From nancy at ucar.edu Thu Aug 27 14:17:34 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:17:34 -0600 (MDT) Subject: [Dart-dev] [4018] DART/trunk/observations/AIRS/work: mkmf and path_names files for the advance_time util, which is used Message-ID: <200908272017.n7RKHXqn020813@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/fd3e2cb2/attachment.html -------------- next part -------------- Added: DART/trunk/observations/AIRS/work/mkmf_advance_time =================================================================== --- DART/trunk/observations/AIRS/work/mkmf_advance_time (rev 0) +++ DART/trunk/observations/AIRS/work/mkmf_advance_time 2009-08-27 20:17:33 UTC (rev 4018) @@ -0,0 +1,15 @@ +#!/bin/csh +# +# Data Assimilation Research Testbed -- DART +# Copyright 2004-2007, Data Assimilation Research Section +# University Corporation for Atmospheric Research +# Licensed under the GPL -- www.gpl.org/licenses/gpl.html +# +# +# $URL: http://subversion.ucar.edu/DAReS/DART/trunk/models/bgrid_solo/work/mkmf_merge_obs_seq $ +# $Id: mkmf_merge_obs_seq 2691 2007-03-11 18:18:09Z thoar $ +# $Revision: 2691 $ +# $Date: 2007-03-11 12:18:09 -0600 (Sun, 11 Mar 2007) $ +# +../../../mkmf/mkmf -p advance_time -t ../../../mkmf/mkmf.template -c"-Duse_netCDF" \ + -a "../../.." path_names_advance_time Property changes on: DART/trunk/observations/AIRS/work/mkmf_advance_time ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/observations/AIRS/work/path_names_advance_time =================================================================== --- DART/trunk/observations/AIRS/work/path_names_advance_time (rev 0) +++ DART/trunk/observations/AIRS/work/path_names_advance_time 2009-08-27 20:17:33 UTC (rev 4018) @@ -0,0 +1,6 @@ +time_manager/advance_time.f90 +time_manager/time_manager_mod.f90 +common/types_mod.f90 +utilities/utilities_lite_mod.f90 +utilities/parse_args_mod.f90 +mpi_utilities/null_mpi_utilities_mod.f90 From nancy at ucar.edu Thu Aug 27 14:19:52 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 14:19:52 -0600 (MDT) Subject: [Dart-dev] [4019] DART/trunk/observations/AIRS: The scripts used to generate multiple days of AIRS data files, with Message-ID: <200908272019.n7RKJqkT023277@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/4098b79d/attachment.html -------------- next part -------------- Added: DART/trunk/observations/AIRS/shell_scripts/README =================================================================== --- DART/trunk/observations/AIRS/shell_scripts/README (rev 0) +++ DART/trunk/observations/AIRS/shell_scripts/README 2009-08-27 20:19:52 UTC (rev 4019) @@ -0,0 +1,7 @@ + +These scripts are intended to help download the original AIRS hdf +data files, convert them in bulk, and merge the resulting obs_seq files. + +In most cases, they're intended to be copied over to the ../work directory +and then customized for the particular time period and local directory names. + Added: DART/trunk/observations/AIRS/shell_scripts/download.sh =================================================================== --- DART/trunk/observations/AIRS/shell_scripts/download.sh (rev 0) +++ DART/trunk/observations/AIRS/shell_scripts/download.sh 2009-08-27 20:19:52 UTC (rev 4019) @@ -0,0 +1,58 @@ +#!/bin/bash + +# download the requested tar files from the NCAR mass store. + +# set the first and last days. can roll over +# month and year boundaries now! +let start_year=2006 +let start_month=10 +let start_day=1 + +let end_year=2007 +let end_month=1 +let end_day=31 + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. +mon2=`printf %02d $end_month` +day2=`printf %02d $end_day` +end_d=(`echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time`) + +mon2=`printf %02d $start_month` +day2=`printf %02d $start_day` +start_d=(`echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time`) + +curday=(`echo ${start_year}${mon2}${day2}00 0 | ./advance_time`) + +# how many total days are going to be converted (for the loop counter) +let totaldays=${end_d[0]}-${start_d[0]}+1 + +# loop over each day +let d=1 +while (( d <= totaldays)) ; do + + # parse out the parts from a string which is YYYYMMDDHH + year=${curday:0:4} + month=${curday:4:2} + day=${curday:6:2} + + + echo getting ${year}${month}${day}.tar from mass store + msrcp mss:/MIJEONG/AIRS/V5/L2/${year}${month}/${year}${month}${day}.tar . + + + # advance the day; the output is YYYYMMDD00 + curday=(`echo ${year}${month}${day}00 +1d | ./advance_time`) + + # advance the loop counter + let d=d+1 + +done + +exit 0 + Property changes on: DART/trunk/observations/AIRS/shell_scripts/download.sh ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/observations/AIRS/shell_scripts/mergeit.sh =================================================================== --- DART/trunk/observations/AIRS/shell_scripts/mergeit.sh (rev 0) +++ DART/trunk/observations/AIRS/shell_scripts/mergeit.sh 2009-08-27 20:19:52 UTC (rev 4019) @@ -0,0 +1,94 @@ +#!/bin/bash + +# merge the files into "daily" files which start at 03:01Z +# and end at 03:00Z the following day. (the name of the file +# is the first day.) + +# set the first and last days to be merged. can roll over +# month and year boundaries now! note that for the end day, +# you need at least the first 40ish files from the following day +# for the merge to have the right data (from 0Z to 3Z) available. + +let start_year=2006 +let start_month=10 +let start_day=1 + +let end_year=2007 +let end_month=1 +let end_day=31 + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. + +# these outputs from advance time (with the -g flag) are +# 2 integers: gregorian_day_number seconds +# and since we don't set hours, minutes, or seconds, the second +# number is always 0 and uninteresting for us. +mon2=`printf %02d $end_month` +day2=`printf %02d $end_day` +end_d=(`echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time`) + +mon2=`printf %02d $start_month` +day2=`printf %02d $start_day` +start_d=(`echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time`) + +# these are a string in the format YYYYMMDDHH +# do them here to prime the loop below which first takes them apart. +curday=(`echo ${start_year}${mon2}${day2}00 0 | ./advance_time`) +nextday=(`echo ${start_year}${mon2}${day2}00 +1d | ./advance_time`) + +# how many total days are going to be merged (for the loop counter) +# (pull out the first of the 2 numbers which are output from advance_time) +let totaldays=${end_d[0]}-${start_d[0]}+1 + +# loop over each day +let d=1 +while (( d <= totaldays)) ; do + + # parse out the parts from a string which is YYYYMMDDHH + # both for the current day and tomorrow + cyear=${curday:0:4} + cmonth=${curday:4:2} + cday=${curday:6:2} + nyear=${nextday:0:4} + nmonth=${nextday:4:2} + nday=${nextday:6:2} + + # compute the equivalent gregorian days here. + g=(`echo ${cyear}${cmonth}${cday}00 0 -g | ./advance_time`) + greg1=${g[0]} + let greg2=greg1+1 + + echo starting AIRS obs merge ${cyear}${cmonth}${cday} + echo gregorian: $greg + + # all of todays data plus the first 40 of tomorrows + ls AIRS.${cyear}.${cmonth}.${cday}.*.out > olist + ls AIRS.${nyear}.${nmonth}.${nday}.0[0123]?.out >> olist + + sed -e "s/YYYY/${cyear}/g" \ + -e "s/MM/${cmonth}/g" \ + -e "s/DD/${cday}/g" \ + -e "s/GREG1/${greg1}/g" \ + -e "s/GREG2/${greg2}/g" < ./input.nml.template > input.nml + + # do the merge here + ./obs_sequence_tool + + + # advance the day; the output is YYYYMMDD00 + curday=nextday + nextday=(`echo ${year}${month}${day}00 +1d | ./advance_time`) + + # advance the loop counter + let d=d+1 + +done + +exit 0 + Property changes on: DART/trunk/observations/AIRS/shell_scripts/mergeit.sh ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh =================================================================== --- DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh (rev 0) +++ DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh 2009-08-27 20:19:52 UTC (rev 4019) @@ -0,0 +1,113 @@ +#!/bin/bash + +# this version gets the tar file from the mass store first. +# unpack one day of tar files at a time, convert them into +# individual obs_seq files. this program also does the merge +# of the 240 individual daily swaths into a single obs_seq file. + +# this program should be started from the work directory. +# it assumes ../data, ../tars, the output dir, etc +# exist relative to starting from AIRS/work. + +# set the first and last days to be converted. can roll over +# month and year boundaries now! +let start_year=2006 +let start_month=10 +let start_day=1 + +let end_year=2007 +let end_month=1 +let end_day=31 + +# relative to work dir +output_dir=../output.thin + +# whether to download the tar file from the mass store or not +# set to one of: true or false +download=true + +# end of things you should have to set in this script + +# convert the start and stop times to gregorian days, so we can +# compute total number of days including rolling over month and +# year boundaries. make sure all values have leading 0s if they +# are < 10. do the end time first so we can use the same values +# to set the initial day while we are doing the total day calc. +mon2=`printf %02d $end_month` +day2=`printf %02d $end_day` +end_d=(`echo ${end_year}${mon2}${day2}00 0 -g | ./advance_time`) + +mon2=`printf %02d $start_month` +day2=`printf %02d $start_day` +start_d=(`echo ${start_year}${mon2}${day2}00 0 -g | ./advance_time`) + +curday=(`echo ${start_year}${mon2}${day2}00 0 | ./advance_time`) + +# how many total days are going to be converted (for the loop counter) +let totaldays=${end_d[0]}-${start_d[0]}+1 + +# loop over each day +let d=1 +while (( d <= totaldays)) ; do + + # parse out the parts from a string which is YYYYMMDDHH + year=${curday:0:4} + month=${curday:4:2} + day=${curday:6:2} + + # compute the equivalent gregorian day here. + g=(`echo ${year}${month}${day}00 0 -g | ./advance_time`) + greg=${g[0]} + + echo starting AIRS to obs ${year}${month}${day} + echo gregorian: $greg + + # download the tar file from the mss first + if [[ "$download" = "true" ]]; then + echo getting ${year}${month}${day}.tar from mass store + (cd ../tars; msrcp mss:/MIJEONG/AIRS/V5/L2/${year}${month}/${year}${month}${day}.tar . ) + fi + + # assume the original collection of data (hdf files, one per swath) + # are in ../tars and that the filenames inside the tar files are named + # YYYYMM/YYYYMMDD/*.hdf + (cd ../data; tar -xvf ../tars/${year}${month}${day}.tar >> tarlog) + + # construct the input list of files for the converter. + # cd there first in a subshell so the ls just contains simple file names + (cd ../data/${year}${month}/${year}${month}${day}; ls AIR*hdf > flist) + + # get back to work dir and edit a template file to set the + # values that change in the namelists. + sed -e "s/YYYY/${year}/g" \ + -e "s/MM/${month}/g" \ + -e "s/DD/${day}/g" \ + -e "s/GREG/${greg}/g" < ./input.nml.template > input.nml + + # actually make the obs_seq files, one per input. these still need to + # be merged if you want daily files. + ./convert_airs_L2 + + # do the merge now + ls ${output_dir}/AIRS.${year}.${month}.${day}.*.out > olist + ./obs_sequence_tool + + # start local mods + # ok, this is a local mod - to try to keep from running out of disk space + remote_dir=/gpfs/ptmp/dart/Obs_sets/AIRS_24_subx4_ascii/${year}${month}/ + cp -f ${output_dir}/AIRS.${year}${month}${day}.out $remote_dir + # and clean up so we don't run out of disk space + (cd ../data/${year}${month}/${year}${month}${day}; rm AIR*hdf) + (cd ${output_dir}; rm AIRS.${year}.${month}.${day}.*.out) + (cd ../tars; rm ${year}${month}${day}.tar) + # end local mods + + # advance the day; the output is YYYYMMDD00 + curday=(`echo ${year}${month}${day}00 +1d | ./advance_time`) + + # advance the loop counter + let d=d+1 + +done + +exit 0 Property changes on: DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh ___________________________________________________________________ Name: svn:executable + * From nancy at ucar.edu Thu Aug 27 17:19:21 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Thu, 27 Aug 2009 17:19:21 -0600 (MDT) Subject: [Dart-dev] [4020] DART/trunk/models/POP: The grid information is not in the LANL-POP restart file, so it must be Message-ID: <200908272319.n7RNJLZ8022210@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090827/20731766/attachment-0001.html -------------- next part -------------- Modified: DART/trunk/models/POP/README =================================================================== --- DART/trunk/models/POP/README 2009-08-27 20:19:52 UTC (rev 4019) +++ DART/trunk/models/POP/README 2009-08-27 23:19:20 UTC (rev 4020) @@ -6,6 +6,8 @@ Tim + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + (this should stay in the README. at some point we might want to move the test program to a separate test directory, in which case this file needs to be updated to reflect that.) @@ -18,3 +20,39 @@ http://www.image.ucar.edu/pub/DART/POP/ nancy + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tim : Tue Jul 21 17:45:52 MDT 2009 + +Working on reading the BINARY grid files instead of the (nonexistent) +netCDF ones. Getting grid sizes from restart netCDF file and must make +hard assumptions about variable storage order. + +dart_pop_mod is being modified to read the pop_in namelist and then set things +like the ocean dynamics timestep. Must ensure that the model_mod then uses that +to set a valid adv_to_time ... + +dart_pop_mod must also set the time_manager_nml:stop_count (and stop_option) to +the right values. + +dart_pop_mod must also create a pointer file with the expected restart file as +a way to make sure the model has advanced to the proper spot. + +advance_model.csh must paste the pop_in.DART namelist on top of the pop_in namelist +for model control ... + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is how I understand (LANL) POP to work: + +Given: +&init_ts_nml + init_ts_option = 'restart' + init_ts_file = 'pop.r' + init_ts_file_fmt = 'nc' +/ + +The init_ts_file entry is completely ignored. A pointer file with the name +"pop_pointer.restart" contains the name of the restart file. + Modified: DART/trunk/models/POP/dart_pop_mod.f90 =================================================================== --- DART/trunk/models/POP/dart_pop_mod.f90 2009-08-27 20:19:52 UTC (rev 4019) +++ DART/trunk/models/POP/dart_pop_mod.f90 2009-08-27 23:19:20 UTC (rev 4020) @@ -11,307 +11,629 @@ ! $Revision$ ! $Date$ -use types_mod, only : r8, rad2deg, PI -use obs_def_mod, only : obs_def_type, get_obs_def_time, read_obs_def, & - write_obs_def, destroy_obs_def, interactive_obs_def, & - copy_obs_def, set_obs_def_time, set_obs_def_kind, & - set_obs_def_error_variance, set_obs_def_location -use time_manager_mod, only : time_type, get_date, set_time, GREGORIAN, & - set_date, set_calendar_type, get_time, & - print_date, print_time, operator(==) +use types_mod, only : r8, rad2deg, PI, SECPERDAY +use time_manager_mod, only : time_type, get_date, set_date, get_time, set_time, & + set_calendar_type, get_calendar_string, & + print_date, print_time, operator(==), operator(-) use utilities_mod, only : get_unit, open_file, close_file, file_exist, & - register_module, error_handler, & - E_ERR, E_MSG, timestamp -use location_mod, only : location_type, set_location, VERTISHEIGHT, VERTISSURFACE -use obs_sequence_mod, only : init_obs_sequence, init_obs, insert_obs_in_seq, & - set_obs_values, set_qc, obs_sequence_type, obs_type, & - copy_obs, set_copy_meta_data, set_qc_meta_data, set_obs_def, & - get_first_obs, get_last_obs, get_obs_def + register_module, error_handler, nc_check, & + find_namelist_in_file, check_namelist_read, & + E_ERR, E_MSG, timestamp, find_textfile_dims, & + logfileunit -use obs_kind_mod, only : get_obs_kind_index +use typesizes +use netcdf implicit none private -public :: real_obs_sequence +public :: get_pop_calendar, set_model_time_step, & + get_horiz_grid_dims, get_vert_grid_dim, & + read_horiz_grid, read_topography, read_vert_grid, & + write_pop_namelist ! version controlled file description for error handling, do not edit character(len=128), parameter :: & - source = "$URL$", & - revision = "$Revision$", & - revdate = "$Date$" + source = '$URL$', & + revision = '$Revision$', & + revdate = '$Date$' +character(len=256) :: msgstring logical, save :: module_initialized = .false. +character(len=256) :: ic_filename, restart_filename + ! set this to true if you want to print out the current time ! after each N observations are processed, for benchmarking. logical :: print_timestamps = .false. integer :: print_every_Nth = 10000 -contains +!------------------------------------------------------------------ +! The POP time manager namelist variables +!------------------------------------------------------------------ -!------------------------------------------------- +character(len=100) :: accel_file ! length consistent with POP +character(len= 64) :: stop_option, runid, dt_option, time_mix_opt +character(len= 1) :: date_separator +logical :: impcor, laccel, allow_leapyear +real(r8) :: dtuxcel, dt_count +integer :: iyear0, imonth0, iday0, ihour0, iminute0, isecond0 +integer :: stop_count, fit_freq, time_mix_freq -function real_obs_sequence (obsfile, year, month, day, max_num, & - lon1, lon2, lat1, lat2) -!------------------------------------------------------------------------------ -! this function is to prepare data to DART sequence format +namelist /time_manager_nml/ runid, time_mix_opt, time_mix_freq, & + impcor, laccel, accel_file, dtuxcel, iyear0, imonth0, & + iday0, ihour0, iminute0, isecond0, dt_option, dt_count, & + stop_option, stop_count, date_separator, allow_leapyear, fit_freq + +!------------------------------------------------------------------ +! The POP restart manager namelist variables +!------------------------------------------------------------------ + +character(len=100) :: restart_outfile ! length consistent with POP +character(len= 64) :: restart_freq_opt, restart_fmt +logical :: leven_odd_on, pressure_correction +integer :: restart_freq, even_odd_freq + +namelist /restart_nml/ restart_freq_opt, restart_freq, restart_outfile, & + restart_fmt, leven_odd_on, even_odd_freq, pressure_correction + +!------------------------------------------------------------------ +! The POP initial temperature and salinity namelist +!------------------------------------------------------------------ + +character(len=100) :: init_ts_file ! length consistent with POP +character(len= 64) :: init_ts_option, init_ts_file_fmt + +namelist /init_ts_nml/ init_ts_option, init_ts_file, init_ts_file_fmt + +!------------------------------------------------------------------ +! The POP domain namelist +!------------------------------------------------------------------ + +character(len= 64) :: clinic_distribution_type, tropic_distribution_type +character(len= 64) :: ew_boundary_type, ns_boundary_type +integer :: nprocs_clinic, nprocs_tropic + +namelist /domain_nml/ clinic_distribution_type, nprocs_clinic, & + tropic_distribution_type, nprocs_tropic, & + ew_boundary_type, ns_boundary_type + +!------------------------------------------------------------------ +! The POP grid info namelist +!------------------------------------------------------------------ ! -character(len=129), intent(in) :: obsfile -integer, intent(in) :: year, month, day, max_num -real(r8), intent(in) :: lon1, lon2, lat1, lat2 +! POP grid information comes in several files: +! horizontal grid lat/lons in one, +! topography (lowest valid vert level) in another, and +! the vertical grid spacing in a third. +! +!------------------------------------------------------------------ +! +! Here is what we can get from the (binary) horiz grid file: +! real (r8), dimension(:,:), allocatable :: & +! ULAT, &! latitude (radians) of U points +! ULON, &! longitude (radians) of U points +! HTN , &! length (cm) of north edge of T box +! HTE , &! length (cm) of east edge of T box +! HUS , &! length (cm) of south edge of U box +! HUW , &! length (cm) of west edge of U box +! ANGLE ! angle +! +! Here is what we can get from the topography file: +! integer, dimension(:,:), allocatable :: & +! KMT ! k index of deepest grid cell on T grid +! +! These must be derived or come from someplace else ... +! KMU ! k index of deepest grid cell on U grid +! HT ! real(r8) value of deepest valid T depth (in cm) +! HU ! real(r8) value of deepest valid U depth (in cm) +! +! The vert grid file is ascii, with 3 columns/line: +! cell thickness(in cm) cell center(in m) cell bottom(in m) +! +!------------------------------------------------------------------ -type(obs_sequence_type) :: real_obs_sequence +character(len=100) :: horiz_grid_file, vert_grid_file, topography_file, & + bottom_cell_file, region_mask_file +character(len= 64) :: horiz_grid_opt, sfc_layer_opt, vert_grid_opt, & + topography_opt +logical :: partial_bottom_cells, topo_smooth, flat_bottom, lremove_points +namelist /grid_nml/ horiz_grid_opt, horiz_grid_file, sfc_layer_opt, & + vert_grid_opt, vert_grid_file, topography_opt, topography_file, & + partial_bottom_cells, bottom_cell_file, region_mask_file, & + topo_smooth, flat_bottom, lremove_points -type(obs_def_type) :: obs_def -type(obs_type) :: obs, prev_obs -integer :: i, num_copies, num_qc -integer :: days, seconds -integer :: yy, mn, dd, hh, mm, ss -integer :: startdate1, startdate2 -integer :: obs_num, calender_type, iskip -integer :: obs_unit -integer :: which_vert, obstype +!====================================================================== +contains +!====================================================================== -real (r8) :: lon, lat, vloc, obs_value -real (r8) :: aqc, var2, lonc -type(time_type) :: time, pre_time -character(len = 32) :: obs_kind_name -character(len = 80) :: label -character(len = 129) :: copy_meta_data, qc_meta_data +subroutine initialize_module +!------------------------------------------------------------------ +integer :: iunit, io -if ( .not. module_initialized ) call initialize_module +! Read POP calendar information +! In 'restart' mode, this is primarily the calendar type and 'stop' +! information. The time attributes of the restart file override +! the namelist time information. -num_copies = 1 -num_qc = 1 +call find_namelist_in_file('pop_in', 'time_manager_nml', iunit) +read(iunit, nml = time_manager_nml, iostat = io) +call check_namelist_read(iunit, io, 'time_manager_nml') -! Initialize an obs_sequence +if ( allow_leapyear ) then + call set_calendar_type('gregorian') +else + call set_calendar_type('noleap') +endif -call init_obs_sequence(real_obs_sequence, num_copies, num_qc, max_num) +! Read POP initial information (for input/restart filename) +! The tricky part here is that we should really check for +! the existence of the init_ts_file and take evasive action +! like checking for the existence of a pointer file. -! set meta data of obs_seq +call find_namelist_in_file('pop_in', 'init_ts_nml', iunit) +read(iunit, nml = init_ts_nml, iostat = io) +call check_namelist_read(iunit, io, 'init_ts_nml') -do i = 1, num_copies - copy_meta_data = 'observation' - call set_copy_meta_data(real_obs_sequence, i, copy_meta_data) -end do +ic_filename = trim(init_ts_file)//'.'//trim(init_ts_file_fmt) -do i = 1, num_qc - qc_meta_data = 'QC index' - call set_qc_meta_data(real_obs_sequence, i, qc_meta_data) -end do +! FIXME ... what about the pointer file ... +if ( .not. file_exist(ic_filename) ) then + msgstring = 'pop_in:init_ts_file '//trim(ic_filename)//' not found' + call error_handler(E_ERR,'initialize_module', & + msgstring, source, revision, revdate) +endif -! Initialize the obs variable +! Read POP restart information (for model timestepping/grid dimensions) +call find_namelist_in_file('pop_in', 'restart_nml', iunit) +read(iunit, nml = restart_nml, iostat = io) +call check_namelist_read(iunit, io, 'restart_nml') -call init_obs(obs, num_copies, num_qc) -call init_obs(prev_obs, num_copies, num_qc) +! Read POP domain information (for lon wrapping or not) +call find_namelist_in_file('pop_in', 'domain_nml', iunit) +read(iunit, nml = domain_nml, iostat = io) +call check_namelist_read(iunit, io, 'domain_nml') -! set observation time type -calender_type = GREGORIAN -call set_calendar_type(calender_type) +! Read POP grid information (for grid dims/filenames) +call find_namelist_in_file('pop_in', 'grid_nml', iunit) +read(iunit, nml = grid_nml, iostat = io) +call check_namelist_read(iunit, io, 'grid_nml') -! open observation data file +module_initialized = .true. -obs_unit = get_unit() -open(unit = obs_unit, file = obsfile, form='formatted', status='old') -print*, 'input file opened= ', trim(obsfile) -rewind (obs_unit) +! Print module information to log file and stdout. +call register_module(source, revision, revdate) -obs_num = 0 -iskip = 0 +end subroutine initialize_module -! loop over all observations within the file -!------------------------------------------------------------------------------ -obsloop: do - read(obs_unit,*,end=200) lon, lat, vloc, obs_value, which_vert, var2, aqc, & - obs_kind_name, startdate1, startdate2 +subroutine get_horiz_grid_dims(Nx, Ny) +!------------------------------------------------------------------ +! subroutine get_horiz_grid_dims(Nx, Ny) +! +! Read the lon, lat grid size from the restart netcdf file. +! The actual grid file is a binary file with no header information. +! +! The file name comes from module storage ... namelist. - !print*,'' - !print*,' Observation ', obs_num+1 - !print*,' lon lat vloc obs_value ',lon, lat, vloc, obs_value - !print*,' which_vert var2 aqc ',which_vert, var2, aqc - !print*,' obs_kind_name ',obs_kind_name - !print*,' date1 date2 ',startdate1, startdate2 +integer, intent(out) :: Nx ! Number of Longitudes +integer, intent(out) :: Ny ! Number of Latitudes - ! Calculate the DART time from the observation time - yy = startdate1/10000 - mn = mod(startdate1/100,100) - dd = mod(startdate1 ,100) - hh = startdate2/10000 - mm = mod(startdate2/100,100) - ss = mod(startdate2 ,100) - time = set_date(yy,mn,dd,hh,mm,ss) - call get_time(time,seconds,days) +integer :: grid_id, dimid, nc_rc - ! verify the location is not outside valid limits - if((lon > 360.0_r8) .or. (lon < 0.0_r8) .or. & - (lat > 90.0_r8) .or. (lat < -90.0_r8)) then - write(*,*) 'invalid location. lon,lat = ', lon, lat - iskip = iskip + 1 - cycle obsloop - endif +if ( .not. module_initialized ) call initialize_module - lonc = lon - if (lon2 > 360.0_r8 .and. lon < 180.0_r8) lonc = lon + 360.0_r8 +! get the ball rolling ... - ! reject observations outside the bounding box - if(lat < lat1 .or. lat > lat2 .or. lonc < lon1 .or. lonc > lon2) then - iskip = iskip + 1 - cycle obsloop +call nc_check(nf90_open(trim(ic_filename), nf90_nowrite, grid_id), & + 'get_horiz_grid_dims','open '//trim(ic_filename)) + +! Longitudes : get dimid for 'i' or 'nlon', and then get value +nc_rc = nf90_inq_dimid(grid_id, 'i', dimid) +if (nc_rc /= nf90_noerr) then + nc_rc = nf90_inq_dimid(grid_id, 'nlon', dimid) + if (nc_rc /= nf90_noerr) then + msgstring = "unable to find either 'i' or 'nlon' in file "//trim(ic_filename) + call error_handler(E_ERR, 'get_horiz_grid_dims', msgstring, & + source,revision,revdate) endif +endif - ! assign each observation the correct observation type - obstype = get_obs_kind_index(obs_kind_name) - if(obstype < 1) then - print*, 'unknown observation type [',trim(obs_kind_name),'] ... skipping ...' - cycle obsloop - !else - ! print*,trim(obs_kind_name),' is ',obstype +call nc_check(nf90_inquire_dimension(grid_id, dimid, len=Nx), & + 'get_horiz_grid_dims','inquire_dimension i '//trim(ic_filename)) + +! Latitudes : get dimid for 'j' or 'nlat' ... and then get value +nc_rc = nf90_inq_dimid(grid_id, 'j', dimid) +if (nc_rc /= nf90_noerr) then + nc_rc = nf90_inq_dimid(grid_id, 'nlat', dimid) + if (nc_rc /= nf90_noerr) then + msgstring = "unable to find either 'j' or 'nlat' in "//trim(ic_filename) + call error_handler(E_ERR, 'get_horiz_grid_dims', msgstring, & + source,revision,revdate) endif +endif - obs_num = obs_num + 1 +call nc_check(nf90_inquire_dimension(grid_id, dimid, len=Ny), & + 'get_horiz_grid_dims','inquire_dimension i '//trim(ic_filename)) - ! print a reassuring message after every Nth processed obs. - ! if requested, print in the form of a timestamp. - ! the default is just a plain string with the current obs count. - if(mod(obs_num, print_every_Nth) == 0) then - write(label, *) 'obs count = ', obs_num - if (print_timestamps) then - call timestamp(string1=label, pos='') - else - write(*,*) trim(label) - endif - endif - if(obs_num == max_num) then - print*, 'Max limit for observation count reached. Increase value in namelist' - stop - endif +! tidy up + +call nc_check(nf90_close(grid_id), & + 'get_horiz_grid_dims','close '//trim(ic_filename) ) + +end subroutine get_horiz_grid_dims + + + + subroutine get_vert_grid_dim(Nz) +!------------------------------------------------------------------ +! subroutine get_vert_grid_dim(Nz) +! +! count the number of lines in the ascii file to figure out max +! number of vert blocks. + +integer, intent(out) :: Nz + +integer :: linelen ! disposable + +if ( .not. module_initialized ) call initialize_module + +call find_textfile_dims(vert_grid_file, Nz, linelen) + +end subroutine get_vert_grid_dim + + -! create the obs_def for this observation, add to sequence -!------------------------------------------------------------------------------ - - call real_obs(num_copies, num_qc, obs, lon, lat, vloc, obs_value, & - var2, aqc, obstype, which_vert, seconds, days) - - if(obs_num == 1) then ! for the first observation +subroutine get_pop_calendar(calstring) +!------------------------------------------------------------------ +! the initialize_module ensures that the pop namelists are read and +! the DART time manager gets the pop calendar setting. +! +! Then, the DART time manager is queried to return what it knows ... +! +character(len=*), INTENT(OUT) :: calstring - call insert_obs_in_seq(real_obs_sequence, obs) - call copy_obs(prev_obs, obs) - pre_time = time +if ( .not. module_initialized ) call initialize_module - else ! not the first observation +call get_calendar_string(calstring) - if(time == pre_time) then ! same time as previous observation +end subroutine get_pop_calendar - call insert_obs_in_seq(real_obs_sequence, obs, prev_obs) - call copy_obs(prev_obs, obs) - pre_time = time - else ! not the same time - call insert_obs_in_seq(real_obs_sequence, obs) - call copy_obs(prev_obs, obs) - pre_time = time +function set_model_time_step() +!------------------------------------------------------------------ +! the initialize_module ensures that the pop namelists are read. +! The restart times in the pop_in&restart_nml are used to define +! appropriate assimilation timesteps. +! +type(time_type) :: set_model_time_step - endif +if ( .not. module_initialized ) call initialize_module - endif +! Check the 'restart_freq_opt' and 'restart_freq' to determine +! when we can stop the model -end do obsloop +if ( trim(restart_freq_opt) == 'nday' ) then + set_model_time_step = set_time(0, restart_freq) ! (seconds, days) +else + call error_handler(E_ERR,'set_model_time_step', & + 'restart_freq_opt must be days', source, revision, revdate) +endif -200 continue +end function set_model_time_step -close(obs_unit) -! Print a little summary -print*, 'obs used = ', obs_num, ' obs skipped = ', iskip -if ( get_first_obs(real_obs_sequence, obs) ) then - call get_obs_def(obs, obs_def) - pre_time = get_obs_def_time(obs_def) - call print_time(pre_time,' first time in sequence is ') - call print_date(pre_time,' first date in sequence is ') + +subroutine write_pop_namelist(model_time, adv_to_time) +!------------------------------------------------------------------ +! +type(time_type), INTENT(IN) :: model_time, adv_to_time +type(time_type) :: offset + +integer :: iunit, secs, days + +if ( .not. module_initialized ) call initialize_module + +offset = adv_to_time - model_time +call get_time(offset, secs, days) + +if (secs /= 0 ) then + write(msgstring,*)'adv_to_time has seconds == ',secs,' must be zero' + call error_handler(E_ERR,'write_pop_namelist', msgstring, source, revision, revdate) endif -if( get_last_obs(real_obs_sequence, obs)) then - call get_obs_def(obs, obs_def) - time = get_obs_def_time(obs_def) - call print_time(time,' last time in sequence is ') - call print_date(time,' last date in sequence is ') + +! call print_date( model_time,'write_pop_namelist:dart model date') +! call print_date(adv_to_time,'write_pop_namelist:advance_to date') +! call print_time( model_time,'write_pop_namelist:dart model time') +! call print_time(adv_to_time,'write_pop_namelist:advance_to time') +! call print_time( offset,'write_pop_namelist:a distance of') +! write( *,'(''write_pop_namelist:TIME_MANAGER_NML STOP_COUNT '',i10,'' days'')') days + +!Convey the information to the namelist 'stop option' and 'stop count' + +if ( trim(stop_option) == 'nday' ) then + stop_count = days +else + call error_handler(E_ERR,'write_pop_namelist', & + 'stop_option must be "nday"', source, revision, revdate) endif -print*, '' -end function real_obs_sequence +iunit = open_file('pop_in.DART',form='formatted',action='rewind') +write(iunit, nml=time_manager_nml) +write(iunit, '('' '')') +close(iunit) +end subroutine write_pop_namelist -subroutine real_obs(num_copies, num_qc, obs, lon, lat, vloc, obs_value, & - var2, aqc, obs_kind, which_vert, seconds, days) -!------------------------------------------------------------------------------ -integer, intent(in) :: num_copies, num_qc -type(obs_type), intent(inout) :: obs -real(r8), intent(in) :: lon, lat, vloc, obs_value, var2, aqc -integer, intent(in) :: obs_kind, which_vert, seconds, days -integer :: i -real(r8) :: aqc01(1), obs_value01(1) -type(obs_def_type) :: obsdef0 + subroutine read_horiz_grid(nx, ny, ULAT, ULON, TLAT, TLON) +!------------------------------------------------------------------ +! subroutine read_horiz_grid(nx, ny, ULAT, ULON, TLAT, TLON) +! +! Open and read the binary grid file +integer, intent(in) :: nx, ny +real(r8), dimension(nx,ny), intent(out) :: ULAT, ULON, TLAT, TLON + +!real(r8), dimension(nx,ny) :: & +! HTN , &! length (cm) of north edge of T box +! HTE , &! length (cm) of east edge of T box +! HUS , &! length (cm) of south edge of U box +! HUW , &! length (cm) of west edge of U box +! ANGLE ! angle + +integer :: grid_unit, reclength + if ( .not. module_initialized ) call initialize_module -! Does real initialization of an observation type +! Check to see that the file exists. -call real_obs_def(obsdef0, lon, lat, vloc, & - var2, obs_kind, which_vert, seconds, days) -call set_obs_def(obs, obsdef0) +if ( .not. file_exist(horiz_grid_file) ) then + msgstring = 'pop_in:horiz_grid_file '//trim(horiz_grid_file)//' not found' + call error_handler(E_ERR,'read_horiz_grid', & + msgstring, source, revision, revdate) +endif -do i = 1, num_copies - obs_value01(1) = obs_value - call set_obs_values(obs, obs_value01(1:1) ) +! Open it and read them in the EXPECTED order. +! Actually, we only need the first two, so I'm skipping the rest. + +grid_unit = get_unit() +INQUIRE(iolength=reclength) ULAT + +open(grid_unit, file=trim(horiz_grid_file), form='unformatted', & + access='direct', recl=reclength, status='old' ) +read(grid_unit, rec=1) ULAT +read(grid_unit, rec=2) ULON +!read(grid_unit, rec=3) HTN +!read(grid_unit, rec=4) HTE +!read(grid_unit, rec=5) HUS +!read(grid_unit, rec=6) HUW +!read(grid_unit, rec=7) ANGLE +close(grid_unit) + +call calc_tpoints(nx, ny, ULAT, ULON, TLAT, TLON) + +! convert from radians to degrees + +ULAT = ULAT * rad2deg +ULON = ULON * rad2deg +TLAT = TLAT * rad2deg +TLON = TLON * rad2deg + +! ensure [0,360) [-90,90] + +where (ULON < 0.0_r8) ULON = ULON + 360.0_r8 +where (ULON > 360.0_r8) ULON = ULON - 360.0_r8 +where (TLON < 0.0_r8) TLON = TLON + 360.0_r8 +where (TLON > 360.0_r8) TLON = TLON - 360.0_r8 + +where (ULAT < -90.0_r8) ULAT = -90.0_r8 +where (ULAT > 90.0_r8) ULAT = 90.0_r8 +where (TLAT < -90.0_r8) TLAT = -90.0_r8 +where (TLAT > 90.0_r8) TLAT = 90.0_r8 + +end subroutine read_horiz_grid + + + subroutine calc_tpoints(nx, ny, ULAT, ULON, TLAT, TLON) +!------------------------------------------------------------------ +! subroutine calc_tpoints(nx, ny, ULAT, ULON, TLAT, TLON) +! +! mimic POP grid.F90:calc_tpoints(), but for one big block. + +integer, intent( in) :: nx, ny +real(r8), dimension(nx,ny), intent( in) :: ULAT, ULON +real(r8), dimension(nx,ny), intent(out) :: TLAT, TLON + +integer :: i, j +real(r8) :: xc,yc,zc,xs,ys,zs,xw,yw,zw ! Cartesian coordinates for +real(r8) :: xsw,ysw,zsw,tx,ty,tz,da ! nbr points + +real(r8), parameter :: c0 = 0.000_r8, c1 = 1.000_r8 +real(r8), parameter :: c2 = 2.000_r8, c4 = 4.000_r8 +real(r8), parameter :: p25 = 0.250_r8, p5 = 0.500_r8 +real(r8) :: pi, pi2, pih, radian + +if ( .not. module_initialized ) call initialize_module + +! Define some constants as in pop + +pi = c4*atan(c1) +pi2 = c2*pi +pih = p5*pi +radian = 180.0_r8/pi + +do j=2,ny +do i=2,nx + + !*** convert neighbor U-cell coordinates to 3-d Cartesian coordinates + !*** to prevent problems with averaging near the pole + + zsw = cos(ULAT(i-1,j-1)) + xsw = cos(ULON(i-1,j-1))*zsw + ysw = sin(ULON(i-1,j-1))*zsw + zsw = sin(ULAT(i-1,j-1)) + + zs = cos(ULAT(i ,j-1)) + xs = cos(ULON(i ,j-1))*zs + ys = sin(ULON(i ,j-1))*zs + zs = sin(ULAT(i ,j-1)) + + zw = cos(ULAT(i-1,j )) + xw = cos(ULON(i-1,j ))*zw + yw = sin(ULON(i-1,j ))*zw + zw = sin(ULAT(i-1,j )) + + zc = cos(ULAT(i ,j )) + xc = cos(ULON(i ,j ))*zc + yc = sin(ULON(i ,j ))*zc + zc = sin(ULAT(i ,j )) + + !*** straight 4-point average to T-cell Cartesian coords + + tx = p25*(xc + xs + xw + xsw) + ty = p25*(yc + ys + yw + ysw) + tz = p25*(zc + zs + zw + zsw) + + !*** convert to lat/lon in radians + + da = sqrt(tx**2 + ty**2 + tz**2) + + TLAT(i,j) = asin(tz/da) + + if (tx /= c0 .or. ty /= c0) then + TLON(i,j) = atan2(ty,tx) + else + TLON(i,j) = c0 + endif + end do +end do -do i = 1, num_qc - aqc01(1) = aqc - call set_qc(obs, aqc01(1:1)) +!*** for bottom row of domain where sw 4pt average is not valid, +!*** extrapolate from interior +!*** NOTE: THIS ASSUMES A CLOSED SOUTH BOUNDARY - WILL NOT +!*** WORK CORRECTLY FOR CYCLIC OPTION + +do i=1,nx + TLON(i,1) = TLON(i,1+1) + TLAT(i,1) = c2*TLAT(i,1+1) - TLAT(i,1+2) end do -end subroutine real_obs +where (TLON(:,:) > pi2) TLON(:,:) = TLON(:,:) - pi2 +where (TLON(:,:) < c0 ) TLON(:,:) = TLON(:,:) + pi2 +!*** this leaves the leftmost/western edge to be filled +!*** if the longitudes wrap, this is easy. +!*** the gx3v5 grid TLON(:,2) and TLON(:,nx) are both about 2pi, +!*** so taking the average is reasonable. +!*** averaging the latitudes is always reasonable. +if ( trim(ew_boundary_type) == 'cyclic' ) then -subroutine real_obs_def(obs_def, lon, lat, vloc, & - var2, obs_kind, which_vert, seconds, days) -!---------------------------------------------------------------------- -type(obs_def_type), intent(inout) :: obs_def -real(r8),intent(in) :: lon, lat, vloc, var2 -integer, intent(in) :: obs_kind, which_vert, seconds, days + TLAT(1,:) = (TLAT(2,:) + TLAT(nx,:))/c2 + TLON(1,:) = (TLON(2,:) + TLON(nx,:))/c2 -type(location_type) :: loc0 +else + write(msgstring,'(''pop_in&domain_nml:ew_boundary_type '',a,'' unknown.'')') & + trim(ew_boundary_type) + call error_handler(E_ERR,'calc_tpoints',msgstring,source,revision,revdate) +endif +end subroutine calc_tpoints + + + + subroutine read_topography(nx, ny, KMT, KMU) +!------------------------------------------------------------------ +! subroutine read_topography(nx, ny, KMT, KMU) +! +! Open and read the binary topography file + +integer, intent(in) :: nx, ny +integer, dimension(nx,ny), intent(out) :: KMT, KMU + +integer :: i, j, topo_unit, reclength + if ( .not. module_initialized ) call initialize_module -! set obs location -loc0 = set_location(lon, lat, vloc, which_vert ) -call set_obs_def_location(obs_def, loc0) +! Check to see that the file exists. -! set obs kind -call set_obs_def_kind(obs_def, obs_kind) +if ( .not. file_exist(topography_file) ) then + msgstring = 'pop_in:topography_file '//trim(topography_file)//' not found' + call error_handler(E_ERR,'read_topography', & + msgstring, source, revision, revdate) +endif -call set_obs_def_time(obs_def, set_time(seconds, days) ) -call set_obs_def_error_variance(obs_def, var2) +! read the binary file -end subroutine real_obs_def +topo_unit = get_unit() +INQUIRE(iolength=reclength) KMT +open( topo_unit, file=trim(topography_file), form='unformatted', & + access='direct', recl=reclength, status='old' ) +read( topo_unit, rec=1) KMT +close(topo_unit) +KMU(1, 1) = 0 +do j=2,ny +do i=2,nx + KMU(i,j) = min(KMT(i, j), KMT(i-1, j), KMT(i, j-1), KMT(i-1, j-1)) +enddo +enddo -subroutine initialize_module -!------------------------------------------------- -call register_module(source, revision, revdate) -module_initialized = .true. -end subroutine initialize_module +end subroutine read_topography + + subroutine read_vert_grid(nz, ZC, ZG) +!------------------------------------------------------------------ +! subroutine read_vert_grid(nz, ZC, ZG) +! +! Open and read the ASCII vertical grid information +! +! The vert grid file is ascii, with 3 columns/line: +! cell thickness(in cm) cell center(in m) cell bottom(in m) + +integer, intent(in) :: nz +real(r8), intent(out) :: ZC(nz), ZG(nz) + +integer :: iunit, i, ios +real(r8) :: depth + +if ( .not. module_initialized ) call initialize_module + +! Check to see that the file exists. + +if ( .not. file_exist(vert_grid_file) ) then + msgstring = 'pop_in:vert_grid_file '//trim(vert_grid_file)//' not found' + call error_handler(E_ERR,'read_vert_grid', & + msgstring, source, revision, revdate) +endif + +! read the ASCII file + +iunit = open_file(trim(vert_grid_file), action = 'read') + +do i=1, nz + + read(iunit,*,iostat=ios) depth, ZC(i), ZG(i) + + if ( ios /= 0 ) then ! error + write(msgstring,*)'error reading depths, line ',i + call error_handler(E_ERR,'read_vert_grid',msgstring,source,revision,revdate) + endif + +enddo + +end subroutine read_vert_grid + + + end module dart_pop_mod Modified: DART/trunk/models/POP/dart_to_pop.f90 =================================================================== --- DART/trunk/models/POP/dart_to_pop.f90 2009-08-27 20:19:52 UTC (rev 4019) +++ DART/trunk/models/POP/dart_to_pop.f90 2009-08-27 23:19:20 UTC (rev 4020) @@ -27,12 +27,13 @@ initialize_utilities, finalize_utilities, & find_namelist_in_file, check_namelist_read, & logfileunit +use assim_model_mod, only : open_restart_read, aread_state_restart, close_restart +use time_manager_mod, only : time_type, get_time, print_time, print_date, & + operator(-), set_time use model_mod, only : static_init_model, sv_to_restart_file, & get_model_size, get_model_time_step, & set_model_end_time -use assim_model_mod, only : open_restart_read, aread_state_restart, close_restart -use time_manager_mod, only : time_type, get_time, print_time, print_date, & - operator(-) +use dart_pop_mod, only : write_pop_namelist implicit none @@ -48,15 +49,16 @@ character (len = 128) :: dart_to_pop_input_file = 'assim_model_state_ic' character (len = 128) :: dart_to_pop_restart_file = 'my_pop_restart_file' +logical :: advance_time_present = .TRUE. -namelist /dart_to_pop_nml/ dart_to_pop_input_file, dart_to_pop_restart_file +namelist /dart_to_pop_nml/ dart_to_pop_input_file, dart_to_pop_restart_file, & + advance_time_present !---------------------------------------------------------------------- integer :: iunit, io, x_size integer :: secs, days type(time_type) :: model_time, adv_to_time -type(time_type) :: model_timestep, offset real(r8), allocatable :: statevector(:) !---------------------------------------------------------------------- @@ -82,52 +84,41 @@ !---------------------------------------------------------------------- iunit = open_restart_read(dart_to_pop_input_file) -call aread_state_restart(model_time, statevector, iunit, adv_to_time) + +if ( advance_time_present ) then + call aread_state_restart(model_time, statevector, iunit, adv_to_time) +else + call aread_state_restart(model_time, statevector, iunit) +endif call close_restart(iunit) !---------------------------------------------------------------------- ! update the current POP state vector -!---------------------------------------------------------------------- - -call sv_to_restart_file(statevector, dart_to_pop_restart_file, & - model_time, adv_to_time) - -!iunit = open_file('data.cal.DART',form='formatted',action='rewind') -!write(iunit, nml=CAL_NML) -!close(iunit) - -!---------------------------------------------------------------------- -! convert the adv_to_time to the appropriate number of POP +! Convey the amount of time to integrate the model ... ! time_manager_nml: stop_option, stop_count increments !---------------------------------------------------------------------- -model_timestep = get_model_time_step() -offset = adv_to_time - model_time +call sv_to_restart_file(statevector, dart_to_pop_restart_file, model_time) -!call set_model_end_time(offset) -!call write_data_namelistfile() +if ( advance_time_present ) then + call write_pop_namelist(model_time, adv_to_time) +endif !---------------------------------------------------------------------- ! Log what we think we're doing, and exit. !---------------------------------------------------------------------- -call get_time(offset, secs, days) - call print_date( model_time,'dart_to_pop:dart model date') -call print_date(adv_to_time,'dart_to_pop:advance_to date') call print_time( model_time,'dart_to_pop:dart model time') -call print_time(adv_to_time,'dart_to_pop:advance_to time') -call print_time( offset,'dart_to_pop:a distance of') -write( * ,'(''dart_to_pop:PARM03 endTime '',i,'' seconds'')') & - (secs + days*SECPERDAY) - call print_date( model_time,'dart_to_pop:dart model date',logfileunit) -call print_date(adv_to_time,'dart_to_pop:advance_to date',logfileunit) call print_time( model_time,'dart_to_pop:dart model time',logfileunit) + +if ( advance_time_present ) then +call print_time(adv_to_time,'dart_to_pop:advance_to time') +call print_date(adv_to_time,'dart_to_pop:advance_to date') call print_time(adv_to_time,'dart_to_pop:advance_to time',logfileunit) -call print_time( offset,'dart_to_pop: a distance of',logfileunit) -write(logfileunit,'(''dart_to_pop:PARM03 endTime '',i,'' seconds'')') & - (secs + days*SECPERDAY) +call print_date(adv_to_time,'dart_to_pop:advance_to date',logfileunit) +endif call finalize_utilities() Modified: DART/trunk/models/POP/matlab/Check_pop_to_dart.m =================================================================== --- DART/trunk/models/POP/matlab/Check_pop_to_dart.m 2009-08-27 20:19:52 UTC (rev 4019) +++ DART/trunk/models/POP/matlab/Check_pop_to_dart.m 2009-08-27 23:19:20 UTC (rev 4020) @@ -1,166 +1,160 @@ -% Check_pop_to_dart +function [dart pop] = Check_pop_to_dart(popfile,dartfile) +% Check_pop_to_dart : check pop_to_dart.f90 ... the conversion of a POP restart to a DART state vector file. % -% data.cal holds the starting time information +% popfile = 'pop.r.nc'; +% dartfile = 'dart.ics'; +% x = Check_pop_to_dart(popfile, dartfile); % +% popfile = '~DART/models/POP/work/cx3.dart.001.pop.r.0002-01-01-00000.nc'; +% dartfile = '~DART/models/POP/work/perfect_ics'; +% [dart pop] = Check_pop_to_dart(popfile, dartfile); -popdir = '/ptmp/thoar/POP/job_40705'; -popfile = 'pop.r.x1A.00000102'; -dartfile = 'assim_model_state_ud'; +% Data Assimilation Research Testbed -- DART +% Copyright 2004-2007, Data Assimilation Research Section +% University Corporation for Atmospheric Research +% Licensed under the GPL -- www.gpl.org/licenses/gpl.html +% +% +% $URL$ +% $Id$ +% $Revision$ +% $Date$ -fname = sprintf('%s/%s',popdir,popfile); +% Read the original POP file values. +if (exist(popfile,'file') ~= 2) + error('POP file %s does not exist.',popfile) +end +if (exist(dartfile,'file') ~= 2) + error('DART file %s does not exist.',dartfile) +end -S = nc_varget(fname, 'SALT_CUR'); -T = nc_varget(fname, 'TEMP_CUR'); -U = nc_varget(fname, 'UVEL_CUR'); -V = nc_varget(fname, 'VVEL_CUR'); -SSH = nc_varget(fname,'PSURF_CUR'); +iyear = nc_attget(popfile,nc_global,'iyear'); +imonth = nc_attget(popfile,nc_global,'imonth'); +iday = nc_attget(popfile,nc_global,'iday'); +ihour = nc_attget(popfile,nc_global,'ihour'); +iminute = nc_attget(popfile,nc_global,'iminute'); +isecond = nc_attget(popfile,nc_global,'isecond'); -modelsize = prod(size(S)) + prod(size(T)) + ... - prod(size(U)) + prod(size(V)) + prod(size(SSH)); +fprintf('POP year month day hour minute second %d %d %d %d %d %d\n', ... + iyear,imonth,iday,ihour,iminute,isecond); -[nx ny nz] = size(S); +% The nc_varget() function returns the variables with the fastest +% varying dimension on the right. This is opposite to the Fortran +% convention of the fastest varying dimension on the left ... so +% one of the variables must be permuted in order to be compared. -iyear = nc_attget(fname,nc_global,'iyear'); -imonth = nc_attget(fname,nc_global,'imonth'); -iday = nc_attget(fname,nc_global,'iday'); -ihour = nc_attget(fname,nc_global,'ihour'); -iminute = nc_attget(fname,nc_global,'iminute'); -isecond = nc_attget(fname,nc_global,'isecond'); +S = nc_varget(popfile, 'SALT_CUR'); pop.S = permute(S, [3 2 1]); +T = nc_varget(popfile, 'TEMP_CUR'); pop.T = permute(T, [3 2 1]); +U = nc_varget(popfile, 'UVEL_CUR'); pop.U = permute(U, [3 2 1]); +V = nc_varget(popfile, 'VVEL_CUR'); pop.V = permute(V, [3 2 1]); +PSURF = nc_varget(popfile, 'PSURF_CUR'); pop.PSURF = permute(PSURF, [2 1]); -fprintf('year month day hour minute second %d %d %d %d %d %d\n', ... - iyear,imonth,iday,ihour,iminute,isecond); +disp(sprintf('pop.PSURF min/max are %0.8g %0.8g',min(pop.PSURF(:)),max(pop.PSURF(:)))) -% Get the dart equivalent +[nx ny nz] = size(pop.U); +fprintf('vert dimension size is %d\n',nz) +fprintf('N-S dimension size is %d\n',ny) +fprintf('E-W dimension size is %d\n',nx) -fname = sprintf('%s/%s',popdir,dartfile); -fid = fopen(fname,'rb','ieee-le'); +modelsize = nx*ny*nz; + +% filesize = S,T,U,V * (nx*ny*nz) + SSH * (nx*ny) +storage = 8; +size2d = nx*ny; +size3d = nx*ny*nz; +n2ditems = 1*size2d; +n3ditems = 4*size3d; +rec1size = 4+(4+4)+4; % time stamps ... +rec2size = 4+(n3ditems*storage + n2ditems*storage)+4; + +fsize = rec1size + rec2size; +disp(sprintf('with a modelsize of %d the file size should be %d bytes', ... + modelsize,fsize)) + +% Open and read timetag for state +fid = fopen(dartfile,'rb','ieee-le'); trec1 = fread(fid,1,'int32'); seconds = fread(fid,1,'int32'); days = fread(fid,1,'int32'); trecN = fread(fid,1,'int32'); @@ Diff output truncated at 40000 characters. @@ From nancy at ucar.edu Fri Aug 28 09:10:45 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Fri, 28 Aug 2009 09:10:45 -0600 (MDT) Subject: [Dart-dev] [4021] DART/trunk/observations/AIRS/work/path_names_advance_time: Fix the name of the utilities_mod file. Message-ID: <200908281510.n7SFAjvM007632@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090828/5d2d8fa6/attachment.html -------------- next part -------------- Modified: DART/trunk/observations/AIRS/work/path_names_advance_time =================================================================== --- DART/trunk/observations/AIRS/work/path_names_advance_time 2009-08-27 23:19:20 UTC (rev 4020) +++ DART/trunk/observations/AIRS/work/path_names_advance_time 2009-08-28 15:10:45 UTC (rev 4021) @@ -1,6 +1,6 @@ time_manager/advance_time.f90 time_manager/time_manager_mod.f90 common/types_mod.f90 -utilities/utilities_lite_mod.f90 +utilities/utilities_mod.f90 utilities/parse_args_mod.f90 mpi_utilities/null_mpi_utilities_mod.f90 From nancy at ucar.edu Fri Aug 28 09:49:03 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Fri, 28 Aug 2009 09:49:03 -0600 (MDT) Subject: [Dart-dev] [4022] DART/trunk/utilities/utilities_mod.f90: Make it so the nml file is really not opened or written to at all Message-ID: <200908281549.n7SFn3mH021122@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090828/501f366c/attachment.html -------------- next part -------------- Modified: DART/trunk/utilities/utilities_mod.f90 =================================================================== --- DART/trunk/utilities/utilities_mod.f90 2009-08-28 15:10:45 UTC (rev 4021) +++ DART/trunk/utilities/utilities_mod.f90 2009-08-28 15:49:03 UTC (rev 4022) @@ -289,30 +289,32 @@ ! If nmlfilename != logfilename, open it. otherwise set nmlfileunit ! to be same as logunit. - if (trim(adjustl(nmlfilename)) /= trim(adjustl(lname))) then - if (do_output_flag) & - write(*,*)'Trying to open namelist log ', trim(adjustl(nmlfilename)) - - nmlfileunit = nextunit() - if (nmlfileunit < 0) & - call error_handler(E_ERR,'initialize_utilities', & - 'Cannot get unit for nm log file', source, revision, revdate) - - open(nmlfileunit, file=trim(adjustl(nmlfilename)), form='formatted', & - position='append', iostat = io ) - if ( io /= 0 ) then - call error_handler(E_ERR,'initialize_utilities', & - 'Cannot open nm log file', source, revision, revdate) + if (do_nml_file()) then + if (trim(adjustl(nmlfilename)) /= trim(adjustl(lname))) then + if (do_output_flag) & + write(*,*)'Trying to open namelist log ', trim(adjustl(nmlfilename)) + + nmlfileunit = nextunit() + if (nmlfileunit < 0) & + call error_handler(E_ERR,'initialize_utilities', & + 'Cannot get unit for nm log file', source, revision, revdate) + + open(nmlfileunit, file=trim(adjustl(nmlfilename)), form='formatted', & + position='append', iostat = io ) + if ( io /= 0 ) then + call error_handler(E_ERR,'initialize_utilities', & + 'Cannot open nm log file', source, revision, revdate) + endif + + else + nmlfileunit = logfileunit endif - - else - nmlfileunit = logfileunit endif ! Echo the namelist values for this module using normal mechanism ! including a separator line for this run. if (do_output_flag) then - if (nmlfileunit /= logfileunit) then + if (do_nml_file() .and. (nmlfileunit /= logfileunit)) then if ( present(progname) ) then write(nmlfileunit, *) '!Starting Program '//trim(progname) else @@ -374,7 +376,7 @@ ! integer :: logfileunit -- private module variable if (do_output_flag) then - if (nmlfileunit /= logfileunit) then + if (do_nml_file() .and. (nmlfileunit /= logfileunit)) then write(nmlfileunit, *) '!Ending Program ' endif endif From nancy at ucar.edu Fri Aug 28 16:44:56 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Fri, 28 Aug 2009 16:44:56 -0600 (MDT) Subject: [Dart-dev] [4023] DART/trunk/DART_LAB/matlab/advance_oned.m: Added a model bias capability. Message-ID: <200908282244.n7SMiug3008668@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090828/5e0dbd22/attachment.html -------------- next part -------------- Modified: DART/trunk/DART_LAB/matlab/advance_oned.m =================================================================== --- DART/trunk/DART_LAB/matlab/advance_oned.m 2009-08-28 15:49:03 UTC (rev 4022) +++ DART/trunk/DART_LAB/matlab/advance_oned.m 2009-08-28 22:44:56 UTC (rev 4023) @@ -1,4 +1,4 @@ -function x_new = advance_oned(x, alpha) +function x_new = advance_oned(x, alpha, model_bias) % Data Assimilation Research Testbed -- DART % Copyright 2004-2009, Data Assimilation Research Section @@ -11,15 +11,16 @@ % $Revision$ % $Date$ -x_new = x + comp_dt(x, alpha); +x_new = x + comp_dt(x, alpha, model_bias); end %--------------------------------------------------- % Internal function comp_dt -function dx = comp_dt(x, alpha) +function dx = comp_dt(x, alpha, model_bias) % Compute the time tendency; alpha controls nonlinearity -dx = x + alpha .* x .* abs(x); +% model_bias controls a shift in the model dynamics +dx = (x + model_bias) + alpha .* x .* abs(x); end From nancy at ucar.edu Fri Aug 28 16:46:16 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Fri, 28 Aug 2009 16:46:16 -0600 (MDT) Subject: [Dart-dev] [4024] DART/trunk/DART_LAB/matlab: Enhanced capabilities and gui clean-up. Message-ID: <200908282246.n7SMkGNr009941@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090828/1283fa98/attachment-0001.html -------------- next part -------------- Modified: DART/trunk/DART_LAB/matlab/gaussian_product.fig =================================================================== (Binary files differ) Modified: DART/trunk/DART_LAB/matlab/oned_ensemble.fig =================================================================== (Binary files differ) Modified: DART/trunk/DART_LAB/matlab/oned_ensemble.m =================================================================== --- DART/trunk/DART_LAB/matlab/oned_ensemble.m 2009-08-28 22:44:56 UTC (rev 4023) +++ DART/trunk/DART_LAB/matlab/oned_ensemble.m 2009-08-28 22:46:16 UTC (rev 4024) @@ -29,7 +29,7 @@ % $Revision$ % $Date$ -% Last Modified by GUIDE v2.5 25-Mar-2009 14:34:04 +% Last Modified by GUIDE v2.5 28-Aug-2009 16:29:57 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -65,34 +65,43 @@ handles.output = hObject; % Insert the ensemble structure into this -handles.ens_size = 0; -handles.ens_members = 0; -handles.h_obs_plot = 0; -handles.h_update_ens = 0; -handles.h_ens_member = 0; -handles.h_obs_ast = 0; +handles.ens_size = 0; +handles.ens_members = 0; +handles.h_obs_plot = 0; +handles.h_update_ens = 0; +handles.h_ens_member = 0; +handles.h_obs_ast = 0; +handles.h_update_lines = 0; +handles.observation = 0; +handles.obs_error_sd = 0; +handles.inflation = 1.5; +handles.plot_inflation = false; +handles.h_inf_ens_member = 0; +handles.h_inf_up_ens = 0; +handles.h_inf_lines = 0; +handles.h_inf_axis = 0; % Update handles structure guidata(hObject, handles); +% Get the initial observation, obs_error_sd and inflation from the gui +handles.observation = str2double(get(handles.edit_observation, 'String')); +handles.obs_error_sd = str2double(get(handles.edit_obs_error_sd, 'String')); +handles.inflation = str2double(get(handles.edit_inflation, 'String')); + % Go ahead and plot the initial observational error distribution -h_observation = get(handles.edit1); -h_obs_error_sd = get(handles.edit2); -observation = str2double(h_observation.String); -obs_error_sd = str2double(h_obs_error_sd.String); -handles.h_obs_plot = plot_gaussian(observation, obs_error_sd, 1); +handles.h_obs_plot = plot_gaussian(handles.observation, handles.obs_error_sd, 1); set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); hold on % Plot an asterisk -handles.h_obs_ast = plot(observation, 0, 'r*', 'MarkerSize', 16); +handles.h_obs_ast = plot(handles.observation, 0, 'r*', 'MarkerSize', 16); % Set a basic plotting domain range that includes mean +/- 3 obs SDs -lower = observation - 3*obs_error_sd; -upper = observation + 3*obs_error_sd; -axis([lower upper -0.2 1]); +lower = handles.observation - 3*handles.obs_error_sd; +upper = handles.observation + 3*handles.obs_error_sd; +axis([lower upper -0.4 1]); - set(gca, 'YTick', [0 0.2 0.4 0.6 0.8]); set(gca, 'YTickLabel', [0 0.2 0.4 0.6 0.8]); @@ -102,7 +111,6 @@ % Update handles structure guidata(hObject, handles); - % UIWAIT makes oned_ensemble wait for user response (see UIRESUME) % uiwait(handles.figure1); @@ -124,49 +132,51 @@ %---------------------------------------------------------------------- -% --- Executes on button press in pushbutton1. -function pushbutton1_Callback(hObject, eventdata, handles) -% hObject handle to pushbutton1 (see GCBO) +% --- Executes on button press in pushbutton_create_new. +function pushbutton_create_new_Callback(hObject, eventdata, handles) +% hObject handle to pushbutton_create_new (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Disable the update ensemble button and all other active buttons -set(handles.pushbutton1, 'Enable', 'Off'); -set(handles.pushbutton2, 'Enable', 'Off'); -set(handles.edit1, 'Enable', 'Off'); -set(handles.edit2, 'Enable', 'Off'); +set(handles.pushbutton_update_ens, 'Enable', 'Off'); +set(handles.edit_observation, 'Enable', 'Off'); +set(handles.edit_obs_error_sd, 'Enable', 'Off'); +set(handles.edit_inflation, 'Enable', 'Off'); % Clear out any old ensemble members if they exist -for i = 1:handles.ens_size - set(handles.h_ens_member(i), 'Visible', 'off'); -end +set(handles.h_ens_member, 'Visible', 'off'); +set(handles.h_inf_ens_member, 'Visible', 'off'); -% Remove mean and sd of old ensemble -set(handles.text2, 'String', 'Prior Mean = '); -set(handles.text3, 'String', 'Prior SD = '); +set(handles.h_update_lines, 'Visible', 'off'); +set(handles.h_inf_lines, 'Visible', 'off'); +set(handles.h_inf_axis, 'Visible', 'off'); +% Turn off any old update points +set(handles.h_update_ens, 'Visible', 'off'); +set(handles.h_inf_up_ens, 'Visible', 'off'); +set(handles.h_inf_ens_member, 'Visible', 'off'); + +clear_labels(handles); + hold on + % Set a basic plotting domain range that includes mean +/- 3 obs SDs -h_observation = get(handles.edit1); -h_obs_error_sd = get(handles.edit2); -observation = str2double(h_observation.String); -obs_error_sd = str2double(h_obs_error_sd.String); -lower = observation - 3*obs_error_sd; -upper = observation + 3*obs_error_sd; -axis([lower upper -0.2 1]); +lower = min(handles.observation - 3*handles.obs_error_sd, min(handles.ens_members)); +upper = max(handles.observation + 3*handles.obs_error_sd, max(handles.ens_members)); +axis([lower upper -0.4 1]); set(gca, 'YTick', [0 0.2 0.4 0.6 0.8]); set(gca, 'YTickLabel', [0 0.2 0.4 0.6 0.8]); - % Messages should start 1/10 of the way across the screen x_message = lower + 0.1 * (upper - lower); -h_click = text(x_message, 0.7, 'Click on x-axis to create member', 'FontSize', 16); +h_click = text(x_message, 0.4, 'Click on x-axis to create member', 'FontSize', 16); % Need to guarantee at least 2 ensemble members ens_size = 0; -h_err_text = text(x_message, 0.9, 'Click inside graphics box to select member', ... +h_err_text = text(x_message, 0.5, 'Click inside graphics box to select member', ... 'Color', 'r', 'FontSize', 16, 'Visible', 'off'); while ens_size < 2 @@ -189,14 +199,12 @@ prior_sd = std(x); set(handles.text2, 'String', ['Prior Mean = ', num2str(prior_mean)]); set(handles.text3, 'String', ['Prior SD = ', num2str(prior_sd)]); - end end +h_finish = text(x_message, 0.3, 'Click outside of plot to finish', 'Fontsize', 16); -h_finish = text(x_message, 0.5, 'Click outside of plot to finish', 'Fontsize', 16); - -while ens_size < 1000 +while ens_size < 100 [xt, zt] = ginput(1); % Terminate by clicking outside of graph range if(xt > upper | xt < lower) @@ -213,9 +221,7 @@ prior_sd = std(x); set(handles.text2, 'String', ['Prior Mean = ', num2str(prior_mean)]); set(handles.text3, 'String', ['Prior SD = ', num2str(prior_sd)]); - end - end % Ensemble created, comupte mean and sd, clean up and return @@ -226,73 +232,82 @@ % Update handles structure guidata(hObject, handles); - % Turn off the data entry messages set(h_click, 'Visible', 'off'); set(h_finish, 'Visible', 'off'); % Enable the update ensemble button -set(handles.pushbutton1, 'Enable', 'On'); -set(handles.pushbutton2, 'Enable', 'On'); -set(handles.edit1, 'Enable', 'On'); -set(handles.edit2, 'Enable', 'On'); +set(handles.pushbutton_update_ens, 'Enable', 'On'); +set(handles.edit_observation, 'Enable', 'On'); +set(handles.edit_obs_error_sd, 'Enable', 'On'); +set(handles.edit_inflation, 'Enable', 'On'); %---------------------------------------------------------------------- -function edit1_Callback(hObject, eventdata, handles) -% hObject handle to edit1 (see GCBO) +function edit_observation_Callback(hObject, eventdata, handles) +% hObject handle to edit_observation (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) -% Hints: get(hObject,'String') returns contents of edit1 as text -% str2double(get(hObject,'String')) returns contents of edit1 as a double +% Hints: get(hObject,'String') returns contents of edit_observation as text +% str2double(get(hObject,'String')) returns contents of edit_observation as a double +% Turn off any old updated points +set(handles.h_update_ens, 'Visible', 'off'); +set(handles.h_inf_up_ens, 'Visible', 'off'); +set(handles.h_inf_ens_member, 'Visible', 'off'); + +% Remove mean and sd of old posterior +clear_labels(handles); + +% And the lines in between +set(handles.h_update_lines, 'Visible', 'off'); +set(handles.h_inf_lines, 'Visible', 'off'); +set(handles.h_inf_axis, 'Visible', 'off'); + % Enable things that an error might have turned off -set(handles.edit2, 'Enable', 'on') -set(handles.pushbutton1, 'Enable', 'on') +set(handles.edit_obs_error_sd, 'Enable', 'on') +set(handles.edit_inflation, 'Enable', 'on') +set(handles.pushbutton_create_new, 'Enable', 'on') % Only enable the update ensemble pushbutton if an ensemble has been created if(handles.ens_size > 0) - set(handles.pushbutton2, 'Enable', 'on'); + set(handles.pushbutton_update_ens, 'Enable', 'on'); end % Get the value of the observation if(isfinite(str2double(get(hObject, 'String')))) observation = str2double(get(hObject, 'String')); else - set(handles.edit1, 'String', '???'); + set(handles.edit_observation, 'String', '???'); % Disable other input to guarantee only one error at a time! - set(handles.edit2, 'Enable', 'off') - set(handles.pushbutton1, 'Enable', 'off') - set(handles.pushbutton2, 'Enable', 'off') + set(handles.edit_obs_error_sd, 'Enable', 'off') + set(handles.edit_inflation, 'Enable', 'off') + set(handles.pushbutton_create_new, 'Enable', 'off') + set(handles.pushbutton_update_ens, 'Enable', 'off') return end -% Get the value of the observation error sd -h_obs_error_sd = get(handles.edit2); -obs_error_sd = str2double(h_obs_error_sd.String); +% Update the global storage +handles.observation = observation; % Plot the updated distribution set(handles.h_obs_plot, 'Visible', 'Off'); -handles.h_obs_plot = plot_gaussian(observation, obs_error_sd, 1); +handles.h_obs_plot = plot_gaussian(handles.observation, handles.obs_error_sd, 1); set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); % Move the observation asterisk set(handles.h_obs_ast, 'Visible', 'Off'); -handles.h_obs_ast = plot(observation, 0, 'r*', 'MarkerSize', 16); +handles.h_obs_ast = plot(handles.observation, 0, 'r*', 'MarkerSize', 16); % Set a basic plotting domain range that includes mean +/- 3 obs SDs -h_observation = get(handles.edit1); -h_obs_error_sd = get(handles.edit2); -observation = str2double(h_observation.String); -obs_error_sd = str2double(h_obs_error_sd.String); -lower = observation - 3*obs_error_sd; -upper = observation + 3*obs_error_sd; -axis([lower upper -0.2 1]); +lower = min(handles.observation - 3*handles.obs_error_sd, min(handles.ens_members)); +upper = max(handles.observation + 3*handles.obs_error_sd, max(handles.ens_members)); +axis([lower upper -0.4 1]); set(gca, 'YTick', [0 0.2 0.4 0.6 0.8]); set(gca, 'YTickLabel', [0 0.2 0.4 0.6 0.8]); @@ -308,8 +323,8 @@ % --- Executes during object creation, after setting all properties. -function edit1_CreateFcn(hObject, eventdata, handles) -% hObject handle to edit1 (see GCBO) +function edit_observation_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit_observation (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called @@ -323,21 +338,35 @@ %---------------------------------------------------------------------- -function edit2_Callback(hObject, eventdata, handles) -% hObject handle to edit2 (see GCBO) +function edit_obs_error_sd_Callback(hObject, eventdata, handles) +% hObject handle to edit_obs_error_sd (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) -% Hints: get(hObject,'String') returns contents of edit2 as text -% str2double(get(hObject,'String')) returns contents of edit2 as a double +% Hints: get(hObject,'String') returns contents of edit_obs_error_sd as text +% str2double(get(hObject,'String')) returns contents of edit_obs_error_sd as a double +% Turn off any old updated points +set(handles.h_update_ens, 'Visible', 'off'); +set(handles.h_inf_up_ens, 'Visible', 'off'); +set(handles.h_inf_ens_member, 'Visible', 'off'); + +% Remove mean and sd of old posterior +clear_labels(handles); + +% And the lines in between +set(handles.h_update_lines, 'Visible', 'off'); +set(handles.h_inf_lines, 'Visible', 'off'); +set(handles.h_inf_axis, 'Visible', 'off'); + % Enable things that an error might have turned off -set(handles.edit1, 'Enable', 'on') -set(handles.pushbutton1, 'Enable', 'on') +set(handles.edit_observation, 'Enable', 'on') +set(handles.edit_inflation, 'Enable', 'on') +set(handles.pushbutton_create_new, 'Enable', 'on') % Only enable the update ensemble pushbutton if an ensemble has been created if(handles.ens_size > 0) - set(handles.pushbutton2, 'Enable', 'on'); + set(handles.pushbutton_update_ens, 'Enable', 'on'); end % Get the value of the observation @@ -345,32 +374,28 @@ str2double(get(hObject, 'String')) > 0) obs_error_sd = str2double(get(hObject, 'String')); else - set(handles.edit2, 'String', '???'); + set(handles.edit_obs_error_sd, 'String', '???'); % Disable other input to guarantee only one error at a time! - set(handles.edit1, 'Enable', 'off') - set(handles.pushbutton1, 'Enable', 'off') - set(handles.pushbutton2, 'Enable', 'off') + set(handles.edit_observation, 'Enable', 'off') + set(handles.edit_inflation, 'Enable', 'off') + set(handles.pushbutton_create_new, 'Enable', 'off') + set(handles.pushbutton_update_ens, 'Enable', 'off') return end -% Get the value of the observation -h_observation = get(handles.edit1); -observation = str2double(h_observation.String); +% Update the value in global storage +handles.obs_error_sd = obs_error_sd; % Plot the updated distribution set(handles.h_obs_plot, 'Visible', 'off'); -handles.h_obs_plot = plot_gaussian(observation, obs_error_sd, 1); +handles.h_obs_plot = plot_gaussian(handles.observation, handles.obs_error_sd, 1); set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); % Set a basic plotting domain range that includes mean +/- 3 obs SDs -h_observation = get(handles.edit1); -h_obs_error_sd = get(handles.edit2); -observation = str2double(h_observation.String); -obs_error_sd = str2double(h_obs_error_sd.String); -lower = observation - 3*obs_error_sd; -upper = observation + 3*obs_error_sd; -axis([lower upper -0.2 1]); +lower = min(handles.observation - 3*handles.obs_error_sd, min(handles.ens_members)); +upper = max(handles.observation + 3*handles.obs_error_sd, max(handles.ens_members)); +axis([lower upper -0.4 1]); set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); @@ -388,8 +413,8 @@ % --- Executes during object creation, after setting all properties. -function edit2_CreateFcn(hObject, eventdata, handles) -% hObject handle to edit2 (see GCBO) +function edit_obs_error_sd_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit_obs_error_sd (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called @@ -403,22 +428,22 @@ %---------------------------------------------------------------------- -% --- Executes on selection change in popupmenu1. -function popupmenu1_Callback(hObject, eventdata, handles) -% hObject handle to popupmenu1 (see GCBO) +% --- Executes on selection change in popupmenu_filter_kind. +function popupmenu_filter_kind_Callback(hObject, eventdata, handles) +% hObject handle to popupmenu_filter_kind (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) -% Hints: contents = get(hObject,'String') returns popupmenu1 contents as cell array -% contents{get(hObject,'Value')} returns selected item from popupmenu1 +% Hints: contents = get(hObject,'String') returns popupmenu_filter_kind contents as cell array +% contents{get(hObject,'Value')} returns selected item from popupmenu_filter_kind %---------------------------------------------------------------------- % --- Executes during object creation, after setting all properties. -function popupmenu1_CreateFcn(hObject, eventdata, handles) -% hObject handle to popupmenu1 (see GCBO) +function popupmenu_filter_kind_CreateFcn(hObject, eventdata, handles) +% hObject handle to popupmenu_filter_kind (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called @@ -432,37 +457,42 @@ %---------------------------------------------------------------------- -% --- Executes on button press in pushbutton2. -function pushbutton2_Callback(hObject, eventdata, handles) -% hObject handle to pushbutton2 (see GCBO) +% --- Executes on button press in pushbutton_update_ens. +function pushbutton_update_ens_Callback(hObject, eventdata, handles) +% hObject handle to pushbutton_update_ens (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Turn off any old points set(handles.h_update_ens, 'Visible', 'off'); +set(handles.h_inf_up_ens, 'Visible', 'off'); +set(handles.h_inf_ens_member, 'Visible', 'off'); +% Remove mean and sd of old posterior +clear_labels(handles); + +% And the lines in between +set(handles.h_update_lines, 'Visible', 'off'); +set(handles.h_inf_lines, 'Visible', 'off'); +set(handles.h_inf_axis, 'Visible', 'off'); + ensemble = handles.ens_members; -h_observation = get(handles.edit1); -h_obs_error_sd = get(handles.edit2); -observation = str2double(h_observation.String); -obs_error_sd = str2double(h_obs_error_sd.String); - % Figure out which filter option is currently selected -h_filter_kind = get(handles.popupmenu1); +h_filter_kind = get(handles.popupmenu_filter_kind); filter_type = char(h_filter_kind.String(h_filter_kind.Value)); switch filter_type case 'EAKF' [obs_increments, err] = ... - obs_increment_eakf(ensemble, observation, obs_error_sd^2); + obs_increment_eakf(ensemble, handles.observation, handles.obs_error_sd^2); case 'EnKF' [obs_increments, err] = ... - obs_increment_enkf(ensemble, observation, obs_error_sd^2); + obs_increment_enkf(ensemble, handles.observation, handles.obs_error_sd^2); case 'RHF' [obs_increments, err] = ... - obs_increment_rhf(ensemble, observation, obs_error_sd^2); + obs_increment_rhf(ensemble, handles.observation, handles.obs_error_sd^2); end % Add on increments to get new ensemble @@ -470,4 +500,209 @@ y(1:size(ensemble)) = -0.1; handles.h_update_ens = plot(new_ensemble, y, '*', 'MarkerSize', 16, 'Color', 'Blue'); + +% Plot lines connecting the prior and posterior ensemble members +for i = 1:size(ensemble, 2) + x_line = [handles.ens_members(i), new_ensemble(i)]; + y_line = [0, -0.1]; + handles.h_update_lines(i) = plot(x_line, y_line, 'k'); +end + +% Add in a label of the updated mean and sd +new_mean = mean(new_ensemble); +new_sd = std(new_ensemble); + +% Update mean and sd of old posterior +set(handles.text8, 'String', ['Prior Mean = ', num2str(new_mean)]); +set(handles.text8, 'Visible', 'on'); +set(handles.text7, 'String', ['Prior SD = ', num2str(new_sd)]); +set(handles.text7, 'Visible', 'on'); + +% If the checkbox isn't set, return now +if(not(get(handles.checkbox_inflation, 'Value'))) + guidata(hObject, handles) + return +end + +% Plot the inflated prior ensemble +y = -0.2; +prior_mean = mean(handles.ens_members(1:handles.ens_size)); + +for i = 1: handles.ens_size + inf_ens(i) = (handles.ens_members(i) - prior_mean) * sqrt(handles.inflation) + ... + prior_mean; + handles.h_inf_ens_member(i) = plot(inf_ens(i), y, '*', 'MarkerSize', 16, 'Color', [0 0.73 0]); +end + +% Update mean and sd of old posterior +inf_prior_sd = std(inf_ens(1:handles.ens_size)); +set(handles.text9, 'String', ['Inflated = ', num2str(prior_mean)]); +set(handles.text9, 'Visible', 'on'); +set(handles.text10, 'String', ['Inflated = ', num2str(inf_prior_sd)]); +set(handles.text10, 'Visible', 'on'); + + +% Get the update for the inflated ensemble +switch filter_type + case 'EAKF' + [obs_increments, err] = ... + obs_increment_eakf(inf_ens, handles.observation, handles.obs_error_sd^2); + case 'EnKF' + [obs_increments, err] = ... + obs_increment_enkf(inf_ens, handles.observation, handles.obs_error_sd^2); + case 'RHF' + [obs_increments, err] = ... + obs_increment_rhf(inf_ens, handles.observation, handles.obs_error_sd^2); +end + +% Add on increments to get new ensemble +new_ensemble = inf_ens + obs_increments; + +y(1:size(ensemble)) = -0.3; +handles.h_inf_up_ens = plot(new_ensemble, y, '*', 'MarkerSize', 16, 'Color', 'Blue'); + +% Plot lines connecting the prior and posterior ensemble members +for i = 1:size(ensemble, 2) + x_line = [inf_ens(i), new_ensemble(i)]; + y_line = [-0.2, -0.3]; + handles.h_inf_lines(i) = plot(x_line, y_line, 'k'); +end + +% Set a basic plotting domain range that includes mean +/- 3 obs SDs +% Plus all inflated members +lower = min(handles.observation - 3*handles.obs_error_sd, min(inf_ens)); +upper = max(handles.observation + 3*handles.obs_error_sd, max(inf_ens)); +axis([lower upper -0.4 1]); + +% Plot the axes for the two priors +plot([lower upper], [0 0], 'k', 'Linewidth', 2); +handles.h_inf_axis = plot([lower upper], [-0.2 -0.2], 'k', 'Linewidth', 2); + +% Update mean and sd of old posterior +update_inf_mean = mean(new_ensemble(1:handles.ens_size)); +update_inf_sd = std(new_ensemble(1:handles.ens_size)); +set(handles.text12, 'String', ['Inflated = ', num2str(update_inf_mean)]); +set(handles.text12, 'Visible', 'on'); +set(handles.text11, 'String', ['Inflated = ', num2str(update_inf_sd)]); +set(handles.text11, 'Visible', 'on'); + guidata(hObject, handles) + + + + + +% --- Executes on button press in checkbox_inflation. +function checkbox_inflation_Callback(hObject, eventdata, handles) +% hObject handle to checkbox_inflation (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of checkbox_inflation + + + + +function clear_labels(handles) + +% Turns off all labels except for the prior mean and SD +set(handles.text9, 'Visible', 'off'); +set(handles.text10, 'Visible', 'off'); +set(handles.text8, 'Visible', 'off'); +set(handles.text7, 'Visible', 'off'); +set(handles.text12, 'Visible', 'off'); +set(handles.text11, 'Visible', 'off'); + + + + + +function edit_inflation_Callback(hObject, eventdata, handles) +% hObject handle to edit_inflation (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit_inflation as text +% str2double(get(hObject,'String')) returns contents of edit_inflation as a double + +% Turn off any old updated points +set(handles.h_update_ens, 'Visible', 'off'); +set(handles.h_inf_up_ens, 'Visible', 'off'); +set(handles.h_inf_ens_member, 'Visible', 'off'); + +% Remove mean and sd of old posterior +clear_labels(handles); + +% And the lines in between +set(handles.h_update_lines, 'Visible', 'off'); +set(handles.h_inf_lines, 'Visible', 'off'); +set(handles.h_inf_axis, 'Visible', 'off'); + +% Enable things that an error might have turned off +set(handles.edit_observation, 'Enable', 'on') +set(handles.edit_obs_error_sd, 'Enable', 'on') +set(handles.pushbutton_create_new, 'Enable', 'on') + +% Only enable the update ensemble pushbutton if an ensemble has been created +if(handles.ens_size > 0) + set(handles.pushbutton_update_ens, 'Enable', 'on'); +end + +% Get the value of the observation +if(isfinite(str2double(get(hObject, 'String'))) && ... + str2double(get(hObject, 'String')) > 0) + inflation = str2double(get(hObject, 'String')); +else + set(handles.edit_inflation, 'String', '???'); + + % Disable other input to guarantee only one error at a time! + set(handles.edit_observation, 'Enable', 'off') + set(handles.edit_obs_error_sd, 'Enable', 'off') + set(handles.pushbutton_create_new, 'Enable', 'off') + set(handles.pushbutton_update_ens, 'Enable', 'off') + return +end + +% Update the value in global storage +handles.inflation = inflation; + +% Plot the updated distribution +set(handles.h_obs_plot, 'Visible', 'off'); +handles.h_obs_plot = plot_gaussian(handles.observation, handles.obs_error_sd, 1); +set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); + +% Set a basic plotting domain range that includes mean +/- 3 obs SDs +lower = min(handles.observation - 3*handles.obs_error_sd, min(handles.ens_members)); +upper = max(handles.observation + 3*handles.obs_error_sd, max(handles.ens_members)); +axis([lower upper -0.4 1]); + +set(handles.h_obs_plot, 'Color', 'r', 'Linestyle', '--', 'Linewidth', 2); + +set(gca, 'YTick', [0 0.2 0.4 0.6 0.8]); +set(gca, 'YTickLabel', [0 0.2 0.4 0.6 0.8]); + +hold on +plot([lower upper], [0 0], 'k', 'Linewidth', 2); + +% Update handles structure +guidata(hObject, handles); + + + + + + + +% --- Executes during object creation, after setting all properties. +function edit_inflation_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit_inflation (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + Modified: DART/trunk/DART_LAB/matlab/oned_model.fig =================================================================== (Binary files differ) Modified: DART/trunk/DART_LAB/matlab/oned_model.m =================================================================== --- DART/trunk/DART_LAB/matlab/oned_model.m 2009-08-28 22:44:56 UTC (rev 4023) +++ DART/trunk/DART_LAB/matlab/oned_model.m 2009-08-28 22:46:16 UTC (rev 4024) @@ -5,7 +5,7 @@ % % ONED_MODEL demonstrates the simplest possible case of ensemble data % assimilation. It is possible to explore assimilation algorithms, -% ensemble sizes, observation biases, etc. on-the-fly. The posterior +% ensemble sizes, model biases, etc. on-the-fly. The posterior % of the state is indicated by blue asterisks, the states evolve along % a tajectory indicated by the green lines to wind up at a prior state % for the assimilation - indicated by the green asterisks. After the @@ -44,7 +44,7 @@ % $Revision$ % $Date$ -% Last Modified by GUIDE v2.5 06-May-2009 08:31:46 +% Last Modified by GUIDE v2.5 27-Aug-2009 08:54:05 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -91,7 +91,8 @@ handles.error = 0; handles.spread = 0; handles.kurtosis = 0; -handles.obs_bias = 0; +handles.model_bias = 0; +handles.inflation = 1.0; % An array to keep track of rank histograms handles.prior_rank(1 : handles.ens_size + 1) = 0; @@ -202,16 +203,21 @@ % Hints: get(hObject,'String') returns contents of edit1 as text % str2double(get(hObject,'String')) returns contents of edit1 as a double -% Get the value of the obs_bias -if(isfinite(str2double(get(hObject, 'String')))) - handles.obs_bias = str2double(get(hObject, 'String')); -else +% Get the value of the model_bias +handles.model_bias = str2double(get(hObject, 'String')); +if(not(isfinite(handles.model_bias))) + % Indicate input error in text box set(handles.edit1, 'String', '???'); - % Disable other input to guarantee only one error at a time! + % After this, only this edit box will work + turn_off_controls(handles); + set(handles.edit1, 'Enable', 'On'); + return end +% Turn on all controls if successful +turn_on_controls(handles) % Update handles structure guidata(hObject, handles); @@ -314,15 +320,20 @@ % str2double(get(hObject,'String')) returns contents of edit5 as a double % Get the value of the model nonlinearity parameter -if(isfinite(str2double(get(hObject, 'String')))) - handles.alpha= str2double(get(hObject, 'String')); -else +handles.alpha= str2double(get(hObject, 'String')); +if(not(isfinite(handles.alpha)) | handles.alpha < 0) + % Indicate input error in text box set(handles.edit5, 'String', '???'); - % Disable other input to guarantee only one error at a time! + % After this, only this edit box will work + turn_off_controls(handles); + set(handles.edit5, 'Enable', 'On'); + return end +% Enable all controls +turn_on_controls(handles); % Update handles structure guidata(hObject, handles); @@ -364,6 +375,23 @@ return end +% Get the value of the ensemble size +new_ens_size = str2double(get(hObject, 'String')); +if(not(isfinite(new_ens_size)) | new_ens_size < 2) + % Indicate input error in text box + set(handles.edit6, 'String', '???'); + + % After this, only this edit box will work + turn_off_controls(handles); + set(handles.edit6, 'Enable', 'On'); + + return +end + +% Legal value for ensemble size; enable all controls +turn_on_controls(handles); + +% Reset the histograms handles = reset_histograms(new_ens_size, hObject, handles); % Generate a new ensemble by truncating old ensemble OR adding new @@ -514,14 +542,9 @@ % Turn off all the other controls to avoid a mess -set(handles.pushbutton1, 'Enable', 'Off'); -set(handles.reset_pushbutton, 'Enable', 'Off'); -set(handles.edit1, 'Enable', 'Off'); -set(handles.edit5, 'Enable', 'Off'); -set(handles.edit6, 'Enable', 'Off'); -set(handles.popupmenu1, 'Enable', 'Off'); +turn_off_controls(handles) +set(handles.pushbutton_run, 'Enable', 'On'); - if(strcmp(get(hObject, 'String'), 'Stop Free Run')) % Being told to stop; switch to not running status set(hObject, 'String', 'Start Free Run'); @@ -541,31 +564,19 @@ status_string = get(my_data.pushbutton_run, 'String'); if(strcmp(status_string, 'Start Free Run')) % Turn all the other controls back on - set(handles.pushbutton1, 'Enable', 'On'); - set(handles.reset_pushbutton, 'Enable', 'On'); - set(handles.edit1, 'Enable', 'On'); - set(handles.edit5, 'Enable', 'On'); - set(handles.edit6, 'Enable', 'On'); - set(handles.popupmenu1, 'Enable', 'On'); - + turn_on_controls(handles); return end % Do the next advance or assimilation step step_ahead(hObject, my_data) - pause(1) + pause(0.2) end end % Turn all the other controls back on -set(handles.pushbutton1, 'Enable', 'On'); -set(handles.reset_pushbutton, 'Enable', 'On'); -set(handles.edit1, 'Enable', 'On'); -set(handles.edit5, 'Enable', 'On'); -set(handles.edit6, 'Enable', 'On'); -set(handles.popupmenu1, 'Enable', 'On'); +turn_on_controls(handles); - %----------- Moves the model ahead or assimilates next observations ------ function step_ahead(hObject, handles) @@ -578,7 +589,14 @@ % Set to do an assimilation next time handles.ready_to_advance = false; % Advance the model - ens_new = advance_oned(handles.ens, handles.alpha); + ens_new = advance_oned(handles.ens, handles.alpha, handles.model_bias); + +% Inflate the model + ens_new_mean = mean(ens_new); + ens_new = (ens_new - ens_new_mean) * sqrt(handles.inflation) + ens_new_mean; + + + handles.time_step = handles.time_step + 1; h = plot(handles.time_step - 0.1, ens_new, '*', 'MarkerSize', 6); set(h, 'Color', [0 0.73 0]); @@ -710,7 +728,7 @@ handles.ready_to_advance = true; % Generate the observation as a draw Normal(0, 1) obs_error_sd = handles.obs_error_sd; - observation = randn(obs_error_sd) + handles.obs_bias; + observation = randn(obs_error_sd); % Plot the observation plot(handles.time_step, observation, 'r*', 'MarkerSize', 10); @@ -918,3 +936,77 @@ +function edit7_Callback(hObject, eventdata, handles) +% hObject handle to edit7 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit7 as text +% str2double(get(hObject,'String')) returns contents of edit7 as a double + +% Get the value of the model_bias +handles.inflation= str2double(get(hObject, 'String')); +if(not(isfinite(handles.inflation)) | handles.inflation < 1) + % Indicate input error in text box + set(handles.edit7, 'String', '???'); + + % After this, only this edit box will work + turn_off_controls(handles); + set(handles.edit7, 'Enable', 'On'); + + return +end + +% Turn on all the controls +turn_on_controls(handles); + +% Update handles structure +guidata(hObject, handles); + + + +% --- Executes during object creation, after setting all properties. +function edit7_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit7 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + + +%-----------Turns off all the controls---------- +function turn_off_controls(handles) + +% Turn off all the other controls to avoid a mess +set(handles.pushbutton1, 'Enable', 'Off'); +set(handles.pushbutton_run, 'Enable', 'Off'); +set(handles.reset_pushbutton, 'Enable', 'Off'); +set(handles.edit1, 'Enable', 'Off'); +set(handles.edit5, 'Enable', 'Off'); +set(handles.edit6, 'Enable', 'Off'); +set(handles.edit7, 'Enable', 'Off'); +set(handles.popupmenu1, 'Enable', 'Off'); + + + + +%-----------Turns on all the controls---------- +function turn_on_controls(handles) + +% Turn on all the other controls to avoid a mess +set(handles.pushbutton1, 'Enable', 'On'); +set(handles.pushbutton_run, 'Enable', 'On'); +set(handles.reset_pushbutton, 'Enable', 'On'); +set(handles.edit1, 'Enable', 'On'); +set(handles.edit5, 'Enable', 'On'); +set(handles.edit6, 'Enable', 'On'); +set(handles.edit7, 'Enable', 'On'); +set(handles.popupmenu1, 'Enable', 'On'); + + + Modified: DART/trunk/DART_LAB/matlab/run_lorenz_96.fig =================================================================== (Binary files differ) Modified: DART/trunk/DART_LAB/matlab/run_lorenz_96.m =================================================================== --- DART/trunk/DART_LAB/matlab/run_lorenz_96.m 2009-08-28 22:44:56 UTC (rev 4023) +++ DART/trunk/DART_LAB/matlab/run_lorenz_96.m 2009-08-28 22:46:16 UTC (rev 4024) @@ -30,7 +30,7 @@ % $Revision$ % $Date$ -% Last Modified by GUIDE v2.5 02-Jun-2009 15:44:28 +% Last Modified by GUIDE v2.5 27-Aug-2009 16:35:11 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -88,15 +88,15 @@ handles.h_truth = 0; % Generate set of ensemble perturbations -for n = 1:ens_size +for n = 1:handles.ens_size handles.post(1, 1:MODEL_SIZE, n) = handles.true_state(1, :); end -handles.post(1, 1:MODEL_SIZE, 1:ens_size) = ... - handles.post(1, 1:MODEL_SIZE, 1:ens_size) + ... - 0.001 * randn(1, MODEL_SIZE, ens_size); +handles.post(1, 1:MODEL_SIZE, 1:handles.ens_size) = ... + handles.post(1, 1:MODEL_SIZE, 1:handles.ens_size) + ... + 0.001 * randn(1, MODEL_SIZE, handles.ens_size); % For convenience make the first prior identical to the first posterior -handles.prior(1, 1:MODEL_SIZE, 1:ens_size) = handles.post; +handles.prior(1, 1:MODEL_SIZE, 1:handles.ens_size) = handles.post; % Update handles structure @@ -470,3 +470,58 @@ end + +function edit_ens_size_Callback(hObject, eventdata, handles) +% hObject handle to edit_ens_size (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of edit_ens_size as text +% str2double(get(hObject,'String')) returns contents of edit_ens_size as a double + +% Set the ensemble size global value to the update +handles.ens_size = str2double(get(hObject, 'String')); +if(not(isfinite(handles.ens_size)) | handles.ens_size < 2) + set(handles.edit_ens_size, 'String', '???'); + + % After this, only this edit box will work + %%%turn_off_controls(handles); + set(handles.edit_ens_size, 'Enable', 'On'); + + return +end + +% Enable all controls +%%%turn_on_controls(handles); + +% Need to reset the ensemble and the time +slkjdf + + + +% Update handles structure +guidata(hObject, handles); + + + + +% --- Executes during object creation, after setting all properties. +function edit_ens_size_CreateFcn(hObject, eventdata, handles) +% hObject handle to edit_ens_size (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes when uipanel2 is resized. +function uipanel2_ResizeFcn(hObject, eventdata, handles) +% hObject handle to uipanel2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + + From nancy at ucar.edu Mon Aug 31 15:25:29 2009 From: nancy at ucar.edu (nancy at ucar.edu) Date: Mon, 31 Aug 2009 15:25:29 -0600 (MDT) Subject: [Dart-dev] [4025] DART/trunk/models/POP: A non-advancing 'perfect model' assimilation and 'filter' worked for a Message-ID: <200908312125.n7VLPTg1000897@subversion.ucar.edu> An HTML attachment was scrubbed... URL: http://mailman.ucar.edu/pipermail/dart-dev/attachments/20090831/27d0d990/attachment.html -------------- next part -------------- Modified: DART/trunk/models/POP/dart_pop_mod.f90 =================================================================== --- DART/trunk/models/POP/dart_pop_mod.f90 2009-08-28 22:46:16 UTC (rev 4024) +++ DART/trunk/models/POP/dart_pop_mod.f90 2009-08-31 21:25:29 UTC (rev 4025) @@ -66,6 +66,17 @@ stop_option, stop_count, date_separator, allow_leapyear, fit_freq !------------------------------------------------------------------ +! The POP I/O namelist variables +!------------------------------------------------------------------ + +character(len=100) :: log_filename, pointer_filename +logical :: lredirect_stdout, luse_pointer_files +integer :: num_iotasks + +namelist /io_nml/ num_iotasks, lredirect_stdout, log_filename, & + luse_pointer_files, pointer_filename + +!------------------------------------------------------------------ ! The POP restart manager namelist variables !------------------------------------------------------------------ @@ -168,25 +179,46 @@ call set_calendar_type('noleap') endif +! Read POP I/O information (for restart file ... grid dimensions) ! Read POP initial information (for input/restart filename) -! The tricky part here is that we should really check for -! the existence of the init_ts_file and take evasive action -! like checking for the existence of a pointer file. +call find_namelist_in_file('pop_in', 'io_nml', iunit) +read(iunit, nml = io_nml, iostat = io) +call check_namelist_read(iunit, io, 'io_nml') + call find_namelist_in_file('pop_in', 'init_ts_nml', iunit) read(iunit, nml = init_ts_nml, iostat = io) call check_namelist_read(iunit, io, 'init_ts_nml') -ic_filename = trim(init_ts_file)//'.'//trim(init_ts_file_fmt) +! Is it a pointer file or not ... +if ( luse_pointer_files ) then -! FIXME ... what about the pointer file ... + restart_filename = trim(pointer_filename)//'.restart' + + if ( .not. file_exist(restart_filename) ) then + msgstring = 'pop_in:pointer file '//trim(restart_filename)//' not found' + call error_handler(E_ERR,'initialize_module', & + msgstring, source, revision, revdate) + endif + + iunit = open_file(restart_filename,'formatted') + read(iunit,'(A)')ic_filename + + restart_filename = ' ' + write(*,*)'DEBUG ... pointer filename dereferenced to ',trim(ic_filename ) + +else + ic_filename = trim(init_ts_file)//'.'//trim(init_ts_file_fmt) +endif + +! Make sure we have a pop restart file (for grid dims) if ( .not. file_exist(ic_filename) ) then msgstring = 'pop_in:init_ts_file '//trim(ic_filename)//' not found' call error_handler(E_ERR,'initialize_module', & msgstring, source, revision, revdate) endif -! Read POP restart information (for model timestepping/grid dimensions) +! Read POP restart information (for model timestepping) call find_namelist_in_file('pop_in', 'restart_nml', iunit) read(iunit, nml = restart_nml, iostat = io) call check_namelist_read(iunit, io, 'restart_nml') @@ -196,7 +228,7 @@ read(iunit, nml = domain_nml, iostat = io) call check_namelist_read(iunit, io, 'domain_nml') -! Read POP grid information (for grid dims/filenames) +! Read POP grid information (for grid filenames) call find_namelist_in_file('pop_in', 'grid_nml', iunit) read(iunit, nml = grid_nml, iostat = io) call check_namelist_read(iunit, io, 'grid_nml') Modified: DART/trunk/models/POP/dart_to_pop.f90 =================================================================== --- DART/trunk/models/POP/dart_to_pop.f90 2009-08-28 22:46:16 UTC (rev 4024) +++ DART/trunk/models/POP/dart_to_pop.f90 2009-08-31 21:25:29 UTC (rev 4025) @@ -47,7 +47,7 @@ ! The namelist variables !------------------------------------------------------------------ -character (len = 128) :: dart_to_pop_input_file = 'assim_model_state_ic' +character (len = 128) :: dart_to_pop_input_file = 'filter_ics' character (len = 128) :: dart_to_pop_restart_file = 'my_pop_restart_file' logical :: advance_time_present = .TRUE. Added: DART/trunk/models/POP/shell_scripts/run_perfect_model_obs.batch =================================================================== --- DART/trunk/models/POP/shell_scripts/run_perfect_model_obs.batch (rev 0) +++ DART/trunk/models/POP/shell_scripts/run_perfect_model_obs.batch 2009-08-31 21:25:29 UTC (rev 4025) @@ -0,0 +1,223 @@ +#!/bin/csh +# +#BXXX -b 18:00 +#BSUB -J POP_OSSE +#BSUB -o POP_OSSE.%J.log +#BSUB -N -u ${USER}@ucar.edu +#BSUB -q economy +#BSUB -n 16 +#BSUB -R "span[ptile=2]" +#BSUB -W 2:00 +#BSUB -m "cr0128en cr0129en cr0130en cr0131en cr0132en cr0133en cr0134en cr0135en cr0136en cr0137en cr0138en cr0139en cr0140en cr0141en cr0202en cr0201en" +# +#----------------------------------------------------------------------------- +# Data Assimilation Research Testbed -- DART +# Copyright 2004-2009, Data Assimilation Research Section +# University Corporation for Atmospheric Research +# Licensed under the GPL -- www.gpl.org/licenses/gpl.html +# +# +# $URL: http://subversion.ucar.edu/DAReS/DART/trunk/models/POP/shell_scripts/job.simple.csh $ +# $Id: job.simple.csh 3575 2008-08-21 18:01:05Z thoar $ +# $Revision: 3575 $ +# $Date: 2008-08-21 12:01:05 -0600 (Thu, 21 Aug 2008) $ +#----------------------------------------------------------------------------- +# run_perfect_model_obs.batch ... Top level script to generate observations and a TRUE state. +# +# Unlike the more complex job.csh, this script only processes a single +# observation file. Still fairly complex; requires a raft of +# data files and most of them are in hardcoded locations. +# +# This script is designed to be run from the command line (as a single thread) +# and should only take a few seconds to a minute to complete, depending on +# the filesystem performance and data file size. +# +# The script moves the necessary files to the current directory - in DART +# nomenclature, this will be called CENTRALDIR. +# After everything is confirmed to have been assembled, it is possible +# to edit the data, data.cal, and input.nml files for the specifics of +# the experiment; as well as allow final configuration of a 'nodelist' file. +# +# Once the 'table is set', all that remains is to start/submit the +# 'runme_filter' script. That script will spawn 'filter' as a +# parallel job on the appropriate nodes; each of these tasks will +# call a separate model_advance.csh when necessary. +# +# The central directory is where the scripts reside and where script and +# program I/O are expected to happen. +#----------------------------------------------------------------------------- + +#---------------------------------------------------------------------- +# Turns out the scripts are a lot more flexible if you don't rely on +# the queuing-system-specific variables -- so I am converting them to +# 'generic' names and using the generics throughout the remainder. +#---------------------------------------------------------------------- + +if ($?LSB_HOSTS) then + + setenv ORIGINALDIR $LS_SUBCWD + setenv JOBNAME $LSB_OUTPUTFILE:ar + setenv JOBID $LSB_JOBID + setenv MYQUEUE $LSB_QUEUE + setenv MYHOST $LSB_SUB_HOST + +else + + #------------------------------------------------------------------- + # You can run this interactively to check syntax, file motion, etc. + #------------------------------------------------------------------- + + setenv ORIGINALDIR `pwd` + setenv JOBNAME POP + setenv JOBID $$ + setenv MYQUEUE Interactive + setenv MYHOST $host + +endif + +#---------------------------------------------------------------------- +# Just an echo of job attributes +#---------------------------------------------------------------------- + +echo +echo "${JOBNAME} ($JOBID) submitted from $ORIGINALDIR" +echo "${JOBNAME} ($JOBID) submitted from $MYHOST" +echo "${JOBNAME} ($JOBID) running in queue $MYQUEUE" +echo "${JOBNAME} ($JOBID) running on $host" +echo "${JOBNAME} ($JOBID) started at "`date` +echo + +#---------------------------------------------------------------------- +# Make a unique, (empty, clean) temporary directory. +#---------------------------------------------------------------------- + +setenv TMPDIR /ptmp/${user}/${JOBNAME}/job_${JOBID} + +mkdir -p ${TMPDIR} +cd ${TMPDIR} + +set CENTRALDIR = `pwd` +set myname = $0 # this is the name of this script + +# some systems don't like the -v option to any of the following + +set OSTYPE = `uname -s` +switch ( ${OSTYPE} ) + case IRIX64: + setenv REMOVE 'rm -rf' + setenv COPY 'cp -p' + setenv MOVE 'mv -f' + breaksw + case AIX: + setenv REMOVE 'rm -rf' + setenv COPY 'cp -p' + setenv MOVE 'mv -f' + breaksw + default: + setenv REMOVE 'rm -rvf' + setenv COPY 'cp -vp' + setenv MOVE 'mv -fv' + breaksw +endsw + +echo "${JOBNAME} ($JOBID) CENTRALDIR == $CENTRALDIR" + +#----------------------------------------------------------------------------- +# Set variables containing various directory names where we will GET things +#----------------------------------------------------------------------------- + +set DARTDIR = /fs/image/home/${user}/SVN/DART/models/POP +set POPDIR = /fs/image/home/${user}/SVN/DART/models/POP/input + +#----------------------------------------------------------------------------- +# Get the DART executables, scripts, and input files +#----------------------------------------------------------------------------- + +# executables +${COPY} ${DARTDIR}/work/perfect_model_obs . +${COPY} ${DARTDIR}/work/dart_to_pop . +${COPY} ${DARTDIR}/work/pop_to_dart . + +# shell scripts +${COPY} ${DARTDIR}/shell_scripts/advance_model.csh . + +# data files +${COPY} ${DARTDIR}/work/obs_seq.in . +${COPY} ${DARTDIR}/work/dart.ics perfect_ics +${COPY} ${DARTDIR}/work/input.nml . + +#----------------------------------------------------------------------------- +# Get the POP executable, control files, and data files. +# trying to use the CCSM naming conventions +#----------------------------------------------------------------------------- + +${COPY} ${POPDIR}/pop . +${COPY} ${POPDIR}/pop_in.part1 . +${COPY} ${POPDIR}/pop_in.part2 . +${COPY} ${POPDIR}/pop.r.nc . +echo "pop.r.nc" >! pop_pointer.restart + +${COPY} ${POPDIR}/gx3v5_tavg_contents . +${COPY} ${POPDIR}/gx3v5_movie_contents . +${COPY} ${POPDIR}/gx3v5_history_contents . +${COPY} ${POPDIR}/gx3v5_transport_contents . + +${COPY} ${POPDIR}/vert_grid.gx3v5 . +${COPY} ${POPDIR}/horiz_grid.gx3v5.r8ieee.le . +${COPY} ${POPDIR}/topography.gx3v5.r8ieee.le . + +#${COPY} ${POPDIR}/chl_mm_SeaWiFs97-01_20031205.ieeer8 . +#${COPY} ${POPDIR}/sfwf_20040517.ieeer8 . +#${COPY} ${POPDIR}/shf_20031208.ieeer8 . +#${COPY} ${POPDIR}/tidal_energy_gx3v5_20081021.ieeer8 . +#${COPY} ${POPDIR}/ts_PHC2_jan_20030806.ieeer8 . + +#----------------------------------------------------------------------------- +# Check that everything moved OK, and the table is set. +# Gives us a chance to edit the local input.nml, data.cal, etc. if needed. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Run perfect_model_obs ... harvest the observations to populate obs_seq.out +#----------------------------------------------------------------------------- + +cat pop_in.part1 pop_in.part2 >! pop_in + +./perfect_model_obs + +echo "${JOBNAME} ($JOBID) finished at "`date` + +#----------------------------------------------------------------------------- +# Move the output to storage after filter completes. +# At this point, all the restart,diagnostic files are in the CENTRALDIR +# and need to be moved to the 'experiment permanent' directory. +# We have had problems with some, but not all, files being moved +# correctly, so we are adding bulletproofing to check to ensure the filesystem +# has completed writing the files, etc. Sometimes we get here before +# all the files have finished being written. +#----------------------------------------------------------------------------- + +echo "Listing contents of CENTRALDIR before archiving" +ls -l + +exit + +${MOVE} *.data *.meta ${experiment}/POP +${MOVE} data data.cal ${experiment}/POP +${MOVE} STD* ${experiment}/POP + +${MOVE} filter_restart* ${experiment}/DART +${MOVE} assim_model_state_ud[1-9]* ${experiment}/DART +${MOVE} assim_model_state_ic[1-9]* ${experiment}/DART +${MOVE} Posterior_Diag.nc ${experiment}/DART +${MOVE} Prior_Diag.nc ${experiment}/DART +${MOVE} obs_seq.final ${experiment}/DART +${MOVE} dart_log.out ${experiment}/DART + +# Good style dictates that you save the scripts so you can see what worked. + +${COPY} input.nml ${experiment}/DART +${COPY} *.csh ${experiment}/DART +${COPY} $myname ${experiment}/DART + +ls -lrt Property changes on: DART/trunk/models/POP/shell_scripts/run_perfect_model_obs.batch ___________________________________________________________________ Name: svn:executable + * Added: DART/trunk/models/POP/work/README =================================================================== --- DART/trunk/models/POP/work/README (rev 0) +++ DART/trunk/models/POP/work/README 2009-08-31 21:25:29 UTC (rev 4025) @@ -0,0 +1,48 @@ +create_obs_sequence parameters: + Input upper bound on number of observations in sequence : 10 + Input number of copies of data (0 for just a definition): 0 + Input number of quality control values per field (0 or greater): 0 + input a -1 if there are no more obs: 0 + + Input -1 * state variable index for identity observations + OR input the name of the observation kind from table below: + OR input the integer index, BUT see documentation... + 1 SALINITY + 2 TEMPERATURE + 3 U_CURRENT_COMPONENT + 4 V_CURRENT_COMPONENT + 5 SEA_SURFACE_HEIGHT +2 + location_mod:initialize_module vert-normalization 20.0000000000000 100000.000000000 10000.0000000000 + location_mod:initialize_module horizontal only T + Vertical co-ordinate options + -2 --> vertical coordinate undefined + -1 --> surface + 1 --> model level + 2 --> pressure + 3 --> height +3 + Vertical co-ordinate height : 23.0 + Input longitude: value 0 to 360.0 or a negative number for + Uniformly distributed random location in the horizontal: 315 + Input latitude: value -90.0 to 90.0: 30 + input time in days and seconds (as integers): 8760 0 + Input error variance for this observation definition : 2.0 + input a -1 if there are no more obs : -1 + Input filename for sequence ( set_def.out usually works well): set_def.out + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- + +create_fixed_network_sequence + +set_def.out +1 +1 +8760 0 +1 0 +obs_seq.in + + + + Modified: DART/trunk/models/POP/work/input.nml =================================================================== --- DART/trunk/models/POP/work/input.nml 2009-08-28 22:46:16 UTC (rev 4024) +++ DART/trunk/models/POP/work/input.nml 2009-08-31 21:25:29 UTC (rev 4025) @@ -20,7 +20,7 @@ &filter_nml async = 2, adv_ens_command = "./advance_model.csh", - ens_size = 8, + ens_size = 10, start_from_restart = .false., output_restart = .true., obs_sequence_in_name = "obs_seq.perfect", @@ -78,7 +78,7 @@ &ensemble_manager_nml single_restart_file_in = .true., - single_restart_file_out = .true., + single_restart_file_out = .false., perturbation_amplitude = 0.2 / &cov_cutoff_nml