ARTS  2.0.49
m_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 */
18 
19 
20 
21 /*===========================================================================
22  === File description
23  ===========================================================================*/
24 
37 /*===========================================================================
38  === External declarations
39  ===========================================================================*/
40 
41 #include <cmath>
42 #include <string>
43 #include "absorption.h"
44 #include "arts.h"
45 #include "auto_md.h"
46 #include "check_input.h"
47 #include "math_funcs.h"
48 #include "messages.h"
49 #include "interpolation_poly.h"
50 #include "jacobian.h"
51 #include "physics_funcs.h"
52 #include "rte.h"
53 
54 extern const String ABSSPECIES_MAINTAG;
55 extern const String FREQUENCY_MAINTAG;
56 extern const String FREQUENCY_SUBTAG_A;
57 extern const String FREQUENCY_CALCMODE_A;
58 extern const String POINTING_MAINTAG;
59 extern const String POINTING_SUBTAG_A;
60 extern const String POINTING_CALCMODE_A;
61 extern const String POINTING_CALCMODE_B;
62 extern const String POLYFIT_MAINTAG;
63 extern const String TEMPERATURE_MAINTAG;
64 
65 
66 
67 /*===========================================================================
68  === The methods, with general methods first followed by the Add/Calc method
69  === pairs for each retrieval quantity.
70  ===========================================================================*/
71 
72 
73 //----------------------------------------------------------------------------
74 // General methods:
75 //----------------------------------------------------------------------------
76 
77 
78 /* Workspace method: Doxygen documentation will be auto-generated */
80  Workspace& ws,
81  Index& jacobian_do,
82  Matrix& jacobian,
83  ArrayOfArrayOfIndex& jacobian_indices,
84  Agenda& jacobian_agenda,
85  const ArrayOfRetrievalQuantity& jacobian_quantities,
86  const Matrix& sensor_pos,
87  const Sparse& sensor_response,
88  const Verbosity& verbosity )
89 {
90  // Make sure that the array is not empty
91  if( jacobian_quantities.nelem() == 0 )
92  throw runtime_error(
93  "No retrieval quantities has been added to *jacobian_quantities*." );
94 
95  // Check that sensor_pol and sensor_response has been initialised
96  if( sensor_pos.nrows() == 0 )
97  {
98  ostringstream os;
99  os << "The number of rows in *sensor_pos* is zero, i.e. no measurement\n"
100  << "blocks has been defined. This has to be done before calling\n"
101  << "jacobianClose.";
102  throw runtime_error(os.str());
103  }
104  if( sensor_response.nrows() == 0 )
105  {
106  ostringstream os;
107  os << "The sensor has either to be defined or turned off before calling\n"
108  << "jacobianClose.";
109  throw runtime_error(os.str());
110  }
111 
112  // Loop over retrieval quantities, set JacobianIndices
113  Index nrows = sensor_pos.nrows() * sensor_response.nrows();
114  Index ncols = 0;
115  //
116  for( Index it=0; it<jacobian_quantities.nelem(); it++ )
117  {
118  // Store start jacobian index
119  ArrayOfIndex indices(2);
120  indices[0] = ncols;
121 
122  // Count total number of field points, i.e. product of grid lengths
123  Index cols = 1;
124  ArrayOfVector grids = jacobian_quantities[it].Grids();
125  for( Index jt=0; jt<grids.nelem(); jt++ )
126  { cols *= grids[jt].nelem(); }
127 
128  // Store stop index
129  indices[1] = ncols + cols - 1;
130  jacobian_indices.push_back( indices );
131 
132  ncols += cols;
133  }
134 
135  // Resize *jacobian*
136  jacobian.resize( nrows, ncols );
137  jacobian = 0;
138 
139  jacobian_agenda.check(ws, verbosity);
140  jacobian_do = 1;
141 }
142 
143 
144 
145 /* Workspace method: Doxygen documentation will be auto-generated */
147  ArrayOfRetrievalQuantity& jacobian_quantities,
148  Agenda& jacobian_agenda,
149  const Verbosity& )
150 {
151  jacobian_quantities.resize(0);
152  jacobian_agenda = Agenda();
153  jacobian_agenda.set_name( "jacobian_agenda" );
154 }
155 
156 
157 
158 /* Workspace method: Doxygen documentation will be auto-generated */
160  Index& jacobian_do,
161  Agenda& jacobian_agenda,
162  ArrayOfRetrievalQuantity& jacobian_quantities,
163  ArrayOfArrayOfIndex& jacobian_indices,
164  const Verbosity& verbosity )
165 {
166  jacobianInit(jacobian_quantities, jacobian_agenda, verbosity);
167  jacobian_do = 0;
168  jacobian_indices.resize(0);
169 }
170 
171 
172 
173 
174 
175 //----------------------------------------------------------------------------
176 // Absorption species:
177 //----------------------------------------------------------------------------
178 
179 /* Workspace method: Doxygen documentation will be auto-generated */
181  Workspace& ws _U_,
183  Agenda& jacobian_agenda,
184  const Index& atmosphere_dim,
185  const Vector& p_grid,
186  const Vector& lat_grid,
187  const Vector& lon_grid,
188  const Vector& rq_p_grid,
189  const Vector& rq_lat_grid,
190  const Vector& rq_lon_grid,
191  const String& species,
192  const String& method,
193  const String& mode,
194  const Numeric& dx,
195  const Verbosity& verbosity )
196 {
199 
200  // Check that this species is not already included in the jacobian.
201  for( Index it=0; it<jq.nelem(); it++ )
202  {
203  if( jq[it].MainTag() == ABSSPECIES_MAINTAG &&
204  jq[it].Subtag() == species )
205  {
206  ostringstream os;
207  os << "The gas species:\n" << species << "\nis already included in "
208  << "*jacobian_quantities*.";
209  throw runtime_error(os.str());
210  }
211  }
212 
213  // Check retrieval grids, here we just check the length of the grids
214  // vs. the atmosphere dimension
215  ArrayOfVector grids(atmosphere_dim);
216  {
217  ostringstream os;
218  if( !check_retrieval_grids( grids, os, p_grid, lat_grid, lon_grid,
219  rq_p_grid, rq_lat_grid, rq_lon_grid,
220  "retrieval pressure grid",
221  "retrieval latitude grid",
222  "retrievallongitude_grid",
223  atmosphere_dim ) )
224  throw runtime_error(os.str());
225  }
226 
227  // Check that method is either "analytical" or "perturbation"
228  bool analytical;
229  if( method == "perturbation" )
230  { analytical = 0; }
231  else if( method == "analytical" )
232  { analytical = 1; }
233  else
234  {
235  ostringstream os;
236  os << "The method for absorption species retrieval can only be "
237  << "\"analytical\"\n or \"perturbation\".";
238  throw runtime_error(os.str());
239  }
240 
241  // Check that mode is either "vmr", "nd" or "rel" with or without prefix log
242  if( mode != "vmr" && mode != "nd" && mode != "rel" && mode != "logrel" )
243  {
244  throw runtime_error( "The retrieval mode can only be \"vmr\", \"nd\" "
245  "\"rel\" or \"logrel\"." );
246  }
247 
248  // If nd, check that not temmperature is retrieved
249  if( mode == "nd" )
250  {
251  for (Index it=0; it<jq.nelem(); it++)
252  {
253  if( jq[it].MainTag() == TEMPERATURE_MAINTAG )
254  {
255  ostringstream os;
256  os <<
257  "Retrieval of temperature and number densities can not be mixed.";
258  throw runtime_error(os.str());
259  }
260  }
261  }
262 
263  // Create the new retrieval quantity
266  rq.Subtag( species );
267  rq.Mode( mode );
268  rq.Analytical( analytical );
269  rq.Perturbation( dx );
270  rq.Grids( grids );
271 
272  // Add it to the *jacobian_quantities*
273  jq.push_back( rq );
274 
275  // Add gas species method to the jacobian agenda, if perturbation
276  if( analytical )
277  {
278  out3 << " Calculations done by semi-analytical expressions.\n";
279  jacobian_agenda.append( "jacobianCalcAbsSpeciesAnalytical", TokVal() );
280  }
281  else
282  {
283  out2 << " Adding absorption species: " << species
284  << " to *jacobian_quantities*\n" << " and *jacobian_agenda*\n";
285  out3 << " Calculations done by perturbation, size " << dx
286  << " " << mode << ".\n";
287 
288  jacobian_agenda.append( "jacobianCalcAbsSpeciesPerturbations", species );
289  }
290 }
291 
292 
293 
294 /* Workspace method: Doxygen documentation will be auto-generated */
296  Matrix& jacobian _U_,
297  const Index& imblock _U_,
298  const Vector& iyb _U_,
299  const Vector& yb _U_,
300  const Verbosity& )
301 {
302  /* Nothing to do here for the analytical case, this function just exists
303  to satisfy the required inputs and outputs of the jacobian_agenda */
304 }
305 
306 
307 
308 /* Workspace method: Doxygen documentation will be auto-generated */
310  Workspace& ws,
311  Matrix& jacobian,
312  const Index& imblock,
313  const Vector& iyb _U_,
314  const Vector& yb,
315  const Index& atmosphere_dim,
316  const Vector& p_grid,
317  const Vector& lat_grid,
318  const Vector& lon_grid,
319  const Tensor3& t_field,
320  const Tensor3& z_field,
321  const Tensor4& vmr_field,
322  const ArrayOfArrayOfSpeciesTag& abs_species,
323  const Index& cloudbox_on,
324  const Index& stokes_dim,
325  const Vector& f_grid,
326  const Matrix& sensor_pos,
327  const Matrix& sensor_los,
328  const Vector& mblock_za_grid,
329  const Vector& mblock_aa_grid,
330  const Index& antenna_dim,
331  const Sparse& sensor_response,
332  const Agenda& iy_clearsky_agenda,
333  const String& y_unit,
334  const ArrayOfRetrievalQuantity& jacobian_quantities,
335  const ArrayOfArrayOfIndex& jacobian_indices,
336  const String& species,
337  const Verbosity& verbosity)
338 {
339  // Set some useful variables.
341  ArrayOfIndex ji;
342  Index it, pertmode;
343 
344  // Find the retrieval quantity related to this method, i.e. Abs. species -
345  // species. This works since the combined MainTag and Subtag is individual.
346  bool found = false;
347  for( Index n=0; n<jacobian_quantities.nelem() && !found; n++ )
348  {
349  if( jacobian_quantities[n].MainTag() == ABSSPECIES_MAINTAG &&
350  jacobian_quantities[n].Subtag() == species )
351  {
352  found = true;
353  rq = jacobian_quantities[n];
354  ji = jacobian_indices[n];
355  }
356  }
357  if( !found )
358  {
359  ostringstream os;
360  os << "There is no gas species retrieval quantities defined for:\n"
361  << species;
362  throw runtime_error(os.str());
363  }
364 
365  if( rq.Analytical() )
366  {
367  ostringstream os;
368  os << "This WSM handles only perturbation calculations.\n"
369  << "Are you using the method manually?";
370  throw runtime_error(os.str());
371  }
372 
373  // Store the start JacobianIndices and the Grids for this quantity
374  it = ji[0];
375  ArrayOfVector jg = rq.Grids();
376 
377  // Check if a relative pertubation is used or not, this information is needed
378  // by the methods 'perturbation_field_?d'.
379  // Note: both 'vmr' and 'nd' are absolute perturbations
380  if( rq.Mode()=="rel" )
381  pertmode = 0;
382  else
383  pertmode = 1;
384 
385  // For each atmospheric dimension option calculate a ArrayOfGridPos, these
386  // are the base functions for interpolating the perturbations into the
387  // atmospheric grids.
388  ArrayOfGridPos p_gp, lat_gp, lon_gp;
389  Index j_p = jg[0].nelem();
390  Index j_lat = 1;
391  Index j_lon = 1;
392  //
393  get_perturbation_gridpos( p_gp, p_grid, jg[0], true );
394  //
395  if( atmosphere_dim >= 2 )
396  {
397  j_lat = jg[1].nelem();
398  get_perturbation_gridpos( lat_gp, lat_grid, jg[1], false );
399  if( atmosphere_dim == 3 )
400  {
401  j_lon = jg[2].nelem();
402  get_perturbation_gridpos( lon_gp, lon_grid, jg[2], false );
403  }
404  }
405 
406  // Find VMR field for this species.
407  ArrayOfSpeciesTag tags;
408  array_species_tag_from_string( tags, species );
409  Index si = chk_contains( "species", abs_species, tags );
410 
411  // Variables for vmr field perturbation unit conversion
412  Tensor3 nd_field(0,0,0);
413  if( rq.Mode()=="nd" )
414  {
415  nd_field.resize( t_field.npages(), t_field.nrows(), t_field.ncols() );
416  calc_nd_field( nd_field, p_grid, t_field );
417  }
418 
419 
420  // Loop through the retrieval grid and calculate perturbation effect
421  //
422  const Index n1y = sensor_response.nrows();
423  Vector dy( n1y );
424  const Range rowind = get_rowindex_for_mblock( sensor_response, imblock );
425  //
426  for( Index lon_it=0; lon_it<j_lon; lon_it++ )
427  {
428  for( Index lat_it=0; lat_it<j_lat; lat_it++ )
429  {
430  for (Index p_it=0; p_it<j_p; p_it++)
431  {
432  // Here we calculate the ranges of the perturbation. We want the
433  // perturbation to continue outside the atmospheric grids for the
434  // edge values.
435  Range p_range = Range(0,0);
436  Range lat_range = Range(0,0);
437  Range lon_range = Range(0,0);
438 
439  get_perturbation_range( p_range, p_it, j_p );
440 
441  if( atmosphere_dim>=2 )
442  {
443  get_perturbation_range( lat_range, lat_it, j_lat );
444  if( atmosphere_dim == 3 )
445  {
446  get_perturbation_range( lon_range, lon_it, j_lon );
447  }
448  }
449 
450  // Create VMR field to perturb
451  Tensor4 vmr_p = vmr_field;
452 
453  // If perturbation given in ND convert the vmr-field to ND before
454  // the perturbation is added
455  if( rq.Mode() == "nd" )
456  vmr_p(si,joker,joker,joker) *= nd_field;
457 
458  // Calculate the perturbed field according to atmosphere_dim,
459  // the number of perturbations is the length of the retrieval
460  // grid +2 (for the end points)
461  switch (atmosphere_dim)
462  {
463  case 1:
464  {
465  // Here we perturb a vector
466  perturbation_field_1d( vmr_p(si,joker,lat_it,lon_it),
467  p_gp, jg[0].nelem()+2, p_range,
468  rq.Perturbation(), pertmode );
469  break;
470  }
471  case 2:
472  {
473  // Here we perturb a matrix
474  perturbation_field_2d( vmr_p(si,joker,joker,lon_it),
475  p_gp, lat_gp, jg[0].nelem()+2,
476  jg[1].nelem()+2, p_range, lat_range,
477  rq.Perturbation(), pertmode );
478  break;
479  }
480  case 3:
481  {
482  // Here we need to perturb a tensor3
484  p_gp, lat_gp, lon_gp,
485  jg[0].nelem()+2,
486  jg[1].nelem()+2, jg[2].nelem()+2,
487  p_range, lat_range, lon_range,
488  rq.Perturbation(), pertmode );
489  break;
490  }
491  }
492 
493  // If perturbation given in ND convert back to VMR
494  if (rq.Mode()=="nd")
495  vmr_p(si,joker,joker,joker) /= nd_field;
496 
497  // Calculate the perturbed spectrum
498  //
499  Index dummy2 = 0;
500  Vector iybp, dummy1, dummy3;
501  ArrayOfMatrix dummy4;
502  //
503  iyb_calc( ws, iybp, dummy1, dummy2, dummy3, dummy4, imblock,
504  atmosphere_dim, p_grid, lat_grid, lon_grid,
505  t_field, z_field, vmr_p, cloudbox_on, stokes_dim,
506  f_grid, sensor_pos, sensor_los, mblock_za_grid,
507  mblock_aa_grid, antenna_dim, iy_clearsky_agenda,
508  y_unit, 0, ArrayOfRetrievalQuantity(),
509  ArrayOfArrayOfIndex(), verbosity );
510  //
511  mult( dy, sensor_response, iybp );
512 
513  // Difference spectrum
514  for( Index i=0; i<n1y; i++ )
515  { dy[i] = ( dy[i]- yb[i] ) / rq.Perturbation(); }
516 
517  // Put into jacobian
518  jacobian(rowind,it) = dy;
519 
520  // Result from next loop shall go into next column of J
521  it++;
522  }
523  }
524  }
525 }
526 
527 
528 
529 
530 
531 //----------------------------------------------------------------------------
532 // Frequency:
533 //----------------------------------------------------------------------------
534 
535 /* Workspace method: Doxygen documentation will be auto-generated */
537  Workspace& ws _U_,
538  ArrayOfRetrievalQuantity& jacobian_quantities,
539  Agenda& jacobian_agenda,
540  const Vector& f_grid,
541  const String& calcmode,
542  const Numeric& df,
543  const Index& do_stretch,
544  const Verbosity& )
545 {
546  // Check that this type of frequency fit is not already included in the
547  // jacobian.
548  for( Index it=0; it<jacobian_quantities.nelem(); it++ )
549  {
550  if (jacobian_quantities[it].MainTag()== FREQUENCY_MAINTAG &&
551  jacobian_quantities[it].Subtag() == FREQUENCY_SUBTAG_A )
552  {
553  ostringstream os;
554  os << "This type of frequency fit is already included in\n"
555  << "*jacobian_quantities*.";
556  throw runtime_error(os.str());
557  }
558  }
559 
560  // Check that do_stretch is 0 or 1
561  if( do_stretch!=0 && do_stretch!=1 )
562  throw runtime_error( "The argument *do_stretch* must be 0 or 1." );
563 
564  // Checks of df
565  if( df <= 0 )
566  throw runtime_error( "The argument *df* must be > 0." );
567  if( df > 1e6 )
568  throw runtime_error( "The argument *df* is not allowed to exceed 1 MHz." );
569  const Index nf = f_grid.nelem();
570  const Numeric maxdf = f_grid[nf-1] - f_grid[nf-2];
571  if( calcmode == "interp" && df > maxdf )
572  {
573  ostringstream os;
574  os << "The value of *df* is too big with respect to spacing of "
575  << "*f_grid*.\nWith *calcmode* set to \"interp\", the maximum "
576  << "value of *df* equals\nthe spacing between the two last "
577  << "elements of *f_grid*.\n"
578  << "This spacing is : " <<maxdf/1e3 << " kHz\n"
579  << "The value of df is: " << df/1e3 << " kHz";
580  throw runtime_error(os.str());
581  }
582 
583  // Create the new retrieval quantity
587  rq.Analytical( 0 );
588  rq.Perturbation( df );
589  // Shift and stretch are treated as order 0 and 1
590  Vector grid(0,1+do_stretch,1);
591  ArrayOfVector grids(1,grid);
592  rq.Grids(grids);
593 
594  // Add pointing method to the jacobian agenda
595  if( calcmode == "interp" )
596  {
598  jacobian_agenda.append( "jacobianCalcFreqShiftAndStretchInterp", "" );
599  }
600  else
601  throw runtime_error( "Possible choices for *calcmode* are \"interp\"." );
602 
603  // Add it to the *jacobian_quantities*
604  jacobian_quantities.push_back( rq );
605 }
606 
607 
608 
609 /* Workspace method: Doxygen documentation will be auto-generated */
611  Matrix& jacobian,
612  const Index& imblock,
613  const Vector& iyb,
614  const Vector& yb,
615  const Index& stokes_dim,
616  const Vector& f_grid,
617  const Vector& mblock_za_grid,
618  const Vector& mblock_aa_grid,
619  const Index& antenna_dim,
620  const Sparse& sensor_response,
621  const ArrayOfIndex& sensor_response_pol_grid,
622  const Vector& sensor_response_f_grid,
623  const Vector& sensor_response_za_grid,
624  const ArrayOfRetrievalQuantity& jacobian_quantities,
625  const ArrayOfArrayOfIndex& jacobian_indices,
626  const Verbosity& )
627 {
628  // Set some useful (and needed) variables.
630  ArrayOfIndex ji;
631 
632  // Find the retrieval quantity related to this method, i.e. Pointing
633  // za offset. This works since the combined MainTag and Subtag is individual.
634  bool found = false;
635  for( Index n=0; n<jacobian_quantities.nelem() && !found; n++ )
636  {
637  if( jacobian_quantities[n].MainTag() == FREQUENCY_MAINTAG &&
638  jacobian_quantities[n].Subtag() == FREQUENCY_SUBTAG_A &&
639  jacobian_quantities[n].Mode() == FREQUENCY_CALCMODE_A )
640  {
641  found = true;
642  rq = jacobian_quantities[n];
643  ji = jacobian_indices[n];
644  }
645  }
646  if( !found )
647  {
648  throw runtime_error(
649  "There is no such frequency retrieval quantity defined.\n" );
650  }
651 
652  // Check that sensor_response is consistent with yb and iyb
653  //
654  if( sensor_response.nrows() != yb.nelem() )
655  throw runtime_error(
656  "Mismatch in size between *sensor_response* and *yb*." );
657  if( sensor_response.ncols() != iyb.nelem() )
658  throw runtime_error(
659  "Mismatch in size between *sensor_response* and *iyb*." );
660 
661 
662  // Size and another check of sensor_response
663  //
664  const Index nf = sensor_response_f_grid.nelem();
665  const Index npol = sensor_response_pol_grid.nelem();
666  const Index nza = sensor_response_za_grid.nelem();
667 
668 
669  // Get disturbed (part of) y
670  //
671  const Index n1y = sensor_response.nrows();
672  Vector dy( n1y );
673  {
674  const Index nf2 = f_grid.nelem();
675  const Index nza2 = mblock_za_grid.nelem();
676  Index naa2 = mblock_aa_grid.nelem();
677  if( antenna_dim == 1 )
678  { naa2 = 1; }
679  const Index niyb = nf2 * nza2 * naa2 * stokes_dim;
680 
681  // Interpolation weights
682  //
683  const Index porder = 3;
684  //
685  ArrayOfGridPosPoly gp( nf2 );
686  Matrix itw( nf2, porder+1) ;
687  Vector fg_new = f_grid, iyb2(niyb);
688  //
689  fg_new += rq.Perturbation();
690  gridpos_poly( gp, f_grid, fg_new, porder, 1.0 );
691  interpweights( itw, gp );
692 
693  // Do interpolation
694  for( Index iza=0; iza<nza2; iza++ )
695  {
696  for( Index iaa=0; iaa<naa2; iaa++ )
697  {
698  const Index row0 =( iza*naa2 + iaa ) * nf2 * stokes_dim;
699 
700  for( Index is=0; is<stokes_dim; is++ )
701  {
702  interp( iyb2[Range(row0+is,nf2,stokes_dim)], itw,
703  iyb[Range(row0+is,nf2,stokes_dim)], gp );
704  }
705  }
706  }
707 
708  // Determine differnce
709  //
710  mult( dy, sensor_response, iyb2 );
711  //
712  for( Index i=0; i<n1y; i++ )
713  { dy[i] = ( dy[i]- yb[i] ) / rq.Perturbation(); }
714  }
715 
716  //--- Create jacobians ---
717  //
718  const Range rowind = get_rowindex_for_mblock( sensor_response, imblock );
719  const Index lg = rq.Grids()[0].nelem();
720  Index it = ji[0];
721 
722  // Shift jacobian
723  jacobian(rowind,it) = dy;
724 
725  // Stretch jacobian
726  if( lg > 1 )
727  {
728  const Index row0 = rowind.get_start();
729  Vector w;
730 
731  assert( Numeric(1) == rq.Grids()[0][1] );
732  //
733  polynomial_basis_func( w, sensor_response_f_grid, 1 );
734  //
735  it += 1;
736  //
737  for( Index l=0; l<nza; l++ )
738  {
739  for( Index f=0; f<nf; f++ )
740  {
741  const Index row1 = (l*nf + f)*npol;
742  for( Index p=0; p<npol; p++ )
743  { jacobian(row0+row1+p,it) = w[f] * dy[row1+p]; }
744  }
745  }
746  }
747 }
748 
749 
750 
751 
752 
753 //----------------------------------------------------------------------------
754 // Pointing:
755 //----------------------------------------------------------------------------
756 
757 /* Workspace method: Doxygen documentation will be auto-generated */
759  Workspace& ws _U_,
760  ArrayOfRetrievalQuantity& jacobian_quantities,
761  Agenda& jacobian_agenda,
762  const Matrix& sensor_pos,
763  const Vector& sensor_time,
764  const Index& poly_order,
765  const String& calcmode,
766  const Numeric& dza,
767  const Verbosity& )
768 {
769  // Check that poly_order is -1 or positive
770  if( poly_order < -1 )
771  throw runtime_error(
772  "The polynomial order has to be positive or -1 for gitter." );
773 
774  // Check that this jacobian type is not already included.
775  for( Index it=0; it<jacobian_quantities.nelem(); it++ )
776  {
777  if (jacobian_quantities[it].MainTag()== POINTING_MAINTAG &&
778  jacobian_quantities[it].Subtag() == POINTING_SUBTAG_A )
779  {
780  ostringstream os;
781  os << "Fit of zenith angle pointing off-set is already included in\n"
782  << "*jacobian_quantities*.";
783  throw runtime_error(os.str());
784  }
785  }
786 
787  // Checks of dza
788  if( dza <= 0 )
789  throw runtime_error( "The argument *dza* must be > 0." );
790  if( dza > 0.1 )
791  throw runtime_error(
792  "The argument *dza* is not allowed to exceed 0.1 deg." );
793 
794  // Check that sensor_time is consistent with sensor_pos
795  if( sensor_time.nelem() != sensor_pos.nrows() )
796  {
797  ostringstream os;
798  os << "The WSV *sensor_time* must be defined for every "
799  << "measurement block.\n";
800  throw runtime_error(os.str());
801  }
802 
803  // Do not allow that *poly_order* is not too large compared to *sensor_time*
804  if( poly_order > sensor_time.nelem()-1 )
805  { throw runtime_error(
806  "The polynomial order can not be >= length of *sensor_time*." ); }
807 
808  // Create the new retrieval quantity
812  rq.Analytical( 0 );
813  rq.Perturbation( dza );
814 
815 
816  // To store the value or the polynomial order, create a vector with length
817  // poly_order+1, in case of gitter set the size of the grid vector to be the
818  // number of measurement blocks, all elements set to -1.
819  Vector grid(0,poly_order+1,1);
820  if( poly_order == -1 )
821  {
822  grid.resize(sensor_pos.nrows());
823  grid = -1.0;
824  }
825  ArrayOfVector grids(1,grid);
826  rq.Grids(grids);
827 
828  if( calcmode == "recalc" )
829  {
830  rq.Mode( POINTING_CALCMODE_A );
831  jacobian_agenda.append( "jacobianCalcPointingZaRecalc", "" );
832  }
833  else if( calcmode == "interp" )
834  {
835  rq.Mode( POINTING_CALCMODE_B );
836  jacobian_agenda.append( "jacobianCalcPointingZaInterp", "" );
837  }
838  else
839  throw runtime_error(
840  "Possible choices for *calcmode* are \"recalc\" and \"interp\"." );
841 
842  // Add it to the *jacobian_quantities*
843  jacobian_quantities.push_back( rq );
844 }
845 
846 
847 
848 /* Workspace method: Doxygen documentation will be auto-generated */
850  Matrix& jacobian,
851  const Index& imblock,
852  const Vector& iyb,
853  const Vector& yb _U_,
854  const Index& stokes_dim,
855  const Vector& f_grid,
856  const Matrix& sensor_los,
857  const Vector& mblock_za_grid,
858  const Vector& mblock_aa_grid,
859  const Index& antenna_dim,
860  const Sparse& sensor_response,
861  const Vector& sensor_time,
862  const ArrayOfRetrievalQuantity& jacobian_quantities,
863  const ArrayOfArrayOfIndex& jacobian_indices,
864  const Verbosity& )
865 {
866  // Set some useful variables.
868  ArrayOfIndex ji;
869 
870  // Find the retrieval quantity related to this method.
871  // This works since the combined MainTag and Subtag is individual.
872  bool found = false;
873  for( Index n=0; n<jacobian_quantities.nelem() && !found; n++ )
874  {
875  if( jacobian_quantities[n].MainTag() == POINTING_MAINTAG &&
876  jacobian_quantities[n].Subtag() == POINTING_SUBTAG_A &&
877  jacobian_quantities[n].Mode() == POINTING_CALCMODE_B )
878  {
879  found = true;
880  rq = jacobian_quantities[n];
881  ji = jacobian_indices[n];
882  }
883  }
884  if( !found )
885  { throw runtime_error(
886  "There is no such pointing retrieval quantity defined.\n" );
887  }
888 
889 
890  // Get "dy", by inter/extra-polation of existing iyb
891  //
892  const Index n1y = sensor_response.nrows();
893  Vector dy( n1y );
894  {
895  // Sizes
896  const Index nf = f_grid.nelem();
897  const Index nza = mblock_za_grid.nelem();
898  Index naa = mblock_aa_grid.nelem();
899  if( antenna_dim == 1 )
900  { naa = 1; }
901 
902  // Shifted zenith angles
903  Vector za1 = mblock_za_grid; za1 -= rq.Perturbation();
904  Vector za2 = mblock_za_grid; za2 += rq.Perturbation();
905 
906  // Find interpolation weights
907  ArrayOfGridPos gp1(nza), gp2(nza);
908  gridpos( gp1, mblock_za_grid, za1, 1e6 ); // Note huge extrapolation!
909  gridpos( gp2, mblock_za_grid, za2, 1e6 ); // Note huge extrapolation!
910  Matrix itw1(nza,2), itw2(nza,2);
911  interpweights( itw1, gp1 );
912  interpweights( itw2, gp2 );
913 
914  // Make interpolation (for all azimuth angles, frequencies and Stokes)
915  //
916  Vector iyb1(iyb.nelem()), iyb2(iyb.nelem());
917  //
918  for( Index iaa=0; iaa<naa; iaa++ )
919  {
920  for( Index iv=0; iv<nf; iv++ )
921  {
922  for( Index is=0; is<stokes_dim; is++ )
923  {
924  const Range r( iaa*nza*nf*stokes_dim+iv*stokes_dim+is,
925  nza, nf*stokes_dim );
926  interp( iyb1[r], itw1, iyb[r], gp1 );
927  interp( iyb2[r], itw2, iyb[r], gp2 );
928  }
929  }
930  }
931 
932  // Apply sensor and take difference
933  //
934  Vector y1(n1y), y2(n1y);
935  mult( y1, sensor_response, iyb1 );
936  mult( y2, sensor_response, iyb2 );
937  //
938  for( Index i=0; i<n1y; i++ )
939  { dy[i] = ( y2[i]- y1[i] ) / ( 2* rq.Perturbation() ); }
940  }
941 
942  //--- Create jacobians ---
943 
944  const Index lg = rq.Grids()[0].nelem();
945  const Index it = ji[0];
946  const Range rowind = get_rowindex_for_mblock( sensor_response, imblock );
947  const Index row0 = rowind.get_start();
948 
949  // Handle gitter seperately
950  if( rq.Grids()[0][0] == -1 ) // Not all values are set here,
951  { // but should already have been
952  assert( lg == sensor_los.nrows() ); // set to 0
953  assert( rq.Grids()[0][imblock] == -1 );
954  jacobian(rowind,it+imblock) = dy;
955  }
956 
957  // Polynomial representation
958  else
959  {
960  Vector w;
961  for( Index c=0; c<lg; c++ )
962  {
963  assert( Numeric(c) == rq.Grids()[0][c] );
964  //
965  polynomial_basis_func( w, sensor_time, c );
966  //
967  for( Index i=0; i<n1y; i++ )
968  { jacobian(row0+i,it+c) = w[imblock] * dy[i]; }
969  }
970  }
971 }
972 
973 
974 
975 /* Workspace method: Doxygen documentation will be auto-generated */
977  Workspace& ws,
978  Matrix& jacobian,
979  const Index& imblock,
980  const Vector& iyb _U_,
981  const Vector& yb,
982  const Index& atmosphere_dim,
983  const Vector& p_grid,
984  const Vector& lat_grid,
985  const Vector& lon_grid,
986  const Tensor3& t_field,
987  const Tensor3& z_field,
988  const Tensor4& vmr_field,
989  const Index& cloudbox_on,
990  const Index& stokes_dim,
991  const Vector& f_grid,
992  const Matrix& sensor_pos,
993  const Matrix& sensor_los,
994  const Vector& mblock_za_grid,
995  const Vector& mblock_aa_grid,
996  const Index& antenna_dim,
997  const Sparse& sensor_response,
998  const Vector& sensor_time,
999  const Agenda& iy_clearsky_agenda,
1000  const String& y_unit,
1001  const ArrayOfRetrievalQuantity& jacobian_quantities,
1002  const ArrayOfArrayOfIndex& jacobian_indices,
1003  const Verbosity& verbosity )
1004 {
1005  // Set some useful variables.
1006  RetrievalQuantity rq;
1007  ArrayOfIndex ji;
1008 
1009  // Find the retrieval quantity related to this method.
1010  // This works since the combined MainTag and Subtag is individual.
1011  bool found = false;
1012  for( Index n=0; n<jacobian_quantities.nelem() && !found; n++ )
1013  {
1014  if( jacobian_quantities[n].MainTag() == POINTING_MAINTAG &&
1015  jacobian_quantities[n].Subtag() == POINTING_SUBTAG_A &&
1016  jacobian_quantities[n].Mode() == POINTING_CALCMODE_A )
1017  {
1018  found = true;
1019  rq = jacobian_quantities[n];
1020  ji = jacobian_indices[n];
1021  }
1022  }
1023  if( !found )
1024  { throw runtime_error(
1025  "There is no such pointing retrieval quantity defined.\n" );
1026  }
1027 
1028 
1029  // Get "dy", by calling iyb_calc with shifted sensor_los.
1030  //
1031  const Index n1y = sensor_response.nrows();
1032  Vector dy( n1y );
1033  {
1034  Index iyet;
1035  Vector iyb2, iye, iyb_aux;
1036  Matrix los = sensor_los;
1037  ArrayOfMatrix diyb_dx;
1038 
1039  los(joker,0) += rq.Perturbation();
1040 
1041  iyb_calc( ws, iyb2, iye, iyet, iyb_aux, diyb_dx, imblock,
1042  atmosphere_dim, p_grid, lat_grid, lon_grid,
1043  t_field, z_field, vmr_field, cloudbox_on, stokes_dim,
1044  f_grid, sensor_pos, los, mblock_za_grid, mblock_aa_grid,
1045  antenna_dim, iy_clearsky_agenda, y_unit,
1047  verbosity );
1048 
1049  // Apply sensor and take difference
1050  //
1051  mult( dy, sensor_response, iyb2 );
1052  //
1053  for( Index i=0; i<n1y; i++ )
1054  { dy[i] = ( dy[i]- yb[i] ) / rq.Perturbation(); }
1055  }
1056 
1057  //--- Create jacobians ---
1058 
1059  const Index lg = rq.Grids()[0].nelem();
1060  const Index it = ji[0];
1061  const Range rowind = get_rowindex_for_mblock( sensor_response, imblock );
1062  const Index row0 = rowind.get_start();
1063 
1064  // Handle gitter seperately
1065  if( rq.Grids()[0][0] == -1 ) // Not all values are set here,
1066  { // but should already have been
1067  assert( lg == sensor_los.nrows() ); // set to 0
1068  assert( rq.Grids()[0][imblock] == -1 );
1069  jacobian(rowind,it+imblock) = dy;
1070  }
1071 
1072  // Polynomial representation
1073  else
1074  {
1075  Vector w;
1076  for( Index c=0; c<lg; c++ )
1077  {
1078  assert( Numeric(c) == rq.Grids()[0][c] );
1079  //
1080  polynomial_basis_func( w, sensor_time, c );
1081  //
1082  for( Index i=0; i<n1y; i++ )
1083  { jacobian(row0+i,it+c) = w[imblock] * dy[i]; }
1084  }
1085  }
1086 }
1087 
1088 
1089 
1090 
1091 
1092 //----------------------------------------------------------------------------
1093 // Polynomial baseline fits:
1094 //----------------------------------------------------------------------------
1095 
1096 /* Workspace method: Doxygen documentation will be auto-generated */
1098  Workspace& ws _U_,
1100  Agenda& jacobian_agenda,
1101  const ArrayOfIndex& sensor_response_pol_grid,
1102  const Vector& sensor_response_f_grid,
1103  const Vector& sensor_response_za_grid,
1104  const Matrix& sensor_pos,
1105  const Index& poly_order,
1106  const Index& no_pol_variation,
1107  const Index& no_los_variation,
1108  const Index& no_mblock_variation,
1109  const Verbosity& )
1110 {
1111  // Check that poly_order is >= 0
1112  if( poly_order < 0 )
1113  throw runtime_error(
1114  "The polynomial order has to be >= 0.");
1115 
1116  // Compare poly_order with number of frequency points
1117  if( poly_order > sensor_response_f_grid.nelem() - 1 )
1118  {
1119  ostringstream os;
1120  os << "The polynomial order can not exceed the length of\n"
1121  << "*sensor_response_f_grid* -1.";
1122  throw runtime_error(os.str());
1123  }
1124 
1125  // Check that polyfit is not already included in the jacobian.
1126  for( Index it=0; it<jq.nelem(); it++ )
1127  {
1128  if( jq[it].MainTag() == POLYFIT_MAINTAG )
1129  {
1130  ostringstream os;
1131  os << "Polynomial baseline fit is already included in\n"
1132  << "*jacobian_quantities*.";
1133  throw runtime_error(os.str());
1134  }
1135  }
1136 
1137  // "Grids"
1138  //
1139  // Grid dimensions correspond here to
1140  // 1: polynomial order
1141  // 2: polarisation
1142  // 3: viewing direction
1143  // 4: measurement block
1144  //
1145  ArrayOfVector grids(4);
1146  //
1147  if( no_pol_variation )
1148  grids[1] = Vector(1,1);
1149  else
1150  grids[1] = Vector(0,sensor_response_pol_grid.nelem(),1);
1151  if( no_los_variation )
1152  grids[2] = Vector(1,1);
1153  else
1154  grids[2] = Vector(0,sensor_response_za_grid.nelem(),1);
1155  if( no_mblock_variation )
1156  grids[3] = Vector(1,1);
1157  else
1158  grids[3] = Vector(0,sensor_pos.nrows(),1);
1159 
1160  // Create the new retrieval quantity
1162  rq.MainTag( POLYFIT_MAINTAG );
1163  rq.Mode( "" );
1164  rq.Analytical( 0 );
1165  rq.Perturbation( 0 );
1166 
1167  // Each polynomial coeff. is treated as a retrieval quantity
1168  //
1169  for( Index i=0; i<=poly_order; i++ )
1170  {
1171  ostringstream sstr;
1172  sstr << "Coefficient " << i;
1173  rq.Subtag( sstr.str() );
1174 
1175  // Grid is a scalar, use polynomial coeff.
1176  grids[0] = Vector(1,(Numeric)i);
1177  rq.Grids( grids );
1178 
1179  // Add it to the *jacobian_quantities*
1180  jq.push_back( rq );
1181 
1182  // Add pointing method to the jacobian agenda
1183  jacobian_agenda.append( "jacobianCalcPolyfit", i );
1184  }
1185 }
1186 
1187 
1188 
1189 /* Workspace method: Doxygen documentation will be auto-generated */
1191  Matrix& jacobian,
1192  const Index& imblock,
1193  const Vector& iyb _U_,
1194  const Vector& yb _U_,
1195  const Sparse& sensor_response,
1196  const ArrayOfIndex& sensor_response_pol_grid,
1197  const Vector& sensor_response_f_grid,
1198  const Vector& sensor_response_za_grid,
1199  const ArrayOfRetrievalQuantity& jacobian_quantities,
1200  const ArrayOfArrayOfIndex& jacobian_indices,
1201  const Index& poly_coeff,
1202  const Verbosity& )
1203 {
1204  // Find the retrieval quantity related to this method
1205  RetrievalQuantity rq;
1206  ArrayOfIndex ji;
1207  bool found = false;
1208  Index iq;
1209  ostringstream sstr;
1210  sstr << "Coefficient " << poly_coeff;
1211  for( iq=0; iq<jacobian_quantities.nelem() && !found; iq++ )
1212  {
1213  if( jacobian_quantities[iq].MainTag() == POLYFIT_MAINTAG &&
1214  jacobian_quantities[iq].Subtag() == sstr.str() )
1215  {
1216  found = true;
1217  break;
1218  }
1219  }
1220  if( !found )
1221  {
1222  throw runtime_error( "There is no Polyfit jacobian defined, in general "
1223  "or for the selected polynomial coefficient.\n");
1224  }
1225 
1226  // Size and check of sensor_response
1227  //
1228  const Index nf = sensor_response_f_grid.nelem();
1229  const Index npol = sensor_response_pol_grid.nelem();
1230  const Index nza = sensor_response_za_grid.nelem();
1231 
1232  // Make a vector with values to distribute over *jacobian*
1233  //
1234  Vector w;
1235  //
1236  polynomial_basis_func( w, sensor_response_f_grid, poly_coeff );
1237 
1238  // Fill J
1239  //
1240  ArrayOfVector jg = jacobian_quantities[iq].Grids();
1241  const Index n1 = jg[1].nelem();
1242  const Index n2 = jg[2].nelem();
1243  const Index n3 = jg[3].nelem();
1244  const Range rowind = get_rowindex_for_mblock( sensor_response, imblock );
1245  const Index row4 = rowind.get_start();
1246  Index col4 = jacobian_indices[iq][0];
1247 
1248  if( n3 > 1 )
1249  { col4 += imblock*n2*n1; }
1250 
1251  for( Index l=0; l<nza; l++ )
1252  {
1253  const Index row3 = row4 + l*nf*npol;
1254  const Index col3 = col4 + l*n1;
1255 
1256  for( Index f=0; f<nf; f++ )
1257  {
1258  const Index row2 = row3 + f*npol;
1259 
1260  for( Index p=0; p<npol; p++ )
1261  {
1262  Index col1 = col3;
1263  if( n1 > 1 )
1264  { col1 += p; }
1265 
1266  jacobian(row2+p,col1) = w[f];
1267  }
1268  }
1269  }
1270 }
1271 
1272 
1273 
1274 
1275 
1276 //----------------------------------------------------------------------------
1277 // Temperatures (atmospheric):
1278 //----------------------------------------------------------------------------
1279 
1280 /* Workspace method: Doxygen documentation will be auto-generated */
1282  Workspace& ws _U_,
1284  Agenda& jacobian_agenda,
1285  const Index& atmosphere_dim,
1286  const Vector& p_grid,
1287  const Vector& lat_grid,
1288  const Vector& lon_grid,
1289  const Vector& rq_p_grid,
1290  const Vector& rq_lat_grid,
1291  const Vector& rq_lon_grid,
1292  const String& hse,
1293  const String& method,
1294  const Numeric& dx,
1295  const Verbosity& verbosity )
1296 {
1297  CREATE_OUT3
1298 
1299  // Check that temperature is not already included in the jacobian.
1300  // We only check the main tag.
1301  for (Index it=0; it<jq.nelem(); it++)
1302  {
1303  if( jq[it].MainTag() == TEMPERATURE_MAINTAG )
1304  {
1305  ostringstream os;
1306  os << "Temperature is already included in *jacobian_quantities*.";
1307  throw runtime_error(os.str());
1308  }
1309  }
1310 
1311  // Check that no number density retrieval has been added
1312  for (Index it=0; it<jq.nelem(); it++)
1313  {
1314  if( jq[it].MainTag() == ABSSPECIES_MAINTAG && jq[it].Mode() == "nd" )
1315  {
1316  ostringstream os;
1317  os <<
1318  "Retrieval of temperature and number densities can not be mixed.";
1319  throw runtime_error(os.str());
1320  }
1321  }
1322 
1323  // Check retrieval grids, here we just check the length of the grids
1324  // vs. the atmosphere dimension
1325  ArrayOfVector grids(atmosphere_dim);
1326  {
1327  ostringstream os;
1328  if( !check_retrieval_grids( grids, os, p_grid, lat_grid, lon_grid,
1329  rq_p_grid, rq_lat_grid, rq_lon_grid,
1330  "retrieval pressure grid",
1331  "retrieval latitude grid",
1332  "retrievallongitude_grid",
1333  atmosphere_dim ) )
1334  throw runtime_error(os.str());
1335  }
1336 
1337  // Check that method is either "analytic" or "perturbation"
1338  bool analytical;
1339  if( method == "perturbation" )
1340  { analytical = 0; }
1341  else if( method == "analytical" )
1342  { analytical = 1; }
1343  else
1344  {
1345  ostringstream os;
1346  os << "The method for atmospheric temperature retrieval can only be "
1347  << "\"analytical\"\n or \"perturbation\".";
1348  throw runtime_error(os.str());
1349  }
1350 
1351  // Set subtag
1352  String subtag;
1353  if( hse == "on" )
1354  { subtag = "HSE on"; }
1355  else if( hse == "off" )
1356  { subtag = "HSE off"; }
1357  else
1358  {
1359  ostringstream os;
1360  os << "The keyword for hydrostatic equilibrium can only be set to\n"
1361  << "\"on\" or \"off\"\n";
1362  throw runtime_error(os.str());
1363  }
1364 
1365  // Create the new retrieval quantity
1368  rq.Subtag( subtag );
1369  rq.Mode( "abs" );
1370  rq.Analytical( analytical );
1371  rq.Perturbation( dx );
1372  rq.Grids( grids );
1373 
1374  // Add it to the *jacobian_quantities*
1375  jq.push_back( rq );
1376 
1377  if( analytical )
1378  {
1379  out3 << " Calculations done by semi-analytical expression.\n";
1380  jacobian_agenda.append( "jacobianCalcTemperatureAnalytical", TokVal() );
1381  }
1382  else
1383  {
1384  out3 << " Calculations done by perturbations, of size " << dx << ".\n";
1385 
1386  jacobian_agenda.append( "jacobianCalcTemperaturePerturbations", "" );
1387  }
1388 }
1389 
1390 
1391 
1392 /* Workspace method: Doxygen documentation will be auto-generated */
1394  Matrix& jacobian _U_,
1395  const Index& imblock _U_,
1396  const Vector& iyb _U_,
1397  const Vector& yb _U_,
1398  const Verbosity& )
1399 {
1400  /* Nothing to do here for the analytical case, this function just exists
1401  to satisfy the required inputs and outputs of the jacobian_agenda */
1402 }
1403 
1404 
1405 
1406 
1407 /* Workspace method: Doxygen documentation will be auto-generated */
1409  Workspace& ws,
1410  Matrix& jacobian,
1411  const Index& imblock,
1412  const Vector& iyb _U_,
1413  const Vector& yb,
1414  const Index& atmosphere_dim,
1415  const Vector& p_grid,
1416  const Vector& lat_grid,
1417  const Vector& lon_grid,
1418  const Tensor3& t_field,
1419  const Tensor3& z_field,
1420  const Tensor4& vmr_field,
1421  const ArrayOfArrayOfSpeciesTag& abs_species,
1422  const Matrix& r_geoid,
1423  const Matrix& z_surface,
1424  const Index& cloudbox_on,
1425  const Index& stokes_dim,
1426  const Vector& f_grid,
1427  const Matrix& sensor_pos,
1428  const Matrix& sensor_los,
1429  const Vector& mblock_za_grid,
1430  const Vector& mblock_aa_grid,
1431  const Index& antenna_dim,
1432  const Sparse& sensor_response,
1433  const Agenda& iy_clearsky_agenda,
1434  const String& y_unit,
1435  const Numeric& p_hse,
1436  const Numeric& z_hse_accuracy,
1437  const ArrayOfRetrievalQuantity& jacobian_quantities,
1438  const ArrayOfArrayOfIndex& jacobian_indices,
1439  const Verbosity& verbosity )
1440 {
1441  // Set some useful variables.
1442  RetrievalQuantity rq;
1443  ArrayOfIndex ji;
1444  Index it;
1445 
1446  // Find the retrieval quantity related to this method, i.e. Temperature.
1447  // For temperature only the main tag is checked.
1448  bool found = false;
1449  for( Index n=0; n<jacobian_quantities.nelem() && !found; n++ )
1450  {
1451  if( jacobian_quantities[n].MainTag() == TEMPERATURE_MAINTAG )
1452  {
1453  found = true;
1454  rq = jacobian_quantities[n];
1455  ji = jacobian_indices[n];
1456  }
1457  }
1458  if( !found )
1459  {
1460  ostringstream os;
1461  os << "There is no temperature retrieval quantities defined.\n";
1462  throw runtime_error(os.str());
1463  }
1464 
1465  if( rq.Analytical() )
1466  {
1467  ostringstream os;
1468  os << "This WSM handles only perturbation calculations.\n"
1469  << "Are you using the method manually?";
1470  throw runtime_error(os.str());
1471  }
1472 
1473  // Store the start JacobianIndices and the Grids for this quantity
1474  it = ji[0];
1475  ArrayOfVector jg = rq.Grids();
1476 
1477  // "Perturbation mode". 1 means absolute perturbations
1478  const Index pertmode = 1;
1479 
1480  // For each atmospheric dimension option calculate a ArrayOfGridPos,
1481  // these will be used to interpolate a perturbation into the atmospheric
1482  // grids.
1483  ArrayOfGridPos p_gp, lat_gp, lon_gp;
1484  Index j_p = jg[0].nelem();
1485  Index j_lat = 1;
1486  Index j_lon = 1;
1487  //
1488  get_perturbation_gridpos( p_gp, p_grid, jg[0], true );
1489  //
1490  if( atmosphere_dim >= 2 )
1491  {
1492  j_lat = jg[1].nelem();
1493  get_perturbation_gridpos( lat_gp, lat_grid, jg[1], false );
1494  if( atmosphere_dim == 3 )
1495  {
1496  j_lon = jg[2].nelem();
1497  get_perturbation_gridpos( lon_gp, lon_grid, jg[2], false );
1498  }
1499  }
1500 
1501  // Local copy of z_field.
1502  Tensor3 z = z_field;
1503 
1504  // Loop through the retrieval grid and calculate perturbation effect
1505  //
1506  const Index n1y = sensor_response.nrows();
1507  Vector dy( n1y );
1508  const Range rowind = get_rowindex_for_mblock( sensor_response, imblock );
1509  //
1510  for( Index lon_it=0; lon_it<j_lon; lon_it++ )
1511  {
1512  for( Index lat_it=0; lat_it<j_lat; lat_it++ )
1513  {
1514  for( Index p_it=0; p_it<j_p; p_it++ )
1515  {
1516  // Perturbed temperature field
1517  Tensor3 t_p = t_field;
1518 
1519  // Here we calculate the ranges of the perturbation. We want the
1520  // perturbation to continue outside the atmospheric grids for the
1521  // edge values.
1522  Range p_range = Range(0,0);
1523  Range lat_range = Range(0,0);
1524  Range lon_range = Range(0,0);
1525  get_perturbation_range( p_range, p_it, j_p );
1526  if( atmosphere_dim >= 2 )
1527  {
1528  get_perturbation_range( lat_range, lat_it, j_lat );
1529  if( atmosphere_dim == 3 )
1530  {
1531  get_perturbation_range( lon_range, lon_it, j_lon );
1532  }
1533  }
1534 
1535  // Calculate the perturbed field according to atmosphere_dim,
1536  // the number of perturbations is the length of the retrieval
1537  // grid +2 (for the end points)
1538  switch (atmosphere_dim)
1539  {
1540  case 1:
1541  {
1542  // Here we perturb a vector
1543  perturbation_field_1d( t_p(joker,lat_it,lon_it),
1544  p_gp, jg[0].nelem()+2, p_range,
1545  rq.Perturbation(), pertmode );
1546  break;
1547  }
1548  case 2:
1549  {
1550  // Here we perturb a matrix
1551  perturbation_field_2d( t_p(joker,joker,lon_it),
1552  p_gp, lat_gp, jg[0].nelem()+2,
1553  jg[1].nelem()+2, p_range, lat_range,
1554  rq.Perturbation(), pertmode );
1555  break;
1556  }
1557  case 3:
1558  {
1559  // Here we need to perturb a tensor3
1560  perturbation_field_3d( t_p(joker,joker,joker), p_gp,
1561  lat_gp, lon_gp, jg[0].nelem()+2,
1562  jg[1].nelem()+2, jg[2].nelem()+2,
1563  p_range, lat_range, lon_range,
1564  rq.Perturbation(), pertmode );
1565  break;
1566  }
1567  }
1568 
1569  // Apply HSE, if selected
1570  if( rq.Subtag() == "HSE on" )
1571  {
1572  z_fieldFromHSE( z, atmosphere_dim, p_grid, lat_grid,
1573  lon_grid, abs_species, t_p, vmr_field,
1574  r_geoid, z_surface, 1,
1575  p_hse, z_hse_accuracy, verbosity);
1576  }
1577 
1578  // Calculate the perturbed spectrum
1579  Index dummy2 = 0;
1580  Vector iybp, dummy1, dummy3;
1581  ArrayOfMatrix dummy4;
1582  //
1583  iyb_calc( ws, iybp, dummy1, dummy2, dummy3, dummy4, imblock,
1584  atmosphere_dim, p_grid, lat_grid, lon_grid,
1585  t_p, z, vmr_field, cloudbox_on, stokes_dim,
1586  f_grid, sensor_pos, sensor_los, mblock_za_grid,
1587  mblock_aa_grid, antenna_dim, iy_clearsky_agenda,
1588  y_unit, 0, ArrayOfRetrievalQuantity(),
1589  ArrayOfArrayOfIndex(), verbosity );
1590  //
1591  mult( dy, sensor_response, iybp );
1592 
1593  // Difference spectrum
1594  for( Index i=0; i<n1y; i++ )
1595  { dy[i] = ( dy[i]- yb[i] ) / rq.Perturbation(); }
1596 
1597  // Put into jacobian
1598  jacobian(rowind,it) = dy;
1599 
1600  // Result from next loop shall go into next column of J
1601  it++;
1602  }
1603  }
1604  }
1605 }
1606 
1607 
1608 
1609 
1610 
1611 
1612 
1613 
1614 
1615 
1616 
1617 //----------------------------------------------------------------------------
1618 // Old:
1619 //----------------------------------------------------------------------------
1620 
1621 
1622 // /* Workspace method: Doxygen documentation will be auto-generated */
1623 // void jacobianAddParticle(// WS Output:
1624 // ArrayOfRetrievalQuantity& jq,
1625 // Agenda& jacobian_agenda,
1626 // // WS Input:
1627 // const Matrix& jac,
1628 // const Index& atmosphere_dim,
1629 // const Vector& p_grid,
1630 // const Vector& lat_grid,
1631 // const Vector& lon_grid,
1632 // const Tensor4& pnd_field,
1633 // const Tensor5& pnd_perturb,
1634 // const ArrayOfIndex& cloudbox_limits,
1635 // // WS Generic Input:
1636 // const Vector& rq_p_grid,
1637 // const Vector& rq_lat_grid,
1638 // const Vector& rq_lon_grid,
1639 // const Verbosity& verbosity)
1640 // {
1641 // throw runtime_error("Particle jacobians not yet handled correctly.");
1642 
1643 // // Check that the jacobian matrix is empty. Otherwise it is either
1644 // // not initialised or it is closed.
1645 // if( jac.nrows()!=0 && jac.ncols()!=0 )
1646 // {
1647 // ostringstream os;
1648 // os << "The Jacobian matrix is not initialised correctly or closed.\n"
1649 // << "New retrieval quantities can not be added at this point.";
1650 // throw runtime_error(os.str());
1651 // }
1652 
1653 // // Check that pnd_perturb is consistent with pnd_field
1654 // if( pnd_perturb.nbooks()!=pnd_field.nbooks() ||
1655 // pnd_perturb.npages()!=pnd_field.npages() ||
1656 // pnd_perturb.nrows()!=pnd_field.nrows() ||
1657 // pnd_perturb.ncols()!=pnd_field.ncols() )
1658 // {
1659 // ostringstream os;
1660 // os << "The perturbation field *pnd_field_perturb* is not consistent with"
1661 // << "*pnd_field*,\none or several dimensions do not match.";
1662 // throw runtime_error(os.str());
1663 // }
1664 
1665 // // Check that particles are not already included in the jacobian.
1666 // for( Index it=0; it<jq.nelem(); it++ )
1667 // {
1668 // if( jq[it].MainTag()=="Particles" )
1669 // {
1670 // ostringstream os;
1671 // os << "The particles number densities are already included in "
1672 // << "*jacobian_quantities*.";
1673 // throw runtime_error(os.str());
1674 // }
1675 // }
1676 
1677 // // Particle Jacobian only defined for 1D and 3D atmosphere. check the
1678 // // retrieval grids, here we just check the length of the grids vs. the
1679 // // atmosphere dimension
1680 // if (atmosphere_dim==2)
1681 // {
1682 // ostringstream os;
1683 // os << "Atmosphere dimension not equal to 1 or 3. "
1684 // << "Jacobians for particle number\n"
1685 // << "density only available for 1D and 3D atmosphere.";
1686 // throw runtime_error(os.str());
1687 // }
1688 
1689 // ArrayOfVector grids(atmosphere_dim);
1690 // // The retrieval grids should only consists of gridpoints within
1691 // // the cloudbox. Setup local atmospheric fields inside the cloudbox
1692 // {
1693 // Vector p_cbox = p_grid;
1694 // Vector lat_cbox = lat_grid;
1695 // Vector lon_cbox = lon_grid;
1696 // switch (atmosphere_dim)
1697 // {
1698 // case 3:
1699 // {
1700 // lon_cbox = lon_grid[Range(cloudbox_limits[4],
1701 // cloudbox_limits[5]-cloudbox_limits[4]+1)];
1702 // }
1703 // case 2:
1704 // {
1705 // lat_cbox = lat_grid[Range(cloudbox_limits[2],
1706 // cloudbox_limits[3]-cloudbox_limits[2]+1)];
1707 // }
1708 // case 1:
1709 // {
1710 // p_cbox = p_grid[Range(cloudbox_limits[0],
1711 // cloudbox_limits[1]-cloudbox_limits[0]+1)];
1712 // }
1713 // }
1714 // ostringstream os;
1715 // if( !check_retrieval_grids( grids, os, p_cbox, lat_cbox, lon_cbox,
1716 // rq_p_grid, rq_lat_grid, rq_lon_grid,
1717 // // FIXMEOLE: These strings have to replaced later with the proper
1718 // // names from the WSM documentation in methods.cc
1719 // "rq_p_grid", "rq_lat_grid", "rq_lon_grid", atmosphere_dim ))
1720 // throw runtime_error(os.str());
1721 // }
1722 
1723 // // Common part for all particle variables
1724 // RetrievalQuantity rq = RetrievalQuantity();
1725 // rq.MainTag("Particles");
1726 // rq.Grids(grids);
1727 // rq.Analytical(0);
1728 // rq.Perturbation(-999.999);
1729 // rq.Mode("Fields *mode* and *perturbation* are not defined");
1730 
1731 // // Set info for each particle variable
1732 // for( Index ipt=0; ipt<pnd_perturb.nshelves(); ipt++ )
1733 // {
1734 // out2 << " Adding particle variable " << ipt +1
1735 // << " to *jacobian_quantities / agenda*.\n";
1736 
1737 // ostringstream os;
1738 // os << "Variable " << ipt+1;
1739 // rq.Subtag(os.str());
1740 
1741 // jq.push_back(rq);
1742 // }
1743 
1744 // // Add gas species method to the jacobian agenda
1745 // String methodname = "jacobianCalcParticle";
1746 // String kwv = "";
1747 // jacobian_agenda.append (methodname, kwv);
1748 // }
1749 
1750 
1751 
1752 
1753 
1754 
1755 
1756 
1757 
1758 
1759 
1760 
1761 // /* Workspace method: Doxygen documentation will be auto-generated */
1762 // void jacobianCalcParticle(
1763 // Workspace& ws,
1764 // // WS Output:
1765 // Matrix& jacobian,
1766 // // WS Input:
1767 // const Vector& y,
1768 // const ArrayOfRetrievalQuantity& jq,
1769 // const ArrayOfArrayOfIndex& jacobian_indices,
1770 // const Tensor5& pnd_field_perturb,
1771 // const Agenda& jacobian_particle_update_agenda,
1772 // const Agenda& ppath_step_agenda,
1773 // const Agenda& rte_agenda,
1774 // const Agenda& iy_space_agenda,
1775 // const Agenda& surface_prop_agenda,
1776 // const Agenda& iy_cloudbox_agenda,
1777 // const Index& atmosphere_dim,
1778 // const Vector& p_grid,
1779 // const Vector& lat_grid,
1780 // const Vector& lon_grid,
1781 // const Tensor3& z_field,
1782 // const Tensor3& t_field,
1783 // const Tensor4& vmr_field,
1784 // const Matrix& r_geoid,
1785 // const Matrix& z_surface,
1786 // const Index& cloudbox_on,
1787 // const ArrayOfIndex& cloudbox_limits,
1788 // const Tensor4& pnd_field,
1789 // const Sparse& sensor_response,
1790 // const Matrix& sensor_pos,
1791 // const Matrix& sensor_los,
1792 // const Vector& f_grid,
1793 // const Index& stokes_dim,
1794 // const Index& antenna_dim,
1795 // const Vector& mblock_za_grid,
1796 // const Vector& mblock_aa_grid,
1797 // const Verbosity& verbosity)
1798 // {
1799 // // Set some useful (and needed) variables.
1800 // Index n_jq = jq.nelem();
1801 // RetrievalQuantity rq;
1802 // ArrayOfIndex ji;
1803 
1804 // // Setup local atmospheric fields inside the cloudbox
1805 // Vector p_cbox = p_grid;
1806 // Vector lat_cbox = lat_grid;
1807 // Vector lon_cbox = lon_grid;
1808 // switch (atmosphere_dim)
1809 // {
1810 // case 3:
1811 // {
1812 // lon_cbox = lon_grid[Range(cloudbox_limits[4],
1813 // cloudbox_limits[5]-cloudbox_limits[4]+1)];
1814 // }
1815 // case 2:
1816 // {
1817 // lat_cbox = lat_grid[Range(cloudbox_limits[2],
1818 // cloudbox_limits[3]-cloudbox_limits[2]+1)];
1819 // }
1820 // case 1:
1821 // {
1822 // p_cbox = p_grid[Range(cloudbox_limits[0],
1823 // cloudbox_limits[1]-cloudbox_limits[0]+1)];
1824 // }
1825 // }
1826 
1827 
1828 // // Variables to handle and store perturbations
1829 // Vector yp;
1830 // Tensor4 pnd_p, base_pert = pnd_field;
1831 
1832 
1833 // // Loop particle variables (indexed by *ipt*, where *ipt* is zero based)
1834 // //
1835 // Index ipt = -1;
1836 // bool not_ready = true;
1837 
1838 // while( not_ready )
1839 // {
1840 // // Step *ipt*
1841 // ipt++;
1842 
1843 // // Define sub-tag string
1844 // ostringstream os;
1845 // os << "Variable " << ipt+1;
1846 
1847 // // Find the retrieval quantity related to this particle type
1848 // //
1849 // bool found = false;
1850 // //
1851 // for( Index n=0; n<n_jq; n++ )
1852 // {
1853 // if( jq[n].MainTag()=="Particles" && jq[n].Subtag()== os.str() )
1854 // {
1855 // found = true;
1856 // rq = jq[n];
1857 // ji = jacobian_indices[n];
1858 // n = n_jq; // To jump out of for-loop
1859 // }
1860 // }
1861 
1862 // // At least one particle type must be found
1863 // assert( !( ipt==0 && !found ) );
1864 
1865 // // Ready or something to do?
1866 // if( !found )
1867 // {
1868 // not_ready = false;
1869 // }
1870 // else
1871 // {
1872 // // Counters for report string
1873 // Index it = 0;
1874 // Index nit = ji[1] -ji[0] + 1;
1875 
1876 // // Counter for column in *jacobian*
1877 // Index icol = ji[0];
1878 
1879 // // Retrieval grid positions
1880 // ArrayOfVector jg = rq.Grids();
1881 // ArrayOfGridPos p_gp, lat_gp, lon_gp;
1882 // Index j_p = jg[0].nelem();
1883 // Index j_lat = 1;
1884 // Index j_lon = 1;
1885 // get_perturbation_gridpos( p_gp, p_cbox, jg[0], true );
1886 // if (atmosphere_dim==3)
1887 // {
1888 // j_lat = jg[1].nelem();
1889 // get_perturbation_gridpos( lat_gp, lat_cbox, jg[1], false );
1890 
1891 // j_lon = jg[2].nelem();
1892 // get_perturbation_gridpos( lon_gp, lon_cbox, jg[2], false );
1893 // }
1894 
1895 // // Give verbose output
1896 // out1 << " Calculating retrieval quantity:" << rq << "\n";
1897 
1898 
1899 // // Loop through the retrieval grid and calculate perturbation effect
1900 // for (Index lon_it=0; lon_it<j_lon; lon_it++)
1901 // {
1902 // for (Index lat_it=0; lat_it<j_lat; lat_it++)
1903 // {
1904 // for (Index p_it=0; p_it<j_p; p_it++)
1905 // {
1906 // // Update the perturbation field
1907 // pnd_p =
1908 // pnd_field_perturb( ipt, joker, joker, joker, joker);
1909 
1910 // it++;
1911 // out1 << " Calculating perturbed spectra no. " << it
1912 // << " of " << nit << "\n";
1913 
1914 // // Here we calculate the ranges of the perturbation.
1915 // // We want the perturbation to continue outside the
1916 // // atmospheric grids for the edge values.
1917 // Range p_range = Range(0,0);
1918 // Range lat_range = Range(0,0);
1919 // Range lon_range = Range(0,0);
1920 // get_perturbation_range( p_range, p_it, j_p );
1921 // if (atmosphere_dim==3)
1922 // {
1923 // get_perturbation_range( lat_range, lat_it, j_lat);
1924 // get_perturbation_range( lon_range, lon_it, j_lon);
1925 // }
1926 
1927 // // Make empty copy of pnd_pert for base functions
1928 // base_pert *= 0;
1929 
1930 // // Calculate the perturbed field according to atm_dim,
1931 // switch (atmosphere_dim)
1932 // {
1933 // case 1:
1934 // {
1935 // for( Index typ_it=0; typ_it<pnd_field.nbooks();
1936 // typ_it++ )
1937 // {
1938 // perturbation_field_1d(
1939 // base_pert(typ_it,joker,lat_it,lon_it),
1940 // p_gp, jg[0].nelem()+2, p_range, 1.0, 1 );
1941 // }
1942 // break;
1943 // }
1944 // case 3:
1945 // {
1946 // for( Index typ_it=0; typ_it<pnd_field.nrows();
1947 // typ_it++ )
1948 // {
1949 // perturbation_field_3d(
1950 // base_pert(typ_it,joker,joker,joker),
1951 // p_gp, lat_gp, lon_gp, jg[0].nelem()+2,
1952 // jg[1].nelem()+2, jg[2].nelem()+2,
1953 // p_range, lat_range, lon_range, 1.0, 1);
1954 // }
1955 // break;
1956 // }
1957 // }
1958 
1959 // // Now add the weighted perturbation field to the
1960 // // reference field and recalculate the scattered field
1961 // pnd_p *= base_pert;
1962 // pnd_p += pnd_field;
1963 // jacobian_particle_update_agendaExecute( ws, pnd_p,
1964 // jacobian_particle_update_agenda );
1965 
1966 // // Calculate the perturbed spectrum
1967 // yCalc( ws, yp, ppath_step_agenda, rte_agenda,
1968 // iy_space_agenda, surface_prop_agenda,
1969 // iy_cloudbox_agenda, atmosphere_dim,
1970 // p_grid, lat_grid, lon_grid, z_field, t_field,
1971 // vmr_field, r_geoid, z_surface, cloudbox_on,
1972 // cloudbox_limits, sensor_response, sensor_pos,
1973 // sensor_los, f_grid, stokes_dim, antenna_dim,
1974 // mblock_za_grid, mblock_aa_grid);
1975 
1976 // // Add dy as column in jacobian. Note that we just return
1977 // // the difference between the two spectra.
1978 // for( Index y_it=0; y_it<yp.nelem(); y_it++ )
1979 // {
1980 // jacobian(y_it,icol) = yp[y_it]-y[y_it];
1981 // }
1982 
1983 // // Step *icol*
1984 // icol++;
1985 // }
1986 // }
1987 // }
1988 // }
1989 // }
1990 // }
1991 
1992 
1993 
1994 
1995 
1996 
1997 
1998 
1999 
2000 
2001 
2002 
2003 
2004 
Matrix
The Matrix class.
Definition: matpackI.h:767
POINTING_MAINTAG
const String POINTING_MAINTAG
jacobianOff
void jacobianOff(Index &jacobian_do, Agenda &jacobian_agenda, ArrayOfRetrievalQuantity &jacobian_quantities, ArrayOfArrayOfIndex &jacobian_indices, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianOff.
Definition: m_jacobian.cc:159
RetrievalQuantity::Analytical
const Index & Analytical() const
Boolean to make analytical calculations (if possible).
Definition: jacobian.h:96
auto_md.h
get_perturbation_range
void get_perturbation_range(Range &range, const Index &index, const Index &length)
Get range for perturbation.
Definition: jacobian.cc:340
Sparse::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackII.cc:59
absorption.h
Declarations required for the calculation of absorption coefficients.
array_species_tag_from_string
void array_species_tag_from_string(ArrayOfSpeciesTag &tags, const String &names)
Converts a String to ArrayOfSpeciesTag.
Definition: abs_species_tags.cc:509
TokVal
This stores arbitrary token values and remembers the type.
Definition: token.h:33
RetrievalQuantity::Grids
const ArrayOfVector & Grids() const
Grids.
Definition: jacobian.h:102
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
POLYFIT_MAINTAG
const String POLYFIT_MAINTAG
joker
const Joker joker
iyb_calc
void iyb_calc(Workspace &ws, Vector &iyb, Vector &iyb_error, Index &iy_error_type, Vector &iyb_aux, ArrayOfMatrix &diyb_dx, const Index &imblock, const Index &atmosphere_dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, ConstTensor3View t_field, ConstTensor3View z_field, ConstTensor4View vmr_field, const Index &cloudbox_on, const Index &stokes_dim, ConstVectorView f_grid, ConstMatrixView sensor_pos, ConstMatrixView sensor_los, ConstVectorView mblock_za_grid, ConstVectorView mblock_aa_grid, const Index &antenna_dim, const Agenda &iy_clearsky_agenda, const String &y_unit, const Index &j_analytical_do, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const Verbosity &verbosity)
iyb_calc
Definition: m_rte.cc:588
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
FREQUENCY_SUBTAG_A
const String FREQUENCY_SUBTAG_A
Sparse
The Sparse class.
Definition: matpackII.h:55
jacobianAddFreqShiftAndStretch
void jacobianAddFreqShiftAndStretch(Workspace &ws, ArrayOfRetrievalQuantity &jacobian_quantities, Agenda &jacobian_agenda, const Vector &f_grid, const String &calcmode, const Numeric &df, const Index &do_stretch, const Verbosity &)
WORKSPACE METHOD: jacobianAddFreqShiftAndStretch.
Definition: m_jacobian.cc:536
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
ArrayOfRetrievalQuantity
Array< RetrievalQuantity > ArrayOfRetrievalQuantity
Definition: jacobian.h:120
CREATE_OUT2
#define CREATE_OUT2
Definition: messages.h:207
Tensor4
The Tensor4 class.
Definition: matpackIV.h:375
TEMPERATURE_MAINTAG
const String TEMPERATURE_MAINTAG
Tensor3::resize
void resize(Index p, Index r, Index c)
Resize function.
Definition: matpackIII.cc:863
Agenda
The Agenda class.
Definition: agenda_class.h:44
calc_nd_field
void calc_nd_field(Tensor3View &nd, const VectorView &p, const Tensor3View &t)
Calculate the number density field.
Definition: jacobian.cc:55
get_rowindex_for_mblock
Range get_rowindex_for_mblock(const Sparse &sensor_response, const Index &imblock)
get_rowindex_for_mblock
Definition: rte.cc:861
ConstTensor3View::npages
Index npages() const
Returns the number of pages.
Definition: matpackIII.h:151
FREQUENCY_MAINTAG
const String FREQUENCY_MAINTAG
dx
#define dx
Definition: continua.cc:14561
jacobianAddPolyfit
void jacobianAddPolyfit(Workspace &ws, ArrayOfRetrievalQuantity &jq, Agenda &jacobian_agenda, const ArrayOfIndex &sensor_response_pol_grid, const Vector &sensor_response_f_grid, const Vector &sensor_response_za_grid, const Matrix &sensor_pos, const Index &poly_order, const Index &no_pol_variation, const Index &no_los_variation, const Index &no_mblock_variation, const Verbosity &)
WORKSPACE METHOD: jacobianAddPolyfit.
Definition: m_jacobian.cc:1097
Array< ArrayOfIndex >
jacobianCalcAbsSpeciesAnalytical
void jacobianCalcAbsSpeciesAnalytical(Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Verbosity &)
WORKSPACE METHOD: jacobianCalcAbsSpeciesAnalytical.
Definition: m_jacobian.cc:295
Agenda::append
void append(const String &methodname, const TokVal &keywordvalue)
Appends methods to an agenda.
Definition: agenda_class.cc:67
mult
void mult(VectorView y, const ConstMatrixView &M, const ConstVectorView &x)
Matrix Vector multiplication.
Definition: matpackI.cc:1607
CREATE_OUT3
#define CREATE_OUT3
Definition: messages.h:208
messages.h
Declarations having to do with the four output streams.
_U_
#define _U_
Definition: config.h:158
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:62
jacobianCalcPointingZaRecalc
void jacobianCalcPointingZaRecalc(Workspace &ws, Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &t_field, const Tensor3 &z_field, const Tensor4 &vmr_field, const Index &cloudbox_on, const Index &stokes_dim, const Vector &f_grid, const Matrix &sensor_pos, const Matrix &sensor_los, const Vector &mblock_za_grid, const Vector &mblock_aa_grid, const Index &antenna_dim, const Sparse &sensor_response, const Vector &sensor_time, const Agenda &iy_clearsky_agenda, const String &y_unit, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianCalcPointingZaRecalc.
Definition: m_jacobian.cc:976
ArrayOfArrayOfIndex
Array< ArrayOfIndex > ArrayOfArrayOfIndex
Definition: array.h:45
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
physics_funcs.h
RetrievalQuantity::Mode
const String & Mode() const
Calculation mode.
Definition: jacobian.h:93
POINTING_CALCMODE_B
const String POINTING_CALCMODE_B
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
Verbosity
Definition: messages.h:50
POINTING_SUBTAG_A
const String POINTING_SUBTAG_A
math_funcs.h
jacobianInit
void jacobianInit(ArrayOfRetrievalQuantity &jacobian_quantities, Agenda &jacobian_agenda, const Verbosity &)
WORKSPACE METHOD: jacobianInit.
Definition: m_jacobian.cc:146
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
jacobianAddPointingZa
void jacobianAddPointingZa(Workspace &ws, ArrayOfRetrievalQuantity &jacobian_quantities, Agenda &jacobian_agenda, const Matrix &sensor_pos, const Vector &sensor_time, const Index &poly_order, const String &calcmode, const Numeric &dza, const Verbosity &)
WORKSPACE METHOD: jacobianAddPointingZa.
Definition: m_jacobian.cc:758
Matrix::resize
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1549
Agenda::check
void check(Workspace &ws, const Verbosity &verbosity)
Checks consistency of an agenda.
Definition: agenda_class.cc:92
jacobianAddAbsSpecies
void jacobianAddAbsSpecies(Workspace &ws, ArrayOfRetrievalQuantity &jq, Agenda &jacobian_agenda, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Vector &rq_p_grid, const Vector &rq_lat_grid, const Vector &rq_lon_grid, const String &species, const String &method, const String &mode, const Numeric &dx, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianAddAbsSpecies.
Definition: m_jacobian.cc:180
ConstTensor3View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackIII.h:154
interpolation_poly.h
Header file for interpolation_poly.cc.
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
jacobianCalcPointingZaInterp
void jacobianCalcPointingZaInterp(Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Index &stokes_dim, const Vector &f_grid, const Matrix &sensor_los, const Vector &mblock_za_grid, const Vector &mblock_aa_grid, const Index &antenna_dim, const Sparse &sensor_response, const Vector &sensor_time, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const Verbosity &)
WORKSPACE METHOD: jacobianCalcPointingZaInterp.
Definition: m_jacobian.cc:849
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
FREQUENCY_CALCMODE_A
const String FREQUENCY_CALCMODE_A
Sparse::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackII.cc:53
z_fieldFromHSE
void z_fieldFromHSE(Tensor3 &z_field, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const ArrayOfArrayOfSpeciesTag &abs_species, const Tensor3 &t_field, const Tensor4 &vmr_field, const Matrix &r_geoid, const Matrix &z_surface, const Index &basics_checked, const Numeric &p_hse, const Numeric &z_hse_accuracy, const Verbosity &)
WORKSPACE METHOD: z_fieldFromHSE.
Definition: m_atmosphere.cc:1781
ConstTensor3View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackIII.h:157
ABSSPECIES_MAINTAG
const String ABSSPECIES_MAINTAG
rte.h
Declaration of functions in rte.cc.
Workspace
Workspace class.
Definition: workspace_ng.h:47
Agenda::set_name
void set_name(const String &nname)
Set agenda name.
Definition: agenda_class.cc:602
chk_contains
Index chk_contains(const String &x_name, const Array< T > &x, const T &what)
Check if an array contains a value.
Definition: check_input.h:193
jacobianCalcPolyfit
void jacobianCalcPolyfit(Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Sparse &sensor_response, const ArrayOfIndex &sensor_response_pol_grid, const Vector &sensor_response_f_grid, const Vector &sensor_response_za_grid, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const Index &poly_coeff, const Verbosity &)
WORKSPACE METHOD: jacobianCalcPolyfit.
Definition: m_jacobian.cc:1190
Range::get_start
Index get_start() const
Returns the start index of the range.
Definition: matpackI.h:196
jacobianCalcAbsSpeciesPerturbations
void jacobianCalcAbsSpeciesPerturbations(Workspace &ws, Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &t_field, const Tensor3 &z_field, const Tensor4 &vmr_field, const ArrayOfArrayOfSpeciesTag &abs_species, const Index &cloudbox_on, const Index &stokes_dim, const Vector &f_grid, const Matrix &sensor_pos, const Matrix &sensor_los, const Vector &mblock_za_grid, const Vector &mblock_aa_grid, const Index &antenna_dim, const Sparse &sensor_response, const Agenda &iy_clearsky_agenda, const String &y_unit, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const String &species, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianCalcAbsSpeciesPerturbations.
Definition: m_jacobian.cc:309
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
jacobianCalcTemperatureAnalytical
void jacobianCalcTemperatureAnalytical(Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Verbosity &)
WORKSPACE METHOD: jacobianCalcTemperatureAnalytical.
Definition: m_jacobian.cc:1393
check_input.h
gridpos_poly
void gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Set up grid positions for higher order interpolation.
Definition: interpolation_poly.cc:124
Vector
The Vector class.
Definition: matpackI.h:555
jacobianAddTemperature
void jacobianAddTemperature(Workspace &ws, ArrayOfRetrievalQuantity &jq, Agenda &jacobian_agenda, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Vector &rq_p_grid, const Vector &rq_lat_grid, const Vector &rq_lon_grid, const String &hse, const String &method, const Numeric &dx, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianAddTemperature.
Definition: m_jacobian.cc:1281
jacobianCalcFreqShiftAndStretchInterp
void jacobianCalcFreqShiftAndStretchInterp(Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Index &stokes_dim, const Vector &f_grid, const Vector &mblock_za_grid, const Vector &mblock_aa_grid, const Index &antenna_dim, const Sparse &sensor_response, const ArrayOfIndex &sensor_response_pol_grid, const Vector &sensor_response_f_grid, const Vector &sensor_response_za_grid, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const Verbosity &)
WORKSPACE METHOD: jacobianCalcFreqShiftAndStretchInterp.
Definition: m_jacobian.cc:610
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
RetrievalQuantity::Subtag
const String & Subtag() const
Subtag.
Definition: jacobian.h:90
jacobianClose
void jacobianClose(Workspace &ws, Index &jacobian_do, Matrix &jacobian, ArrayOfArrayOfIndex &jacobian_indices, Agenda &jacobian_agenda, const ArrayOfRetrievalQuantity &jacobian_quantities, const Matrix &sensor_pos, const Sparse &sensor_response, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianClose.
Definition: m_jacobian.cc:79
interpweights
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Definition: interpolation.cc:756
POINTING_CALCMODE_A
const String POINTING_CALCMODE_A
arts.h
The global header file for ARTS.
RetrievalQuantity::Perturbation
const Numeric & Perturbation() const
Size of perturbation used for perturbation calculations.
Definition: jacobian.h:99
jacobianCalcTemperaturePerturbations
void jacobianCalcTemperaturePerturbations(Workspace &ws, Matrix &jacobian, const Index &imblock, const Vector &iyb, const Vector &yb, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &t_field, const Tensor3 &z_field, const Tensor4 &vmr_field, const ArrayOfArrayOfSpeciesTag &abs_species, const Matrix &r_geoid, const Matrix &z_surface, const Index &cloudbox_on, const Index &stokes_dim, const Vector &f_grid, const Matrix &sensor_pos, const Matrix &sensor_los, const Vector &mblock_za_grid, const Vector &mblock_aa_grid, const Index &antenna_dim, const Sparse &sensor_response, const Agenda &iy_clearsky_agenda, const String &y_unit, const Numeric &p_hse, const Numeric &z_hse_accuracy, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfIndex &jacobian_indices, const Verbosity &verbosity)
WORKSPACE METHOD: jacobianCalcTemperaturePerturbations.
Definition: m_jacobian.cc:1408