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 branches/2015/nemo_v3_6_STABLE/DOC/TexFiles/Chapters – NEMO

source: branches/2015/nemo_v3_6_STABLE/DOC/TexFiles/Chapters/Chap_OBS.tex @ 6992

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

Global reorganisation of DOC directory to ensure the export of NEMO Reference Manual both in PDF & HTML

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