ARTS  2.0.49
jacobian.cc
Go to the documentation of this file.
1 /* Copyright (C) 2004-2008 Mattias Ekstrom <ekstrom@rss.chalmers.se>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
26 #include "arts.h"
27 #include "jacobian.h"
28 #include "special_interp.h"
29 #include "physics_funcs.h"
30 
31 ostream& operator << (ostream& os, const RetrievalQuantity& ot)
32 {
33  return os << "\n Main tag = " << ot.MainTag()
34  << "\n Sub tag = " << ot.Subtag()
35  << "\n Mode = " << ot.Mode()
36  << "\n Analytical = " << ot.Analytical();
37 }
38 
39 /*===========================================================================
40  === The functions in alphabetical order
41  ===========================================================================*/
42 
44 
56  const VectorView& p,
57  const Tensor3View& t)
58 {
59  assert( nd.npages()==t.npages() );
60  assert( nd.nrows()==t.nrows() );
61  assert( nd.ncols()==t.ncols() );
62  assert( nd.npages()==p.nelem() );
63 
64  for (Index p_it=0; p_it<nd.npages(); p_it++)
65  {
66  for (Index lat_it=0; lat_it<nd.nrows(); lat_it++)
67  {
68  for (Index lon_it=0; lon_it<nd.ncols(); lon_it++)
69  {
70  nd(p_it,lat_it,lon_it) = number_density( p[p_it], t(p_it,lat_it,lon_it));
71  }
72  }
73  }
74 }
75 
76 
77 
79 
105  ostringstream& os,
106  const Vector& p_grid,
107  const Vector& lat_grid,
108  const Vector& lon_grid,
109  const Vector& p_retr,
110  const Vector& lat_retr,
111  const Vector& lon_retr,
112  const String& p_retr_name,
113  const String& lat_retr_name,
114  const String& lon_retr_name,
115  const Index& dim)
116 {
117  if ( p_retr.nelem()==0 )
118  {
119  os << "The grid vector *" << p_retr_name << "* is empty,"
120  << " at least one pressure level\n"
121  << "should be specified.";
122  return false;
123  }
124  else if( !is_decreasing( p_retr ) )
125  {
126  os << "The pressure grid vector *" << p_retr_name << "* is not a\n"
127  << "strictly decreasing vector, which is required.";
128  return false;
129  }
130  else if ( log(p_retr[0])> 1.5*log(p_grid[0])-0.5*log(p_grid[1]) ||
131  log(p_retr[p_retr.nelem()-1])<1.5*log(p_grid[p_grid.nelem()-1])-
132  0.5*log(p_grid[p_grid.nelem()-2]))
133  {
134  os << "The grid vector *" << p_retr_name << "* is not covered by the\n"
135  << "corresponding atmospheric grid.";
136  return false;
137  }
138  else
139  {
140  // Pressure grid ok, add it to grids
141  grids[0]=p_retr;
142  }
143 
144  if (dim>=2)
145  {
146  // If 2D and 3D atmosphere, check latitude grid
147  if ( lat_retr.nelem()==0 )
148  {
149  os << "The grid vector *" << lat_retr_name << "* is empty,"
150  << " at least one latitude\n"
151  << "should be specified for a 2D/3D atmosphere.";
152  return false;
153  }
154  else if( !is_increasing( lat_retr ) )
155  {
156  os << "The latitude grid vector *" << lat_retr_name << "* is not a\n"
157  << "strictly increasing vector, which is required.";
158  return false;
159  }
160  else if ( lat_retr[0]<1.5*lat_grid[0]-0.5*lat_grid[1] ||
161  lat_retr[lat_retr.nelem()-1]>1.5*lat_grid[lat_grid.nelem()-1]-
162  0.5*lat_grid[lat_grid.nelem()-2] )
163  {
164  os << "The grid vector *" << lat_retr_name << "* is not covered by the\n"
165  << "corresponding atmospheric grid.";
166  return false;
167  }
168  else
169  {
170  // Latitude grid ok, add it to grids
171  grids[1]=lat_retr;
172  }
173  if (dim==3)
174  {
175  // For 3D atmosphere check longitude grid
176  if ( lon_retr.nelem()==0 )
177  {
178  os << "The grid vector *" << lon_retr_name << "* is empty,"
179  << " at least one longitude\n"
180  << "should be specified for a 3D atmosphere.";
181  return false;
182  }
183  else if( !is_increasing( lon_retr ) )
184  {
185  os << "The longitude grid vector *" << lon_retr_name << "* is not a\n"
186  << "strictly increasing vector, which is required.";
187  return false;
188  }
189  else if ( lon_retr[0]<1.5*lon_grid[0]-0.5*lon_grid[1] ||
190  lon_retr[lon_retr.nelem()-1]>1.5*lon_grid[lon_grid.nelem()-1]-
191  0.5*lon_grid[lon_grid.nelem()-2] )
192  {
193  os << "The grid vector *" << lon_retr_name << "* is not covered by the\n"
194  << "corresponding atmospheric grid.";
195  return false;
196  }
197  else
198  {
199  // Longitude grid ok, add it to grids
200  grids[2]=lon_retr;
201  }
202  }
203  }
204  return true;
205 }
206 
207 
208 
210 
230  const Vector& atm_grid,
231  const Vector& jac_grid,
232  const bool& is_pressure)
233 {
234  Index nj = jac_grid.nelem();
235  Index na = atm_grid.nelem();
236  Vector pert(nj+2);
237 
238  // Create perturbation grid, with extension outside the atmospheric grid
239  if ( is_pressure )
240  {
241  pert[0] = atm_grid[0]*10.0;
242  pert[nj+1] = atm_grid[na-1]*0.1;
243  }
244  else
245  {
246  pert[0] = atm_grid[0]-1.0;
247  pert[nj+1] = atm_grid[na-1]+1.0;
248  }
249  pert[Range(1,nj)] = jac_grid;
250 
251  // Calculate the gridpos
252  gp.resize(na);
253  if( is_pressure ){
254  p2gridpos( gp, pert, atm_grid);
255  }
256  else
257  {
258  gridpos( gp, pert, atm_grid);
259  }
260 }
261 
262 
263 
265 
289  const Vector& pert_grid,
290  const Vector& atm_limit)
291 {
292  limit.resize(2);
293 // Index np = pert_grid.nelem()-1;
294  Index na = atm_limit.nelem()-1;
295 
296  // If the field is ordered in decreasing order set the
297  // increment factor to -1
298  Numeric inc = 1;
299  if (is_decreasing(pert_grid))
300  inc = -1;
301 
302  // Check that the pert_grid is encompassing atm_limit
303 // assert( inc*pert_grid[0] < inc*atm_limit[0] &&
304 // inc*pert_grid[np] > inc*atm_limit[na]);
305 
306  // Find first limit, check if following value is above lower limit
307  limit[0]=0;
308  while (inc*pert_grid[limit[0]+1] < inc*atm_limit[0])
309  {
310  limit[0]++;
311  }
312 
313  // Find last limit, check if previous value is below upper limit
314  limit[1]=pert_grid.nelem();
315  while (inc*pert_grid[limit[1]-1] > inc*atm_limit[na])
316  {
317  limit[1]--;
318  }
319  // Check that the limits are ok
320  assert(limit[1]>limit[0]);
321 
322 }
323 
324 
325 
327 
341  const Index& index,
342  const Index& length)
343 {
344  if (index==0)
345  range = Range(index,2);
346  else if (index==length-1)
347  range = Range(index+1,2);
348  else
349  range = Range(index+1,1);
350 
351 }
352 
353 
354 
356 
371  const ArrayOfGridPos& p_gp,
372  const Index& p_pert_n,
373  const Range& p_range,
374  const Numeric& size,
375  const Index& method)
376 {
377  // Here we only perturb a vector
378  Vector pert(field.nelem());
379  Matrix itw(p_gp.nelem(),2);
380  interpweights(itw,p_gp);
381  // For relative pert_field should be 1.0 and for absolute 0.0
382  Vector pert_field(p_pert_n,1.0-(Numeric)method);
383  pert_field[p_range] += size;
384  interp( pert, itw, pert_field, p_gp);
385  if (method==0)
386  {
387  field *= pert;
388  }
389  else
390  {
391  field += pert;
392  }
393 }
394 
395 
396 
398 
416  const ArrayOfGridPos& p_gp,
417  const ArrayOfGridPos& lat_gp,
418  const Index& p_pert_n,
419  const Index& lat_pert_n,
420  const Range& p_range,
421  const Range& lat_range,
422  const Numeric& size,
423  const Index& method)
424 {
425  // Here we perturb a matrix
426  Matrix pert(field.nrows(),field.ncols());
427  Tensor3 itw(p_gp.nelem(),lat_gp.nelem(),4);
428  interpweights(itw,p_gp,lat_gp);
429  // Init pert_field to 1.0 for relative and 0.0 for absolute
430  Matrix pert_field(p_pert_n,lat_pert_n,1.0-(Numeric)method);
431  pert_field(p_range,lat_range) += size;
432  interp( pert, itw, pert_field, p_gp, lat_gp);
433  if (method==0)
434  {
435  field *= pert;
436  }
437  else
438  {
439  field += pert;
440  }
441 }
442 
443 
444 
446 
467  const ArrayOfGridPos& p_gp,
468  const ArrayOfGridPos& lat_gp,
469  const ArrayOfGridPos& lon_gp,
470  const Index& p_pert_n,
471  const Index& lat_pert_n,
472  const Index& lon_pert_n,
473  const Range& p_range,
474  const Range& lat_range,
475  const Range& lon_range,
476  const Numeric& size,
477  const Index& method)
478 {
479  // Here we need to perturb a tensor3
480  Tensor3 pert(field.npages(),field.nrows(),field.ncols());
481  Tensor4 itw(p_gp.nelem(),lat_gp.nelem(),lon_gp.nelem(),8);
482  interpweights(itw,p_gp,lat_gp,lon_gp);
483  // Init pert_field to 1.0 for relative and 0.0 for absolute
484  Tensor3 pert_field(p_pert_n,lat_pert_n,lon_pert_n,1.0-(Numeric)method);
485  pert_field(p_range,lat_range,lon_range) += size;
486  interp( pert, itw, pert_field, p_gp, lat_gp, lon_gp);
487  if (method==0)
488  {
489  field *= pert;
490  }
491  else
492  {
493  field += pert;
494  }
495 }
496 
497 
498 
500 
514  Vector& b,
515  const Vector& x,
516  const Index& poly_coeff )
517 {
518  const Index l = x.nelem();
519 
520  assert( l > poly_coeff );
521 
522  if( b.nelem() != l )
523  b.resize( l );
524 
525  if( poly_coeff == 0 )
526  { b = 1.0; }
527  else
528  {
529  const Numeric xmin = min( x );
530  const Numeric dx = 0.5 * ( max( x ) - xmin );
531  //
532  for( Index i=0; i<l; i++ )
533  {
534  b[i] = ( x[i] - xmin ) / dx - 1.0;
535  b[i] = pow( b[i], int(poly_coeff) );
536  }
537  //
538  b -= mean( b );
539  }
540 }
541 
542 
543 
545 
562  Numeric& x,
563  const String& unit,
564  const Numeric& vmr,
565  const Numeric& p,
566  const Numeric& t )
567 {
568  if( unit == "rel" || unit == "logrel" )
569  { x = 1; }
570  else if( unit == "vmr" )
571  { x = 1 / vmr; }
572  else if( unit == "nd" )
573  { x = 1 / ( vmr * number_density( p, t ) ); }
574  else
575  {
576  throw runtime_error( "Allowed options for gas species jacobians are "
577  "\"rel\", \"vmr\", \"nd\" and \"logrel\"." );
578  }
579 }
580 
581 
Matrix
The Matrix class.
Definition: matpackI.h:767
RetrievalQuantity::Analytical
const Index & Analytical() const
Boolean to make analytical calculations (if possible).
Definition: jacobian.h:96
MatrixView
The MatrixView class.
Definition: matpackI.h:668
get_perturbation_range
void get_perturbation_range(Range &range, const Index &index, const Index &length)
Get range for perturbation.
Definition: jacobian.cc:340
gridpos
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
Definition: interpolation.cc:167
Tensor3
The Tensor3 class.
Definition: matpackIII.h:340
operator<<
ostream & operator<<(ostream &os, const RetrievalQuantity &ot)
Output operator for RetrievalQuantity.
Definition: jacobian.cc:31
p2gridpos
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
p2gridpos
Definition: special_interp.cc:810
interp
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Definition: interpolation.cc:1000
perturbation_field_1d
void perturbation_field_1d(VectorView field, const ArrayOfGridPos &p_gp, const Index &p_pert_n, const Range &p_range, const Numeric &size, const Index &method)
Calculate the 1D perturbation for a relative perturbation.
Definition: jacobian.cc:370
vmrunitscf
void vmrunitscf(Numeric &x, const String &unit, const Numeric &vmr, const Numeric &p, const Numeric &t)
vmrunitscf
Definition: jacobian.cc:561
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.cc:771
perturbation_field_2d
void perturbation_field_2d(MatrixView field, const ArrayOfGridPos &p_gp, const ArrayOfGridPos &lat_gp, const Index &p_pert_n, const Index &lat_pert_n, const Range &p_range, const Range &lat_range, const Numeric &size, const Index &method)
Calculate the 2D perturbation for a relative perturbation.
Definition: jacobian.cc:415
polynomial_basis_func
void polynomial_basis_func(Vector &b, const Vector &x, const Index &poly_coeff)
Calculates polynomial basis functions.
Definition: jacobian.cc:513
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:796
Tensor4
The Tensor4 class.
Definition: matpackIV.h:375
calc_nd_field
void calc_nd_field(Tensor3View &nd, const VectorView &p, const Tensor3View &t)
Calculate the number density field.
Definition: jacobian.cc:55
ConstTensor3View::npages
Index npages() const
Returns the number of pages.
Definition: matpackIII.h:151
dx
#define dx
Definition: continua.cc:14561
Tensor3View
The Tensor3View class.
Definition: matpackIII.h:234
Array< Vector >
number_density
Numeric number_density(const Numeric &p, const Numeric &t)
number_density
Definition: physics_funcs.cc:195
is_decreasing
bool is_decreasing(ConstVectorView x)
Checks if a vector is sorted in reversed order and is strictly decreasing.
Definition: logic.cc:303
get_perturbation_limit
void get_perturbation_limit(ArrayOfIndex &limit, const Vector &pert_grid, const Vector &atm_limit)
Get limits for perturbation of a box.
Definition: jacobian.cc:288
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:802
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:62
RetrievalQuantity::MainTag
const String & MainTag() const
Main tag.
Definition: jacobian.h:87
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:175
VectorView
The VectorView class.
Definition: matpackI.h:373
physics_funcs.h
mean
Numeric mean(const ConstVectorView &x)
Mean function, vector version.
Definition: matpackI.cc:1862
RetrievalQuantity::Mode
const String & Mode() const
Calculation mode.
Definition: jacobian.h:93
jacobian.h
Declarations required for the calculation of jacobians.
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
get_perturbation_gridpos
void get_perturbation_gridpos(ArrayOfGridPos &gp, const Vector &atm_grid, const Vector &jac_grid, const bool &is_pressure)
Calculate array of GridPos for perturbation interpolation.
Definition: jacobian.cc:229
ConstTensor3View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackIII.h:154
max
#define max(a, b)
Definition: continua.cc:13097
perturbation_field_3d
void perturbation_field_3d(Tensor3View field, const ArrayOfGridPos &p_gp, const ArrayOfGridPos &lat_gp, const ArrayOfGridPos &lon_gp, const Index &p_pert_n, const Index &lat_pert_n, const Index &lon_pert_n, const Range &p_range, const Range &lat_range, const Range &lon_range, const Numeric &size, const Index &method)
Calculate the 3D perturbation for a relative perturbation.
Definition: jacobian.cc:466
Range
The range class.
Definition: matpackI.h:148
check_retrieval_grids
bool check_retrieval_grids(ArrayOfVector &grids, ostringstream &os, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Vector &p_retr, const Vector &lat_retr, const Vector &lon_retr, const String &p_retr_name, const String &lat_retr_name, const String &lon_retr_name, const Index &dim)
Check that the retrieval grids are defined for each atmosphere dim.
Definition: jacobian.cc:104
is_increasing
bool is_increasing(ConstVectorView x)
Checks if a vector is sorted and strictly increasing.
Definition: logic.cc:258
ConstTensor3View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackIII.h:157
min
#define min(a, b)
Definition: continua.cc:13096
special_interp.h
Header file for special_interp.cc.
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
RetrievalQuantity
Contains the data for one retrieval quantity.
Definition: jacobian.h:45
Vector
The Vector class.
Definition: matpackI.h:555
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
RetrievalQuantity::Subtag
const String & Subtag() const
Subtag.
Definition: jacobian.h:90
interpweights
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Definition: interpolation.cc:756
arts.h
The global header file for ARTS.