New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
Chap_OBS.tex in trunk/DOC/TexFiles/Chapters – NEMO

source: trunk/DOC/TexFiles/Chapters/Chap_OBS.tex @ 6997

Last change on this file since 6997 was 6997, checked in by nicolasmartin, 8 years ago

Duplication of changes in DOC directory for the trunk

File size: 59.0 KB
Line 
1\documentclass[NEMO_book]{subfiles}
2\begin{document}
3% ================================================================
4% Chapter observation operator (OBS)
5% ================================================================
6\chapter{Observation and model comparison (OBS)}
7\label{OBS}
8
9Authors: D. Lea, M. Martin, K. Mogensen, A. Vidard, A. Weaver, A. Ryan, ...   % do we keep that ?
10
11\minitoc
12
13
14\newpage
15$\ $\newline    % force a new line
16
17The observation and model comparison code (OBS) reads in observation files (profile
18temperature and salinity, sea surface temperature, sea level anomaly, sea ice concentration,
19and velocity) and calculates  an interpolated model equivalent value at the observation
20location and nearest model timestep. The resulting data are saved in a ``feedback'' file (or
21files). The code was originally developed for use with the NEMOVAR data assimilation code, but
22can be used for validation or verification of the model or with any other data assimilation system.
23
24The OBS code is called from \mdl{nemogcm} for model initialisation and to calculate the model
25equivalent values for observations on the 0th timestep. The code is then called again after
26each timestep from \mdl{step}. The code is only activated if the namelist logical \np{ln\_diaobs}
27is set to true.
28
29For all data types a 2D horizontal  interpolator is needed to interpolate the model fields to
30the observation location. For {\em in situ} profiles, a 1D vertical interpolator is needed in
31addition to provide model fields at the observation depths. Currently this only works in
32z-level model configurations, but is being developed to work with a generalised vertical
33coordinate system.
34
35Some profile observation types (e.g. tropical moored buoys) are made available as daily averaged quantities.
36The observation operator code can be set-up to calculated the equivalent daily average model temperature fields
37using the \np{nn\_profdavtypes} namelist array. Some SST observations are equivalent to a night-time
38average value and the observation operator code can calculate equivalent night-time average model SST fields by
39setting the namelist value \np{ln\_sstnight} to true. Otherwise the model value from the nearest timestep to the
40observation time is used.
41
42The code is controlled by the namelist \textit{nam\_obs}. See the following sections for more
43details on setting up the namelist.
44
45Section~\ref{OBS_example} introduces a test example of the observation operator code including
46where to obtain data and how to setup the namelist. Section~\ref{OBS_details} introduces some
47more technical details of the different observation types used and also shows a more complete
48namelist. Section~\ref{OBS_theory} introduces some of the theoretical aspects of the observation
49operator including interpolation methods and running on multiple processors.
50Section~\ref{OBS_ooo} describes the offline observation operator code.
51Section~\ref{OBS_obsutils} introduces some utilities to help working with the files
52produced by the OBS code.
53
54% ================================================================
55% Example
56% ================================================================
57\section{Running the observation operator code example}
58\label{OBS_example}
59
60This section describes an example of running the observation operator code using
61profile data which can be freely downloaded. It shows how to adapt an
62existing run and build of NEMO to run the observation operator.
63
64\begin{enumerate}
65\item Compile NEMO.
66
67\item Download some EN4 data from
68\href{http://www.metoffice.gov.uk/hadobs}{http://www.metoffice.gov.uk/hadobs}. Choose observations which are
69valid for the period of your test run because the observation operator compares
70the model and observations for a matching date and time.
71
72\item Compile the OBSTOOLS code using:
73\begin{verbatim}
74./maketools -n OBSTOOLS -m [ARCH].
75\end{verbatim}
76
77\item Convert the EN4 data into feedback format:
78\begin{verbatim}
79enact2fb.exe profiles_01.nc EN.4.1.1.f.profiles.g10.YYYYMM.nc
80\end{verbatim}
81
82\item Include the following in the NEMO namelist to run the observation
83operator on this data:
84\end{enumerate}
85
86%------------------------------------------namobs_example-----------------------------------------------------
87\namdisplay{namobs_example}
88%-------------------------------------------------------------------------------------------------------------
89
90Options are defined through the  \ngn{namobs} namelist variables.
91The options \np{ln\_t3d} and \np{ln\_s3d} switch on the temperature and salinity
92profile observation operator code. The filename or array of filenames are
93specified using the \np{cn\_profbfiles} variable. The model grid points for a
94particular  observation latitude and longitude are found using the grid
95searching part of the code. This can be expensive, particularly for large
96numbers of observations, setting \np{ln\_grid\_search\_lookup} allows the use of
97a lookup table which is saved into an ``xypos`` file (or files). This will need
98to be generated the first time if it does not exist in the run directory.
99However, once produced it will significantly speed up future grid searches.
100Setting \np{ln\_grid\_global} means that the code distributes the observations
101evenly between processors. Alternatively each processor will work with
102observations located within the model subdomain (see section~\ref{OBS_parallel}).
103
104A number of utilities are now provided to plot the feedback files, convert and
105recombine the files. These are explained in more detail in section~\ref{OBS_obsutils}.
106Utilites to convert other input data formats into the feedback format are also
107described in section~\ref{OBS_obsutils}.
108
109\section{Technical details}
110\label{OBS_details}
111
112Here we show a more complete example namelist  \ngn{namobs} and also show the NetCDF headers
113of the observation
114files that may be used with the observation operator
115
116%------------------------------------------namobs--------------------------------------------------------
117\namdisplay{namobs}
118%-------------------------------------------------------------------------------------------------------------
119
120The observation operator code uses the "feedback" observation file format for
121all data types. All the
122observation files must be in NetCDF format. Some example headers (produced using
123\mbox{\textit{ncdump~-h}}) for profile
124data, sea level anomaly and sea surface temperature are in the following
125subsections.
126
127\subsection{Profile feedback type observation file header}
128
129\begin{alltt}
130\tiny
131\begin{verbatim}
132netcdf profiles_01 {
133dimensions:
134     N_OBS = 603 ;
135     N_LEVELS = 150 ;
136     N_VARS = 2 ;
137     N_QCF = 2 ;
138     N_ENTRIES = 1 ;
139     N_EXTRA = 1 ;
140     STRINGNAM = 8 ;
141     STRINGGRID = 1 ;
142     STRINGWMO = 8 ;
143     STRINGTYP = 4 ;
144     STRINGJULD = 14 ;
145variables:
146     char VARIABLES(N_VARS, STRINGNAM) ;
147          VARIABLES:long_name = "List of variables in feedback files" ;
148     char ENTRIES(N_ENTRIES, STRINGNAM) ;
149          ENTRIES:long_name = "List of additional entries for each variable in feedback files" ;
150     char EXTRA(N_EXTRA, STRINGNAM) ;
151          EXTRA:long_name = "List of extra variables" ;
152     char STATION_IDENTIFIER(N_OBS, STRINGWMO) ;
153          STATION_IDENTIFIER:long_name = "Station identifier" ;
154     char STATION_TYPE(N_OBS, STRINGTYP) ;
155          STATION_TYPE:long_name = "Code instrument type" ;
156     double LONGITUDE(N_OBS) ;
157          LONGITUDE:long_name = "Longitude" ;
158          LONGITUDE:units = "degrees_east" ;
159          LONGITUDE:_Fillvalue = 99999.f ;
160     double LATITUDE(N_OBS) ;
161          LATITUDE:long_name = "Latitude" ;
162          LATITUDE:units = "degrees_north" ;
163          LATITUDE:_Fillvalue = 99999.f ;
164     double DEPTH(N_OBS, N_LEVELS) ;
165          DEPTH:long_name = "Depth" ;
166          DEPTH:units = "metre" ;
167          DEPTH:_Fillvalue = 99999.f ;
168     int DEPTH_QC(N_OBS, N_LEVELS) ;
169          DEPTH_QC:long_name = "Quality on depth" ;
170          DEPTH_QC:Conventions = "q where q =[0,9]" ;
171          DEPTH_QC:_Fillvalue = 0 ;
172     int DEPTH_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
173          DEPTH_QC_FLAGS:long_name = "Quality flags on depth" ;
174          DEPTH_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
175     double JULD(N_OBS) ;
176          JULD:long_name = "Julian day" ;
177          JULD:units = "days since JULD_REFERENCE" ;
178          JULD:Conventions = "relative julian days with decimal part (as parts of day)" ;
179          JULD:_Fillvalue = 99999.f ;
180     char JULD_REFERENCE(STRINGJULD) ;
181          JULD_REFERENCE:long_name = "Date of reference for julian days" ;
182          JULD_REFERENCE:Conventions = "YYYYMMDDHHMMSS" ;
183     int OBSERVATION_QC(N_OBS) ;
184          OBSERVATION_QC:long_name = "Quality on observation" ;
185          OBSERVATION_QC:Conventions = "q where q =[0,9]" ;
186          OBSERVATION_QC:_Fillvalue = 0 ;
187     int OBSERVATION_QC_FLAGS(N_OBS, N_QCF) ;
188          OBSERVATION_QC_FLAGS:long_name = "Quality flags on observation" ;
189          OBSERVATION_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
190          OBSERVATION_QC_FLAGS:_Fillvalue = 0 ;
191     int POSITION_QC(N_OBS) ;
192          POSITION_QC:long_name = "Quality on position (latitude and longitude)" ;
193          POSITION_QC:Conventions = "q where q =[0,9]" ;
194          POSITION_QC:_Fillvalue = 0 ;
195     int POSITION_QC_FLAGS(N_OBS, N_QCF) ;
196          POSITION_QC_FLAGS:long_name = "Quality flags on position" ;
197          POSITION_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
198          POSITION_QC_FLAGS:_Fillvalue = 0 ;
199     int JULD_QC(N_OBS) ;
200          JULD_QC:long_name = "Quality on date and time" ;
201          JULD_QC:Conventions = "q where q =[0,9]" ;
202          JULD_QC:_Fillvalue = 0 ;
203     int JULD_QC_FLAGS(N_OBS, N_QCF) ;
204          JULD_QC_FLAGS:long_name = "Quality flags on date and time" ;
205          JULD_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
206          JULD_QC_FLAGS:_Fillvalue = 0 ;
207     int ORIGINAL_FILE_INDEX(N_OBS) ;
208          ORIGINAL_FILE_INDEX:long_name = "Index in original data file" ;
209          ORIGINAL_FILE_INDEX:_Fillvalue = -99999 ;
210     float POTM_OBS(N_OBS, N_LEVELS) ;
211          POTM_OBS:long_name = "Potential temperature" ;
212          POTM_OBS:units = "Degrees Celsius" ;
213          POTM_OBS:_Fillvalue = 99999.f ;
214     float POTM_Hx(N_OBS, N_LEVELS) ;
215          POTM_Hx:long_name = "Model interpolated potential temperature" ;
216          POTM_Hx:units = "Degrees Celsius" ;
217          POTM_Hx:_Fillvalue = 99999.f ;
218     int POTM_QC(N_OBS) ;
219          POTM_QC:long_name = "Quality on potential temperature" ;
220          POTM_QC:Conventions = "q where q =[0,9]" ;
221          POTM_QC:_Fillvalue = 0 ;
222     int POTM_QC_FLAGS(N_OBS, N_QCF) ;
223          POTM_QC_FLAGS:long_name = "Quality flags on potential temperature" ;
224          POTM_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
225          POTM_QC_FLAGS:_Fillvalue = 0 ;
226     int POTM_LEVEL_QC(N_OBS, N_LEVELS) ;
227          POTM_LEVEL_QC:long_name = "Quality for each level on potential temperature" ;
228          POTM_LEVEL_QC:Conventions = "q where q =[0,9]" ;
229          POTM_LEVEL_QC:_Fillvalue = 0 ;
230     int POTM_LEVEL_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
231          POTM_LEVEL_QC_FLAGS:long_name = "Quality flags for each level on potential temperature" ;
232          POTM_LEVEL_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
233          POTM_LEVEL_QC_FLAGS:_Fillvalue = 0 ;
234     int POTM_IOBSI(N_OBS) ;
235          POTM_IOBSI:long_name = "ORCA grid search I coordinate" ;
236     int POTM_IOBSJ(N_OBS) ;
237          POTM_IOBSJ:long_name = "ORCA grid search J coordinate" ;
238     int POTM_IOBSK(N_OBS, N_LEVELS) ;
239          POTM_IOBSK:long_name = "ORCA grid search K coordinate" ;
240     char POTM_GRID(STRINGGRID) ;
241          POTM_GRID:long_name = "ORCA grid search grid (T,U,V)" ;
242     float PSAL_OBS(N_OBS, N_LEVELS) ;
243          PSAL_OBS:long_name = "Practical salinity" ;
244          PSAL_OBS:units = "PSU" ;
245          PSAL_OBS:_Fillvalue = 99999.f ;
246     float PSAL_Hx(N_OBS, N_LEVELS) ;
247          PSAL_Hx:long_name = "Model interpolated practical salinity" ;
248          PSAL_Hx:units = "PSU" ;
249          PSAL_Hx:_Fillvalue = 99999.f ;
250     int PSAL_QC(N_OBS) ;
251          PSAL_QC:long_name = "Quality on practical salinity" ;
252          PSAL_QC:Conventions = "q where q =[0,9]" ;
253          PSAL_QC:_Fillvalue = 0 ;
254     int PSAL_QC_FLAGS(N_OBS, N_QCF) ;
255          PSAL_QC_FLAGS:long_name = "Quality flags on practical salinity" ;
256          PSAL_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
257          PSAL_QC_FLAGS:_Fillvalue = 0 ;
258     int PSAL_LEVEL_QC(N_OBS, N_LEVELS) ;
259          PSAL_LEVEL_QC:long_name = "Quality for each level on practical salinity" ;
260          PSAL_LEVEL_QC:Conventions = "q where q =[0,9]" ;
261          PSAL_LEVEL_QC:_Fillvalue = 0 ;
262     int PSAL_LEVEL_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
263          PSAL_LEVEL_QC_FLAGS:long_name = "Quality flags for each level on practical salinity" ;
264          PSAL_LEVEL_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
265          PSAL_LEVEL_QC_FLAGS:_Fillvalue = 0 ;
266     int PSAL_IOBSI(N_OBS) ;
267          PSAL_IOBSI:long_name = "ORCA grid search I coordinate" ;
268     int PSAL_IOBSJ(N_OBS) ;
269          PSAL_IOBSJ:long_name = "ORCA grid search J coordinate" ;
270     int PSAL_IOBSK(N_OBS, N_LEVELS) ;
271          PSAL_IOBSK:long_name = "ORCA grid search K coordinate" ;
272     char PSAL_GRID(STRINGGRID) ;
273          PSAL_GRID:long_name = "ORCA grid search grid (T,U,V)" ;
274     float TEMP(N_OBS, N_LEVELS) ;
275          TEMP:long_name = "Insitu temperature" ;
276          TEMP:units = "Degrees Celsius" ;
277          TEMP:_Fillvalue = 99999.f ;
278
279// global attributes:
280          :title = "NEMO observation operator output" ;
281          :Convention = "NEMO unified observation operator output" ;
282}
283\end{verbatim}
284\end{alltt}
285
286\subsection{Sea level anomaly feedback type observation file header}
287
288\begin{alltt}
289\tiny
290\begin{verbatim}
291netcdf sla_01 {
292dimensions:
293     N_OBS = 41301 ;
294     N_LEVELS = 1 ;
295     N_VARS = 1 ;
296     N_QCF = 2 ;
297     N_ENTRIES = 1 ;
298     N_EXTRA = 1 ;
299     STRINGNAM = 8 ;
300     STRINGGRID = 1 ;
301     STRINGWMO = 8 ;
302     STRINGTYP = 4 ;
303     STRINGJULD = 14 ;
304variables:
305     char VARIABLES(N_VARS, STRINGNAM) ;
306          VARIABLES:long_name = "List of variables in feedback files" ;
307     char ENTRIES(N_ENTRIES, STRINGNAM) ;
308          ENTRIES:long_name = "List of additional entries for each variable in feedback files" ;
309     char EXTRA(N_EXTRA, STRINGNAM) ;
310          EXTRA:long_name = "List of extra variables" ;
311     char STATION_IDENTIFIER(N_OBS, STRINGWMO) ;
312          STATION_IDENTIFIER:long_name = "Station identifier" ;
313     char STATION_TYPE(N_OBS, STRINGTYP) ;
314          STATION_TYPE:long_name = "Code instrument type" ;
315     double LONGITUDE(N_OBS) ;
316          LONGITUDE:long_name = "Longitude" ;
317          LONGITUDE:units = "degrees_east" ;
318          LONGITUDE:_Fillvalue = 99999.f ;
319     double LATITUDE(N_OBS) ;
320          LATITUDE:long_name = "Latitude" ;
321          LATITUDE:units = "degrees_north" ;
322          LATITUDE:_Fillvalue = 99999.f ;
323     double DEPTH(N_OBS, N_LEVELS) ;
324          DEPTH:long_name = "Depth" ;
325          DEPTH:units = "metre" ;
326          DEPTH:_Fillvalue = 99999.f ;
327     int DEPTH_QC(N_OBS, N_LEVELS) ;
328          DEPTH_QC:long_name = "Quality on depth" ;
329          DEPTH_QC:Conventions = "q where q =[0,9]" ;
330          DEPTH_QC:_Fillvalue = 0 ;
331     int DEPTH_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
332          DEPTH_QC_FLAGS:long_name = "Quality flags on depth" ;
333          DEPTH_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
334     double JULD(N_OBS) ;
335          JULD:long_name = "Julian day" ;
336          JULD:units = "days since JULD_REFERENCE" ;
337          JULD:Conventions = "relative julian days with decimal part (as parts of day)" ;
338          JULD:_Fillvalue = 99999.f ;
339     char JULD_REFERENCE(STRINGJULD) ;
340          JULD_REFERENCE:long_name = "Date of reference for julian days" ;
341          JULD_REFERENCE:Conventions = "YYYYMMDDHHMMSS" ;
342     int OBSERVATION_QC(N_OBS) ;
343          OBSERVATION_QC:long_name = "Quality on observation" ;
344          OBSERVATION_QC:Conventions = "q where q =[0,9]" ;
345          OBSERVATION_QC:_Fillvalue = 0 ;
346     int OBSERVATION_QC_FLAGS(N_OBS, N_QCF) ;
347          OBSERVATION_QC_FLAGS:long_name = "Quality flags on observation" ;
348          OBSERVATION_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
349          OBSERVATION_QC_FLAGS:_Fillvalue = 0 ;
350     int POSITION_QC(N_OBS) ;
351          POSITION_QC:long_name = "Quality on position (latitude and longitude)" ;
352          POSITION_QC:Conventions = "q where q =[0,9]" ;
353          POSITION_QC:_Fillvalue = 0 ;
354     int POSITION_QC_FLAGS(N_OBS, N_QCF) ;
355          POSITION_QC_FLAGS:long_name = "Quality flags on position" ;
356          POSITION_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
357          POSITION_QC_FLAGS:_Fillvalue = 0 ;
358     int JULD_QC(N_OBS) ;
359          JULD_QC:long_name = "Quality on date and time" ;
360          JULD_QC:Conventions = "q where q =[0,9]" ;
361          JULD_QC:_Fillvalue = 0 ;
362     int JULD_QC_FLAGS(N_OBS, N_QCF) ;
363          JULD_QC_FLAGS:long_name = "Quality flags on date and time" ;
364          JULD_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
365          JULD_QC_FLAGS:_Fillvalue = 0 ;
366     int ORIGINAL_FILE_INDEX(N_OBS) ;
367          ORIGINAL_FILE_INDEX:long_name = "Index in original data file" ;
368          ORIGINAL_FILE_INDEX:_Fillvalue = -99999 ;
369     float SLA_OBS(N_OBS, N_LEVELS) ;
370          SLA_OBS:long_name = "Sea level anomaly" ;
371          SLA_OBS:units = "metre" ;
372          SLA_OBS:_Fillvalue = 99999.f ;
373     float SLA_Hx(N_OBS, N_LEVELS) ;
374          SLA_Hx:long_name = "Model interpolated sea level anomaly" ;
375          SLA_Hx:units = "metre" ;
376          SLA_Hx:_Fillvalue = 99999.f ;
377     int SLA_QC(N_OBS) ;
378          SLA_QC:long_name = "Quality on sea level anomaly" ;
379          SLA_QC:Conventions = "q where q =[0,9]" ;
380          SLA_QC:_Fillvalue = 0 ;
381     int SLA_QC_FLAGS(N_OBS, N_QCF) ;
382          SLA_QC_FLAGS:long_name = "Quality flags on sea level anomaly" ;
383          SLA_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
384          SLA_QC_FLAGS:_Fillvalue = 0 ;
385     int SLA_LEVEL_QC(N_OBS, N_LEVELS) ;
386          SLA_LEVEL_QC:long_name = "Quality for each level on sea level anomaly" ;
387          SLA_LEVEL_QC:Conventions = "q where q =[0,9]" ;
388          SLA_LEVEL_QC:_Fillvalue = 0 ;
389     int SLA_LEVEL_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
390          SLA_LEVEL_QC_FLAGS:long_name = "Quality flags for each level on sea level anomaly" ;
391          SLA_LEVEL_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
392          SLA_LEVEL_QC_FLAGS:_Fillvalue = 0 ;
393     int SLA_IOBSI(N_OBS) ;
394          SLA_IOBSI:long_name = "ORCA grid search I coordinate" ;
395     int SLA_IOBSJ(N_OBS) ;
396          SLA_IOBSJ:long_name = "ORCA grid search J coordinate" ;
397     int SLA_IOBSK(N_OBS, N_LEVELS) ;
398          SLA_IOBSK:long_name = "ORCA grid search K coordinate" ;
399     char SLA_GRID(STRINGGRID) ;
400          SLA_GRID:long_name = "ORCA grid search grid (T,U,V)" ;
401     float MDT(N_OBS, N_LEVELS) ;
402          MDT:long_name = "Mean Dynamic Topography" ;
403          MDT:units = "metre" ;
404          MDT:_Fillvalue = 99999.f ;
405
406// global attributes:
407          :title = "NEMO observation operator output" ;
408          :Convention = "NEMO unified observation operator output" ;
409}
410\end{verbatim}
411\end{alltt}
412
413The mean dynamic
414topography (MDT) must be provided in a separate file defined on the model grid
415 called {\it slaReferenceLevel.nc}. The MDT is required in
416order to produce the model equivalent sea level anomaly from the model sea
417surface height. Below is an example header for this file (on the ORCA025 grid).
418
419\begin{alltt}
420\tiny
421\begin{verbatim}
422dimensions:
423        x = 1442 ;
424        y = 1021 ;
425variables:
426        float nav_lon(y, x) ;
427                nav_lon:units = "degrees_east" ;
428        float nav_lat(y, x) ;
429                nav_lat:units = "degrees_north" ;
430        float sossheig(y, x) ;
431                sossheig:_FillValue = -1.e+30f ;
432                sossheig:coordinates = "nav_lon nav_lat" ;
433                sossheig:long_name = "Mean Dynamic Topography" ;
434                sossheig:units = "metres" ;
435                sossheig:grid = "orca025T" ;
436\end{verbatim}
437\end{alltt}
438
439\subsection{Sea surface temperature feedback type observation file header}
440
441\begin{alltt}
442\tiny
443\begin{verbatim}
444netcdf sst_01 {
445dimensions:
446     N_OBS = 33099 ;
447     N_LEVELS = 1 ;
448     N_VARS = 1 ;
449     N_QCF = 2 ;
450     N_ENTRIES = 1 ;
451     STRINGNAM = 8 ;
452     STRINGGRID = 1 ;
453     STRINGWMO = 8 ;
454     STRINGTYP = 4 ;
455     STRINGJULD = 14 ;
456variables:
457     char VARIABLES(N_VARS, STRINGNAM) ;
458          VARIABLES:long_name = "List of variables in feedback files" ;
459     char ENTRIES(N_ENTRIES, STRINGNAM) ;
460          ENTRIES:long_name = "List of additional entries for each variable in feedback files" ;
461     char STATION_IDENTIFIER(N_OBS, STRINGWMO) ;
462          STATION_IDENTIFIER:long_name = "Station identifier" ;
463     char STATION_TYPE(N_OBS, STRINGTYP) ;
464          STATION_TYPE:long_name = "Code instrument type" ;
465     double LONGITUDE(N_OBS) ;
466          LONGITUDE:long_name = "Longitude" ;
467          LONGITUDE:units = "degrees_east" ;
468          LONGITUDE:_Fillvalue = 99999.f ;
469     double LATITUDE(N_OBS) ;
470          LATITUDE:long_name = "Latitude" ;
471          LATITUDE:units = "degrees_north" ;
472          LATITUDE:_Fillvalue = 99999.f ;
473     double DEPTH(N_OBS, N_LEVELS) ;
474          DEPTH:long_name = "Depth" ;
475          DEPTH:units = "metre" ;
476          DEPTH:_Fillvalue = 99999.f ;
477     int DEPTH_QC(N_OBS, N_LEVELS) ;
478          DEPTH_QC:long_name = "Quality on depth" ;
479          DEPTH_QC:Conventions = "q where q =[0,9]" ;
480          DEPTH_QC:_Fillvalue = 0 ;
481     int DEPTH_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
482          DEPTH_QC_FLAGS:long_name = "Quality flags on depth" ;
483          DEPTH_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
484     double JULD(N_OBS) ;
485          JULD:long_name = "Julian day" ;
486          JULD:units = "days since JULD_REFERENCE" ;
487          JULD:Conventions = "relative julian days with decimal part (as parts of day)" ;
488          JULD:_Fillvalue = 99999.f ;
489     char JULD_REFERENCE(STRINGJULD) ;
490          JULD_REFERENCE:long_name = "Date of reference for julian days" ;
491          JULD_REFERENCE:Conventions = "YYYYMMDDHHMMSS" ;
492     int OBSERVATION_QC(N_OBS) ;
493          OBSERVATION_QC:long_name = "Quality on observation" ;
494          OBSERVATION_QC:Conventions = "q where q =[0,9]" ;
495          OBSERVATION_QC:_Fillvalue = 0 ;
496     int OBSERVATION_QC_FLAGS(N_OBS, N_QCF) ;
497          OBSERVATION_QC_FLAGS:long_name = "Quality flags on observation" ;
498          OBSERVATION_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
499          OBSERVATION_QC_FLAGS:_Fillvalue = 0 ;
500     int POSITION_QC(N_OBS) ;
501          POSITION_QC:long_name = "Quality on position (latitude and longitude)" ;
502          POSITION_QC:Conventions = "q where q =[0,9]" ;
503          POSITION_QC:_Fillvalue = 0 ;
504     int POSITION_QC_FLAGS(N_OBS, N_QCF) ;
505          POSITION_QC_FLAGS:long_name = "Quality flags on position" ;
506          POSITION_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
507          POSITION_QC_FLAGS:_Fillvalue = 0 ;
508     int JULD_QC(N_OBS) ;
509          JULD_QC:long_name = "Quality on date and time" ;
510          JULD_QC:Conventions = "q where q =[0,9]" ;
511          JULD_QC:_Fillvalue = 0 ;
512     int JULD_QC_FLAGS(N_OBS, N_QCF) ;
513          JULD_QC_FLAGS:long_name = "Quality flags on date and time" ;
514          JULD_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
515          JULD_QC_FLAGS:_Fillvalue = 0 ;
516     int ORIGINAL_FILE_INDEX(N_OBS) ;
517          ORIGINAL_FILE_INDEX:long_name = "Index in original data file" ;
518          ORIGINAL_FILE_INDEX:_Fillvalue = -99999 ;
519     float SST_OBS(N_OBS, N_LEVELS) ;
520          SST_OBS:long_name = "Sea surface temperature" ;
521          SST_OBS:units = "Degree centigrade" ;
522          SST_OBS:_Fillvalue = 99999.f ;
523     float SST_Hx(N_OBS, N_LEVELS) ;
524          SST_Hx:long_name = "Model interpolated sea surface temperature" ;
525          SST_Hx:units = "Degree centigrade" ;
526          SST_Hx:_Fillvalue = 99999.f ;
527     int SST_QC(N_OBS) ;
528          SST_QC:long_name = "Quality on sea surface temperature" ;
529          SST_QC:Conventions = "q where q =[0,9]" ;
530          SST_QC:_Fillvalue = 0 ;
531     int SST_QC_FLAGS(N_OBS, N_QCF) ;
532          SST_QC_FLAGS:long_name = "Quality flags on sea surface temperature" ;
533          SST_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
534          SST_QC_FLAGS:_Fillvalue = 0 ;
535     int SST_LEVEL_QC(N_OBS, N_LEVELS) ;
536          SST_LEVEL_QC:long_name = "Quality for each level on sea surface temperature" ;
537          SST_LEVEL_QC:Conventions = "q where q =[0,9]" ;
538          SST_LEVEL_QC:_Fillvalue = 0 ;
539     int SST_LEVEL_QC_FLAGS(N_OBS, N_LEVELS, N_QCF) ;
540          SST_LEVEL_QC_FLAGS:long_name = "Quality flags for each level on sea surface temperature" ;
541          SST_LEVEL_QC_FLAGS:Conventions = "NEMOVAR flag conventions" ;
542          SST_LEVEL_QC_FLAGS:_Fillvalue = 0 ;
543     int SST_IOBSI(N_OBS) ;
544          SST_IOBSI:long_name = "ORCA grid search I coordinate" ;
545     int SST_IOBSJ(N_OBS) ;
546          SST_IOBSJ:long_name = "ORCA grid search J coordinate" ;
547     int SST_IOBSK(N_OBS, N_LEVELS) ;
548          SST_IOBSK:long_name = "ORCA grid search K coordinate" ;
549     char SST_GRID(STRINGGRID) ;
550          SST_GRID:long_name = "ORCA grid search grid (T,U,V)" ;
551
552// global attributes:
553          :title = "NEMO observation operator output" ;
554          :Convention = "NEMO unified observation operator output" ;
555}
556\end{verbatim}
557\end{alltt}
558
559\section{Theoretical details}
560\label{OBS_theory}
561
562\subsection{Horizontal interpolation methods}
563
564Consider an observation point ${\rm P}$ with
565with longitude and latitude $({\lambda_{}}_{\rm P}, \phi_{\rm P})$ and the
566four nearest neighbouring model grid points ${\rm A}$, ${\rm B}$, ${\rm C}$ 
567and ${\rm D}$ with longitude and latitude ($\lambda_{\rm A}$, $\phi_{\rm A}$),
568($\lambda_{\rm B}$, $\phi_{\rm B}$) etc.
569All horizontal interpolation methods implemented in NEMO
570estimate the value of a model variable $x$ at point $P$ as
571a weighted linear combination of the values of the model
572variables at the grid points ${\rm A}$, ${\rm B}$ etc.:
573\begin{eqnarray}
574{x_{}}_{\rm P} & \hspace{-2mm} = \hspace{-2mm} & 
575\frac{1}{w} \left( {w_{}}_{\rm A} {x_{}}_{\rm A} +
576                   {w_{}}_{\rm B} {x_{}}_{\rm B} +
577                   {w_{}}_{\rm C} {x_{}}_{\rm C} +
578                   {w_{}}_{\rm D} {x_{}}_{\rm D} \right)
579\end{eqnarray}
580where ${w_{}}_{\rm A}$, ${w_{}}_{\rm B}$ etc. are the respective weights for the
581model field at points ${\rm A}$, ${\rm B}$ etc., and
582$w = {w_{}}_{\rm A} + {w_{}}_{\rm B} + {w_{}}_{\rm C} + {w_{}}_{\rm D}$.
583
584Four different possibilities are available for computing the weights.
585
586\begin{enumerate}
587
588\item[1.] {\bf Great-Circle distance-weighted interpolation.} The weights
589  are computed as a function of the great-circle distance $s(P, \cdot)$ 
590  between $P$ and the model grid points $A$, $B$ etc. For example,
591  the weight given to the field ${x_{}}_{\rm A}$ is specified as the
592  product of the distances from ${\rm P}$ to the other points:
593  \begin{eqnarray}
594  {w_{}}_{\rm A} = s({\rm P}, {\rm B}) \, s({\rm P}, {\rm C}) \, s({\rm P}, {\rm D})
595  \nonumber
596  \end{eqnarray}
597  where
598  \begin{eqnarray}
599   s\left ({\rm P}, {\rm M} \right )
600     & \hspace{-2mm} = \hspace{-2mm} & 
601      \cos^{-1} \! \left\{ 
602               \sin {\phi_{}}_{\rm P} \sin {\phi_{}}_{\rm M}
603             + \cos {\phi_{}}_{\rm P} \cos {\phi_{}}_{\rm M} 
604               \cos ({\lambda_{}}_{\rm M} - {\lambda_{}}_{\rm P})
605                   \right\}
606   \end{eqnarray}
607   and $M$ corresponds to $B$, $C$ or $D$.
608   A more stable form of the great-circle distance formula for
609   small distances ($x$ near 1) involves the arcsine function
610   ($e.g.$ see p.~101 of \citet{Daley_Barker_Bk01}:
611   \begin{eqnarray}
612   s\left( {\rm P}, {\rm M} \right)
613     & \hspace{-2mm} = \hspace{-2mm} & 
614      \sin^{-1} \! \left\{ \sqrt{ 1 - x^2 } \right\}
615   \nonumber
616   \end{eqnarray}
617   where
618   \begin{eqnarray}
619    x & \hspace{-2mm} = \hspace{-2mm} & 
620      {a_{}}_{\rm M} {a_{}}_{\rm P} + {b_{}}_{\rm M} {b_{}}_{\rm P} + {c_{}}_{\rm M} {c_{}}_{\rm P}
621   \nonumber
622   \end{eqnarray}
623   and
624   \begin{eqnarray}
625      {a_{}}_{\rm M} & \hspace{-2mm} = \hspace{-2mm} & \sin {\phi_{}}_{\rm M},
626      \nonumber \\
627      {a_{}}_{\rm P} & \hspace{-2mm} = \hspace{-2mm} & \sin {\phi_{}}_{\rm P},
628      \nonumber \\
629      {b_{}}_{\rm M} & \hspace{-2mm} = \hspace{-2mm} & \cos {\phi_{}}_{\rm M} \cos {\phi_{}}_{\rm M},
630      \nonumber \\
631      {b_{}}_{\rm P} & \hspace{-2mm} = \hspace{-2mm} & \cos {\phi_{}}_{\rm P} \cos {\phi_{}}_{\rm P},
632      \nonumber \\
633      {c_{}}_{\rm M} & \hspace{-2mm} = \hspace{-2mm} & \cos {\phi_{}}_{\rm M} \sin {\phi_{}}_{\rm M},
634      \nonumber \\
635      {c_{}}_{\rm P} & \hspace{-2mm} = \hspace{-2mm} & \cos {\phi_{}}_{\rm P} \sin {\phi_{}}_{\rm P}.
636      \nonumber
637   \nonumber
638  \end{eqnarray}
639
640\item[2.] {\bf Great-Circle distance-weighted interpolation with small angle
641  approximation.} Similar to the previous interpolation but with the
642  distance $s$ computed as
643  \begin{eqnarray}
644    s\left( {\rm P}, {\rm M} \right)
645     & \hspace{-2mm} = \hspace{-2mm} & 
646      \sqrt{ \left( {\phi_{}}_{\rm M} - {\phi_{}}_{\rm P} \right)^{2} 
647      + \left( {\lambda_{}}_{\rm M} - {\lambda_{}}_{\rm P} \right)^{2}
648        \cos^{2} {\phi_{}}_{\rm M} }
649  \end{eqnarray}
650  where $M$ corresponds to $A$, $B$, $C$ or $D$.
651
652\item[3.] {\bf Bilinear interpolation for a regular spaced grid.} The
653  interpolation is split into two 1D interpolations in the longitude
654  and latitude directions, respectively.
655
656\item[4.] {\bf Bilinear remapping interpolation for a general grid.} An
657  iterative scheme that involves first mapping a quadrilateral cell
658  into a cell with coordinates (0,0), (1,0), (0,1) and (1,1). This
659  method is based on the SCRIP interpolation package \citep{Jones_1998}.
660 
661\end{enumerate}
662
663\subsection{Grid search}
664
665For many grids used by the NEMO model, such as the ORCA family,
666the horizontal grid coordinates $i$ and $j$ are not simple functions
667of latitude and longitude. Therefore, it is not always straightforward
668to determine the grid points surrounding any given observational position.
669Before the interpolation can be performed, a search
670algorithm is then required to determine the corner points of
671the quadrilateral cell in which the observation is located.
672This is the most difficult and time consuming part of the
6732D interpolation procedure.
674A robust test for determining if an observation falls
675within a given quadrilateral cell is as follows. Let
676${\rm P}({\lambda_{}}_{\rm P} ,{\phi_{}}_{\rm P} )$ denote the observation point,
677and let ${\rm A}({\lambda_{}}_{\rm A} ,{\phi_{}}_{\rm A} )$,
678${\rm B}({\lambda_{}}_{\rm B} ,{\phi_{}}_{\rm B} )$,
679${\rm C}({\lambda_{}}_{\rm C} ,{\phi_{}}_{\rm C} )$ 
680and
681${\rm D}({\lambda_{}}_{\rm D} ,{\phi_{}}_{\rm D} )$ denote
682the bottom left, bottom right, top left and top right
683corner points of the cell, respectively.
684To determine if P is inside
685the cell, we verify that the cross-products
686\begin{eqnarray}
687\begin{array}{lllll}
688{{\bf r}_{}}_{\rm PA} \times {{\bf r}_{}}_{\rm PC}
689& = & [({\lambda_{}}_{\rm A}\; -\; {\lambda_{}}_{\rm P} )
690      ({\phi_{}}_{\rm C}   \; -\; {\phi_{}}_{\rm P} )
691    - ({\lambda_{}}_{\rm C}\; -\; {\lambda_{}}_{\rm P} )
692      ({\phi_{}}_{\rm A}   \; -\; {\phi_{}}_{\rm P} )] \; \widehat{\bf k} \\
693{{\bf r}_{}}_{\rm PB} \times {{\bf r}_{}}_{\rm PA}
694& = & [({\lambda_{}}_{\rm B}\; -\; {\lambda_{}}_{\rm P} )
695      ({\phi_{}}_{\rm A}   \; -\; {\phi_{}}_{\rm P} )
696    - ({\lambda_{}}_{\rm A}\; -\; {\lambda_{}}_{\rm P} )
697      ({\phi_{}}_{\rm B}   \; -\; {\phi_{}}_{\rm P} )] \; \widehat{\bf k} \\
698{{\bf r}_{}}_{\rm PC} \times {{\bf r}_{}}_{\rm PD}
699& = & [({\lambda_{}}_{\rm C}\; -\; {\lambda_{}}_{\rm P} )
700      ({\phi_{}}_{\rm D}   \; -\; {\phi_{}}_{\rm P} )
701    - ({\lambda_{}}_{\rm D}\; -\; {\lambda_{}}_{\rm P} )
702      ({\phi_{}}_{\rm C}   \; -\; {\phi_{}}_{\rm P} )] \; \widehat{\bf k} \\
703{{\bf r}_{}}_{\rm PD} \times {{\bf r}_{}}_{\rm PB}
704& = & [({\lambda_{}}_{\rm D}\; -\; {\lambda_{}}_{\rm P} )
705      ({\phi_{}}_{\rm B}   \; -\; {\phi_{}}_{\rm P} )
706    - ({\lambda_{}}_{\rm B}\; -\; {\lambda_{}}_{\rm P} )
707      ({\phi_{}}_{\rm D}  \;  - \; {\phi_{}}_{\rm P} )] \; \widehat{\bf k} \\
708\end{array}
709\label{eq:cross}
710\end{eqnarray}
711point in the opposite direction to the unit normal
712$\widehat{\bf k}$ (i.e., that the coefficients of
713$\widehat{\bf k}$ are negative),
714where ${{\bf r}_{}}_{\rm PA}$, ${{\bf r}_{}}_{\rm PB}$,
715etc. correspond to the vectors between points P and A,
716P and B, etc.. The method used is
717similar to the method used in
718the SCRIP interpolation package \citep{Jones_1998}.
719
720In order to speed up the grid search, there is the possibility to construct
721a lookup table for a user specified resolution. This lookup
722table contains the lower and upper bounds on the $i$ and $j$ indices
723to be searched for on a regular grid. For each observation position,
724the closest point on the regular grid of this position is computed and
725the $i$ and $j$ ranges of this point searched to determine the precise
726four points surrounding the observation.
727
728\subsection{Parallel aspects of horizontal interpolation}
729\label{OBS_parallel}
730
731For horizontal interpolation, there is the basic problem that the
732observations are unevenly distributed on the globe. In numerical
733models, it is common to divide the model grid into subgrids (or
734domains) where each subgrid is executed on a single processing element
735with explicit message passing for exchange of information along the
736domain boundaries when running on a massively parallel processor (MPP)
737system. This approach is used by \NEMO.
738
739For observations there is no natural distribution since the
740observations are not equally distributed on the globe.
741Two options have been made available: 1) geographical distribution;
742and 2) round-robin.
743
744\subsubsection{Geographical distribution of observations among processors}
745
746%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
747\begin{figure}      \begin{center}
748\includegraphics[width=10cm,height=12cm,angle=-90.]{Fig_ASM_obsdist_local}
749\caption{      \label{fig:obslocal}
750Example of the distribution of observations with the geographical distribution of observational data.} 
751\end{center}      \end{figure}
752%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
753
754This is the simplest option in which the observations are distributed according
755to the domain of the grid-point parallelization. Figure~\ref{fig:obslocal}
756shows an example of the distribution of the {\em in situ} data on processors
757with a different colour for each observation
758on a given processor for a 4 $\times$ 2 decomposition with ORCA2.
759The grid-point domain decomposition is clearly visible on the plot.
760
761The advantage of this approach is that all
762information needed for horizontal interpolation is available without
763any MPP communication. Of course, this is under the assumption that
764we are only using a $2 \times 2$ grid-point stencil for the interpolation
765(e.g., bilinear interpolation). For higher order interpolation schemes this
766is no longer valid. A disadvantage with the above scheme is that the number of
767observations on each processor can be very different. If the cost of
768the actual interpolation is expensive relative to the communication of
769data needed for interpolation, this could lead to load imbalance.
770
771\subsubsection{Round-robin distribution of observations among processors}
772
773%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
774\begin{figure}     \begin{center}
775\includegraphics[width=10cm,height=12cm,angle=-90.]{Fig_ASM_obsdist_global}
776\caption{      \label{fig:obsglobal}
777Example of the distribution of observations with the round-robin distribution of observational data.}
778\end{center}     \end{figure}
779%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
780
781An alternative approach is to distribute the observations equally
782among processors and use message passing in order to retrieve
783the stencil for interpolation. The simplest distribution of the observations
784is to distribute them using a round-robin scheme. Figure~\ref{fig:obsglobal}
785shows the distribution of the {\em in situ} data on processors for the
786round-robin distribution of observations with a different colour for
787each observation on a given processor for a 4 $\times$ 2 decomposition
788with ORCA2 for the same input data as in Fig.~\ref{fig:obslocal}.
789The observations are now clearly randomly distributed on the globe.
790In order to be able to perform horizontal interpolation in this case,
791a subroutine has been developed that retrieves any grid points in the
792global space.
793
794\subsection{Vertical interpolation operator}
795
796Vertical interpolation is achieved using either a cubic spline or
797linear interpolation. For the cubic spline, the top and
798bottom boundary conditions for the second derivative of the
799interpolating polynomial in the spline are set to zero.
800At the bottom boundary, this is done using the land-ocean mask.
801
802\newpage
803
804% ================================================================
805% Offline observation operator documentation
806% ================================================================
807
808%\usepackage{framed}
809
810\section{Offline observation operator}
811\label{OBS_ooo}
812
813\subsection{Concept}
814
815The obs oper maps model variables to observation space. It is possible to apply this mapping
816without running the model. The software which performs this functionality is known as the
817\textbf{offline obs oper}. The obs oper is divided into three stages. An initialisation phase,
818an interpolation phase and an output phase. The implementation of which is outlined in the
819previous sections. During the interpolation phase the offline obs oper populates the model
820arrays by reading saved model fields from disk.
821
822There are two ways of exploiting this offline capacity. The first is to mimic the behaviour of
823the online system by supplying model fields at regular intervals between the start and the end
824of the run. This approach results in a single model counterpart per observation. This kind of
825usage produces feedback files the same file format as the online obs oper.
826The second is to take advantage of the offline setting in which multiple model counterparts can
827be calculated per observation. In this case it is possible to consider all forecasts verifying
828at the same time. By forecast, I mean any method which produces an estimate of physical reality
829which is not an observed value. In the case of class 4 files this means forecasts, analyses, persisted
830analyses and climatological values verifying at the same time. Although the class 4 file format
831doesn't account for multiple ensemble members or multiple experiments per observation, it is possible
832to include these components in the same or multiple files.
833
834%--------------------------------------------------------------------------------------------------------
835% offline_oper.exe
836%--------------------------------------------------------------------------------------------------------
837
838\subsection{Using the offline observation operator}
839
840\subsubsection{Building}
841
842In addition to \emph{OPA\_SRC} the offline obs oper requires the inclusion
843of the \emph{OOO\_SRC} directory. \emph{OOO\_SRC} contains a replacement \textbf{nemo.f90} and
844\textbf{nemogcm.F90} which overwrites the resultant \textbf{nemo.exe}. This is the approach taken
845by \emph{SAS\_SRC} and \emph{OFF\_SRC}.
846
847%--------------------------------------------------------------------------------------------------------
848% Running
849%--------------------------------------------------------------------------------------------------------
850\subsubsection{Running}
851
852The simplest way to use the executable is to edit and append the \textbf{ooo.nml} namelist to
853a full NEMO namelist and then to run the executable as if it were nemo.exe.
854
855\subsubsection{Quick script}
856
857A useful Python utility to control the namelist options can be found in \textbf{OBSTOOLS/OOO}. The
858functions which locate model fields and observation files can be manually specified. The package
859can be installed by appropriate use of the included setup.py script.
860
861Documentation can be auto-generated by Sphinx by running \emph{make html} in the \textbf{doc} directory.
862
863%--------------------------------------------------------------------------------------------------------
864% Configuration section
865%--------------------------------------------------------------------------------------------------------
866\subsection{Configuring the offline observation operator}
867The observation files and settings understood by \textbf{namobs} have been outlined in the online
868obs oper section. In addition there are two further namelists wich control the operation of the offline
869obs oper. \textbf{namooo} which controls the input model fields and \textbf{namcl4} which controls the
870production of class 4 files.
871
872\subsubsection{Single field}
873
874In offline mode model arrays are populated at appropriate time steps via input files.
875At present, \textbf{tsn} and \textbf{sshn} are populated by the default read routines.
876These routines will be expanded upon in future versions to allow the specification of any
877model variable. As such, input files must be global versions of the model domain with
878\textbf{votemper}, \textbf{vosaline} and optionally \textbf{sshn} present.
879
880For each field read there must be an entry in the \textbf{namooo} namelist specifying the
881name of the file to read and the index along the \emph{time\_counter}. For example, to
882read the second time counter from a single file the namelist would be.
883
884\begin{alltt}
885\tiny
886\begin{verbatim} 
887!----------------------------------------------------------------------
888!       namooo Offline obs_oper namelist
889!----------------------------------------------------------------------
890!   ooo_files    specifies the files containing the model counterpart
891!   nn_ooo_idx   specifies the time_counter index within the model file
892&namooo
893   ooo_files = "foo.nc"
894   nn_ooo_idx = 2
895/
896\end{verbatim} 
897\end{alltt}
898
899\subsubsection{Multiple fields per run}
900
901Model field iteration is controlled via \textbf{nn\_ooo\_freq} which specifies
902the number of model steps at which the next field gets read. For example, if
90312 hourly fields are to be interpolated in a setup where 288 steps equals 24 hours.
904
905\begin{alltt}
906\tiny
907\begin{verbatim} 
908!----------------------------------------------------------------------
909!       namooo Offline obs_oper namelist
910!----------------------------------------------------------------------
911!   ooo_files    specifies the files containing the model counterpart
912!   nn_ooo_idx   specifies the time_counter index within the model file
913!   nn_ooo_freq  specifies number of time steps between read operations
914&namooo
915   ooo_files = "foo.nc" "foo.nc"
916   nn_ooo_idx = 1 2
917   nn_ooo_freq = 144
918/
919\end{verbatim} 
920\end{alltt}
921
922The above namelist will result in feedback files whose first 12 hours contain
923the first field of foo.nc and the second 12 hours contain the second field.
924
925%\begin{framed}
926\textbf{Note} Missing files can be denoted as "nofile".
927%\end{framed}
928
929It is easy to see how a collection of fields taken fron a number of files
930at different indices can be combined at a particular frequency in time to
931generate a pseudo model evolution. As long as all that is needed is a single
932model counterpart at a regular interval then namooo is all that needs to
933be edited. However, a far more interesting approach can be taken in which
934multiple forecasts, analyses, persisted analyses and climatologies are
935considered against the same set of observations. For this a slightly more
936complicated approach is needed. It is referred to as \emph{Class 4} since
937it is the fourth metric defined by the GODAE intercomparison project.
938
939%--------------------------------------------------------------------------------------------------------
940% Class 4 file section
941%--------------------------------------------------------------------------------------------------------
942\subsubsection{Multiple model counterparts per observation a.k.a Class 4}
943
944A generalisation of feedback files to allow multiple model components per observation. For a single
945observation, as well as previous forecasts verifying at the same time there are also analyses, persisted
946analyses and climatologies.
947
948
949The above namelist performs two basic functions. It organises the fields
950given in \textbf{namooo} into groups so that observations can be matched
951up multiple times. It also controls the metadata and the output variable
952of the class 4 file when a write routine is called.
953
954%\begin{framed}
955\textbf{Note: ln\_cl4} must be set to \emph{.TRUE.} in \textbf{namobs} 
956to use class 4 outputs.
957%\end{framed}
958
959\subsubsection{Class 4 naming convention}
960
961The standard class 4 file naming convention is as follows.
962
963\noindent
964\linebreak
965\textbf{\$\{prefix\}\_\$\{yyyymmdd\}\_\$\{sys\}\_\$\{cfg\}\_\$\{vn\}\_\$\{kind\}\_\$\{nproc\}.nc}
966
967\noindent
968\linebreak
969Much of the namelist is devoted to specifying this convention. The
970following namelist settings control the elements of the output
971file names. Each should be specified as a single string of character data.
972
973\begin{description}
974\item[cl4\_prefix]
975Prefix for class 4 files e.g. class4
976\item[cl4\_date]
977YYYYMMDD validity date
978\item[cl4\_sys]
979The name of the class 4 model system e.g. FOAM
980\item[cl4\_cfg]
981The name of the class 4 model configuration e.g. orca025
982\item[cl4\_vn]
983The name of the class 4 model version e.g. 12.0
984\end{description}
985
986\noindent
987The kind is specified by the observation type internally to the obs oper. The processor
988number is specified internally in NEMO.
989
990\subsubsection{Class 4 file global attributes}
991
992Global attributes necessary to fulfill the class 4 file definition. These
993are also useful pieces of information when collaborating with external
994partners.
995
996\begin{description}
997\item[cl4\_contact]
998Contact email for class 4 files.
999\item[cl4\_inst]
1000The name of the producers institution.
1001\item[cl4\_cfg]
1002The name of the class 4 model configuration e.g. orca025
1003\item[cl4\_vn]
1004The name of the class 4 model version e.g. 12.0
1005\end{description}
1006
1007\noindent
1008The obs\_type,
1009creation date and validity time are specified internally to the obs oper.
1010
1011\subsubsection{Class 4 model counterpart configuration}
1012
1013As seen previously it is possible to perform a single sweep of the
1014obs oper and specify a collection of model fields equally spaced
1015along that sweep. In the class 4 case the single sweep is replaced
1016with multiple sweeps and a certain ammount of book keeping is
1017needed to ensure each model counterpart makes its way to the
1018correct piece of memory in the output files.
1019
1020\noindent
1021\linebreak
1022In terms of book keeping, the offline obs oper needs to know how many
1023full sweeps need to be performed. This is specified via the
1024\textbf{cl4\_match\_len} variable and is the total number of model
1025counterparts per observation. For example, a 3 forecasts plus 3 persistence
1026fields plus an analysis field would be 7 counterparts per observation.
1027
1028\begin{alltt}
1029\tiny
1030\begin{verbatim}
1031   cl4_match_len = 7
1032\end{verbatim}
1033\end{alltt}
1034
1035Then to correctly allocate a class 4 file the forecast axis must be defined. This
1036is controlled via \textbf{cl4\_fcst\_len}, which in out above example would be 3.
1037
1038\begin{alltt}
1039\tiny
1040\begin{verbatim}
1041   cl4_fcst_len = 3
1042\end{verbatim}
1043\end{alltt}
1044
1045Then for each model field it is necessary to designate what class 4 variable and
1046index along the forecast dimension the model counterpart should be stored in the
1047output file. As well as a value for that lead time in hours, this will be useful
1048when interpreting the data afterwards.
1049
1050\begin{alltt}
1051\tiny
1052\begin{verbatim}
1053   cl4_vars = "forecast" "forecast" "forecast" "persistence" "persistence"
1054              "persistence" "best_estimate"
1055   cl4_fcst_idx = 1 2 3 1 2 3 1
1056   cl4_leadtime = 12 36 60
1057\end{verbatim}
1058\end{alltt}
1059
1060In terms of files and indices of fields inside each file the class 4 approach
1061makes use of the \textbf{namooo} namelist. If our fields are in separate files
1062with a single field per file our example inputs will be specified.
1063
1064\begin{alltt}
1065\tiny
1066\begin{verbatim}
1067   ooo_files = "F.1.nc" "F.2.nc" "F.3.nc" "P.1.nc" "P.2.nc" "P.3.nc" "A.1.nc"
1068   nn_ooo_idx = 1 1 1 1 1 1 1
1069\end{verbatim}
1070\end{alltt}
1071
1072When we combine all of the naming conventions, global attributes and i/o instructions
1073the class 4 namelist becomes.
1074
1075\begin{alltt}
1076\tiny
1077\begin{verbatim}
1078!----------------------------------------------------------------------
1079!       namooo Offline obs_oper namelist
1080!----------------------------------------------------------------------
1081!   ooo_files    specifies the files containing the model counterpart
1082!   nn_ooo_idx   specifies the time_counter index within the model file
1083!   nn_ooo_freq  specifies number of time steps between read operations
1084&namooo
1085   ooo_files = "F.1.nc" "F.2.nc" "F.3.nc" "P.1.nc" "P.2.nc" "P.3.nc" "A.1.nc"
1086   nn_ooo_idx = 1 1 1 1 1 1 1
1087/
1088!----------------------------------------------------------------------
1089!       namcl4 Offline obs_oper class 4 namelist
1090!----------------------------------------------------------------------
1091!
1092!  Naming convention
1093!  -----------------
1094!  cl4_prefix    specifies the output file prefix
1095!  cl4_date      specifies the output file validity date
1096!  cl4_sys       specifies the model counterpart system
1097!  cl4_cfg       specifies the model counterpart configuration
1098!  cl4_vn        specifies the model counterpart version
1099!  cl4_inst      specifies the model counterpart institute
1100!  cl4_contact   specifies the file producers contact details
1101!
1102!  I/O specification
1103!  -----------------
1104!  cl4_vars      specifies the names of the output file netcdf variable
1105!  cl4_fcst_idx  specifies output file forecast index
1106!  cl4_fcst_len  specifies forecast axis length
1107!  cl4_match_len specifies number of unique matches per observation
1108!  cl4_leadtime  specifies the forecast axis lead time
1109!
1110&namcl4
1111   cl4_match_len = 7
1112   cl4_fcst_len = 3
1113   cl4_fcst_idx = 1 2 3 1 2 3 1
1114   cl4_vars = "forecast" "forecast" "forecast" "persistence" "persistence"
1115              "persistence" "best_estimate"
1116   cl4_leadtime = 12 36 60
1117   cl4_prefix = "class4"
1118   cl4_date = "20130101"
1119   cl4_vn = "12.0"
1120   cl4_sys = "FOAM"
1121   cl4_cfg = "AMM7"
1122   cl4_contact = "example@example.com"
1123   cl4_inst = "UK Met Office"
1124/
1125\end{verbatim}
1126\end{alltt}
1127
1128\subsubsection{Climatology interpolation}
1129
1130The climatological counterpart is generated at the start of the run by restarting
1131the model from climatology through appropriate use of \textbf{namtsd}. To override
1132the offline observation operator read routine and to take advantage of the restart
1133settings, specify the first entry in \textbf{cl4\_vars} as "climatology". This will then
1134pipe the restart from climatology into the output class 4 file. As in every other
1135class 4 matchup the input file, input index and output index must be specified.
1136These can be replaced with dummy data since they are not used but they must be
1137present to cycle through the matchups correctly.
1138
1139\subsection{Advanced usage}
1140
1141In certain cases it may be desirable to include both multiple model fields per
1142observation window with multiple match ups per observation. This can be achieved
1143by specifying \textbf{nn\_ooo\_freq} as well as the class 4 settings. Care must
1144be taken in generating the ooo\_files list such that the files are arranged into
1145consecutive blocks of single match ups. For example, 2 forecast fields
1146of 12 hourly data would result in 4 separate read operations but only 2 write
1147operations, 1 per forecast.
1148
1149\begin{alltt}
1150\tiny
1151\begin{verbatim}
1152   ooo_files = "F1.nc" "F1.nc" "F2.nc" "F2.nc"
1153...
1154   cl4_fcst_idx = 1 2
1155\end{verbatim}
1156\end{alltt}
1157
1158The above notation reveals the internal split between match up iterators and file
1159iterators. This technique has not been used before so experimentation is needed
1160before results can be trusted.
1161
1162
1163
1164
1165\newpage
1166
1167\section{Observation Utilities}
1168\label{OBS_obsutils}
1169
1170Some tools for viewing and processing of observation and feedback files are provided in the
1171NEMO repository for convenience. These include OBSTOOLS which are a collection of Fortran
1172programs which are helpful to deal with feedback files. They do such tasks as observation file
1173conversion, printing of file contents, some basic statistical analysis of feedback files. The
1174other tool is an IDL program called dataplot which uses a graphical interface to visualise
1175observations and feedback files. OBSTOOLS and dataplot are described in more detail below. 
1176
1177\subsection{Obstools}
1178
1179A series of Fortran utilities is provided with NEMO called OBSTOOLS. This are helpful in
1180handling observation files and the feedback file output from the NEMO observation operator.
1181The utilities are as follows
1182
1183\subsubsection{c4comb}
1184
1185The program c4comb combines multiple class 4 files produced by individual processors in an
1186MPI run of NEMO offline obs\_oper into a single class 4 file. The program is called in the following way:
1187
1188\begin{alltt}
1189\footnotesize
1190\begin{verbatim}
1191c4comb.exe outputfile inputfile1 inputfile2 ...
1192\end{verbatim}
1193\end{alltt}
1194
1195\subsubsection{corio2fb}
1196
1197The program corio2fb converts profile observation files from the Coriolis format to the
1198standard feedback format. The program is called in the following way:
1199
1200\begin{alltt}
1201\footnotesize
1202\begin{verbatim}
1203corio2fb.exe outputfile inputfile1 inputfile2 ...
1204\end{verbatim}
1205\end{alltt}
1206
1207\subsubsection{enact2fb}
1208
1209The program enact2fb converts profile observation files from the ENACT format to the standard
1210feedback format. The program is called in the following way:
1211
1212\begin{alltt}
1213\footnotesize
1214\begin{verbatim}
1215enact2fb.exe outputfile inputfile1 inputfile2 ...
1216\end{verbatim}
1217\end{alltt}
1218
1219\subsubsection{fbcomb}
1220
1221The program fbcomb combines multiple feedback files produced by individual processors in an
1222MPI run of NEMO into a single feedback file. The program is called in the following way:
1223
1224\begin{alltt}
1225\footnotesize
1226\begin{verbatim}
1227fbcomb.exe outputfile inputfile1 inputfile2 ...
1228\end{verbatim}
1229\end{alltt}
1230
1231\subsubsection{fbmatchup}
1232
1233The program fbmatchup will match observations from two feedback files. The program is called
1234in the following way:
1235
1236\begin{alltt}
1237\footnotesize
1238\begin{verbatim}
1239fbmatchup.exe outputfile inputfile1 varname1 inputfile2 varname2 ...
1240\end{verbatim}
1241\end{alltt}
1242
1243
1244\subsubsection{fbprint}
1245
1246The program fbprint will print the contents of a feedback file or files to standard output.
1247Selected information can be output using optional arguments. The program is called in the
1248following way:
1249
1250\begin{alltt}
1251\footnotesize
1252\begin{verbatim}
1253fbprint.exe [options] inputfile
1254
1255options:
1256     -b            shorter output
1257     -q            Select observations based on QC flags
1258     -Q            Select observations based on QC flags
1259     -B            Select observations based on QC flags
1260     -u            unsorted
1261     -s ID         select station ID 
1262     -t TYPE       select observation type
1263     -v NUM1-NUM2  select variable range to print by number
1264                      (default all)
1265     -a NUM1-NUM2  select additional variable range to print by number
1266                      (default all)
1267     -e NUM1-NUM2  select extra variable range to print by number
1268                      (default all)
1269     -d            output date range
1270     -D            print depths
1271     -z            use zipped files
1272\end{verbatim}
1273\end{alltt}
1274
1275\subsubsection{fbsel}
1276
1277The program fbsel will select or subsample observations. The program is called in the
1278following way:
1279
1280\begin{alltt}
1281\footnotesize
1282\begin{verbatim}
1283fbsel.exe <input filename> <output filename>
1284\end{verbatim}
1285\end{alltt}
1286
1287\subsubsection{fbstat}
1288
1289The program fbstat will output summary statistics in different global areas into a number of
1290files. The program is called in the following way:
1291
1292\begin{alltt}
1293\footnotesize
1294\begin{verbatim}
1295fbstat.exe [-nmlev] <filenames>
1296\end{verbatim}
1297\end{alltt}
1298
1299\subsubsection{fbthin}
1300
1301The program fbthin will thin the data to 1 degree resolution. The code could easily be
1302modified to thin to a different resolution. The program is called in the following way:
1303
1304\begin{alltt}
1305\footnotesize
1306\begin{verbatim}
1307fbthin.exe inputfile outputfile
1308\end{verbatim}
1309\end{alltt}
1310
1311\subsubsection{sla2fb}
1312
1313The program sla2fb will convert an AVISO SLA format file to feedback format. The program is
1314called in the following way:
1315
1316\begin{alltt}
1317\footnotesize
1318\begin{verbatim}
1319sla2fb.exe [-s type] outputfile inputfile1 inputfile2 ...
1320
1321Option:
1322     -s            Select altimeter data_source
1323\end{verbatim}
1324\end{alltt}
1325
1326\subsubsection{vel2fb}
1327
1328The program vel2fb will convert TAO/PIRATA/RAMA currents files to feedback format. The program
1329is called in the following way:
1330
1331\begin{alltt}
1332\footnotesize
1333\begin{verbatim}
1334vel2fb.exe outputfile inputfile1 inputfile2 ...
1335\end{verbatim}
1336\end{alltt}
1337
1338\subsection{building the obstools}
1339
1340To build the obstools use in the tools directory use ./maketools -n OBSTOOLS -m [ARCH].
1341
1342\subsection{Dataplot}
1343
1344An IDL program called dataplot is included which uses a graphical interface to visualise
1345observations and feedback files. It is possible to zoom in, plot individual profiles and
1346calculate some basic statistics. To plot some data run IDL and then:
1347\begin{alltt}
1348\footnotesize
1349\begin{verbatim}
1350IDL> dataplot, "filename"
1351\end{verbatim}
1352\end{alltt}
1353
1354To read multiple files into dataplot, for example multiple feedback files from different
1355processors or from different days, the easiest method is to use the spawn command to generate
1356a list of files which can then be passed to dataplot.
1357\begin{alltt}
1358\footnotesize
1359\begin{verbatim}
1360IDL> spawn, 'ls profb*.nc', files
1361IDL> dataplot, files
1362\end{verbatim}
1363\end{alltt}
1364
1365Fig~\ref{fig:obsdataplotmain} shows the main window which is launched when dataplot starts.
1366This is split into three parts. At the top there is a menu bar which contains a variety of
1367drop down menus. Areas - zooms into prespecified regions; plot - plots the data as a
1368timeseries or a T-S diagram if appropriate; Find - allows data to be searched; Config - sets
1369various configuration options.
1370
1371The middle part is a plot of the geographical location of the observations. This will plot the
1372observation value, the model background value or observation minus background value depending
1373on the option selected in the radio button at the bottom of the window. The plotting colour
1374range can be changed by clicking on the colour bar. The title of the plot gives some basic
1375information about the date range and depth range shown, the extreme values, and the mean and
1376rms values. It is possible to zoom in using a drag-box. You may also zoom in or out using the
1377mouse wheel.
1378
1379The bottom part of the window controls what is visible in the plot above. There are two bars
1380which select the level range plotted (for profile data). The other bars below select the date
1381range shown. The bottom of the figure allows the option to plot the mean, root mean square,
1382standard deviation or mean square values. As mentioned above you can choose to plot the
1383observation value, the model background value or observation minus background value. The next
1384group of radio buttons selects the map projection. This can either be regular latitude
1385longitude grid, or north or south polar stereographic. The next group of radio buttons will
1386plot bad observations, switch to salinity and plot density for profile observations. The
1387rightmost group of buttons will print the plot window as a postscript, save it as png, or exit
1388from dataplot.
1389
1390%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1391\begin{figure}     \begin{center}
1392%\includegraphics[width=10cm,height=12cm,angle=-90.]{Fig_OBS_dataplot_main}
1393\includegraphics[width=9cm,angle=-90.]{Fig_OBS_dataplot_main}
1394\caption{      \label{fig:obsdataplotmain}
1395Main window of dataplot.}
1396\end{center}     \end{figure}
1397%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1398
1399If a profile point is clicked with the mouse button a plot of the observation and background
1400values as a function of depth (Fig~\ref{fig:obsdataplotprofile}).
1401
1402%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1403\begin{figure}     \begin{center}
1404%\includegraphics[width=10cm,height=12cm,angle=-90.]{Fig_OBS_dataplot_prof}
1405\includegraphics[width=7cm,angle=-90.]{Fig_OBS_dataplot_prof}
1406\caption{      \label{fig:obsdataplotprofile}
1407Profile plot from dataplot produced by right clicking on a point in the main window.}
1408\end{center}     \end{figure}
1409%>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1410
1411
1412
1413
1414\end{document}
Note: See TracBrowser for help on using the repository browser.