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 NEMO/trunk/doc/latex/NEMO/subfiles – NEMO

source: NEMO/trunk/doc/latex/NEMO/subfiles/chap_OBS.tex @ 10146

Last change on this file since 10146 was 10146, checked in by nicolasmartin, 6 years ago

Reorganisation for future addition of .rst files from users wiki extraction

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