ARTS  1.0.222
m_wfs.cc
Go to the documentation of this file.
1 /* Copyright (C) 2000, 2001 Patrick Eriksson <patrick@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 
20 // File description
22 
36 // External declarations
39 
40 #ifdef SUNOS
41 # include <ieeefp.h>
42 #endif
43 
44 #include <math.h>
45 #include "arts.h"
46 #include "auto_md.h"
47 #include "matpackI.h"
48 #include "messages.h"
49 #include "auto_wsv.h"
50 #include "math_funcs.h"
51 #include "atm_funcs.h"
52 #include "los.h"
53 extern const Numeric PLANCK_CONST;
54 extern const Numeric BOLTZMAN_CONST;
55 
56 
57 
59 // Function(s) to join two WF matrices and related variables
61 
63 
79 void k_append (
80  Matrix& kx,
81  ArrayOfString& kx_names,
82  ArrayOfIndex& kx_lengths,
83  Matrix& kx_aux,
84  const Matrix& k,
85  const ArrayOfString& k_names,
86  const Matrix& k_aux )
87 {
88  // Size of Kx and K
89  const Index ny1 = kx.nrows(); // length of measurement vector (y)
90  const Index nx1 = kx.ncols(); // length of state vector (x)
91  const Index nri1 = kx_names.nelem(); // number of retrieval identities
92  const Index ny2 = k.nrows();
93  const Index nx2 = k.ncols();
94  const Index nri2 = k_names.nelem();
95  Index iri;
96 
97  // Make copy of Kx data.
98  Matrix ktemp(kx);
99  ArrayOfString ktemp_names(kx_names);
100  ArrayOfIndex ktemp_lengths(kx_lengths);
101  Matrix ktemp_aux(kx_aux);
102 
103 // cout << "ktemp =\n" << ktemp << "\n\n\n";
104 // cout << "ktemp_names =\n" << ktemp_names << "\n\n\n";
105 // cout << "ktemp_lengths =\n" << ktemp_lengths << "\n\n\n";
106 // cout << "ktemp_aux =\n" << ktemp_aux << "\n\n\n";
107 
108  if ( nx1 > 0 )
109  {
110  if ( ny1 != ny2 )
111  throw runtime_error(
112  "The two WF matrices have different number of rows." );
113  }
114 
115  // Reallocate the Kx data
116  kx.resize( ny2, nx1+nx2 );
117  kx_names.resize( nri1+nri2 );
118  kx_lengths.resize( nri1+nri2 );
119  kx_aux.resize( nx1+nx2, 2 );
120 
121  // Move Ktemp to Kx
122  if ( nx1 > 0 )
123  {
124  kx( Range(joker), Range(0,nx1) ) = ktemp;
125  kx_aux( Range(0,nx1), Range(joker) ) = ktemp_aux;
126  // For the Array types kx_names and kx_lenghts we cannot use Range.
127  for ( iri=0; iri<nri1; iri++ )
128  {
129  kx_lengths[iri] = ktemp_lengths[iri];
130  kx_names[iri] = ktemp_names[iri];
131  }
132  }
133 
134  // Calculate the vector length for each identity in K
135  Index l = nx2/nri2;
136 
137  // Move K to Kx
138  kx( Range(joker), Range(nx1,nx2) ) = k;
139  kx_aux( Range(nx1,nx2), Range(joker) ) = k_aux;
140  // For the Array types kx_names and kx_lenghts we cannot use Range.
141  for ( iri=0; iri<nri2; iri++ )
142  {
143  kx_names[nri1+iri] = k_names[iri];
144  kx_lengths[nri1+iri] = l;
145  }
146 }
147 
148 
149 
151 // Help functions for grid conversions
153 
155 
167 void p2grid(
168  Vector& grid,
169  const Vector& pgrid )
170 {
171  grid.resize( pgrid.nelem() );
172  grid = pgrid; // Matpack can copy the contents of
173  // vectors like this. The dimensions
174  // must be the same!
175  transform( grid, log, grid ); // Matpack has the same transform
176  // functionality like the old
177  // vecmat. THE ORDER OF THE ARGUMENTS
178  // IS DIFFERENT, THOUGH (output first).
179  grid *= -1; // Mulitply all elements with -1.
180 }
181 
182 
183 
185 
240  Matrix& is,
241  const Vector& x0,
242  const Vector& xp )
243 {
244  const Index n0 = x0.nelem(); // length of original grid
245  const Index np = xp.nelem(); // length if retrieval grid
246  Index i0, ip; // counter for each grid
247 
248  // Resize is and set all values to -1
249  is.resize( np, 2 );
250  is = -1.0; // Matpack can set all elements like this.
251 
252  // Some checks
253  if ( np < 2 )
254  throw logic_error("The retrieval grid must have a length > 1.");
255  for ( i0=1; i0<n0; i0++ )
256  {
257  if ( x0[i0-1] >= x0[i0] )
258  throw logic_error("The grids must be sorted with increasing values.");
259  }
260  for ( ip=1; ip<np; ip++ )
261  {
262  if ( xp[ip-1] >= xp[ip] )
263  throw logic_error("The grids must be sorted with increasing values.");
264  }
265 
266  // Do something only if at least one point of X0 is inside XP
267  if ( !( (x0[0]>xp[np-1]) || (x0[n0-1]<xp[0]) ) )
268  {
269 
270  // First point of XP
271  i0 = 0;
272  for ( ; x0[i0] < xp[0]; i0++ ) {}
273  if ( x0[i0] < xp[1] )
274  {
275  is(0,0) = (Numeric) i0;
276  for ( ; (i0<n0) && (x0[i0]<xp[1]); i0++ ) {}
277  is(0,1) = (Numeric) (i0 - 1);
278  }
279 
280  // Points inside XP
281  for ( ip=1; ip<(np-1); ip++ )
282  {
283  i0 = 0;
284  for ( ; (i0<n0) && (x0[i0]<=xp[ip-1]); i0++ ) {}
285  if ( (i0<n0) && (x0[i0]<xp[ip+1]) )
286  {
287  is(ip,0) = (Numeric) i0;
288  for ( ; (i0<n0) && (x0[i0]<xp[ip+1]); i0++ ) {}
289  is(ip,1) = (Numeric) (i0 - 1);
290  }
291  }
292 
293  // Last point of XP
294  i0 = 0;
295  for ( ; (i0<n0) && (x0[i0]<=xp[np-2]); i0++ ) {}
296  if ( (i0<n0) && (x0[i0]<=xp[np-1]) )
297  {
298  is(np-1,0) = (Numeric) i0;
299  for ( ; (i0<n0) && (x0[i0]<=xp[np-1]); i0++ ) {}
300  is(np-1,1) = (Numeric) (i0 - 1);
301  }
302  }
303 }
304 
305 
306 
308 
336  Vector& w,
337  const Vector& x0,
338  const Index& i1,
339  const Index& i2,
340  const Vector& xp,
341  const Index& ip )
342 {
343  const Index np = xp.nelem(); // number of retrieval points
344  const Index nw = i2-i1+1; // number of LOS points affected
345  Index i;
346 
347  // Reallocate w
348  w.resize(nw);
349 
350  // First point of the retrieval grid
351  if ( ip == 0 )
352  {
353  for ( i=0; i<nw; i++ )
354  w[i] = ( xp[1] - x0[i1+i] ) / ( xp[1] - xp[0] );
355  }
356  // Points inside the retrieval grid
357  else if ( ip < (np-1) )
358  {
359  for ( i=0; i<nw; i++ )
360  {
361  if ( x0[i1+i] <= xp[ip] )
362  w[i] = ( x0[i1+i] - xp[ip-1] ) / ( xp[ip] - xp[ip-1] );
363  else
364  w[i] = ( xp[ip+1] - x0[i1+i] ) / ( xp[ip+1] - xp[ip] );
365  }
366  }
367  // Last point of the retrieval grid
368  else
369  {
370  for ( i=0; i<nw; i++ )
371  w[i] = ( x0[i1+i] - xp[np-2] ) / ( xp [np-1] - xp[np-2] );
372  }
373 }
374 
376 
396  ArrayOfMatrix& W,
397  const Los& los,
398  const Vector& k_grid)
399 
400 {
401  // Main sizes
402  const Index nza = los.start.nelem(); // number of zenith angles
403  const Index np = k_grid.nelem(); // number of pressure grid
404  // -log(p) is used as altitude variable. The minus is included to get
405  // increasing values, a demand for the grid functions.
406  // const Vector lgrid=-1.0*log(k_grid);
407  Vector lgrid;
408  p2grid( lgrid, k_grid );
409  Vector lplos;
410  Vector w1;
411  W.resize(nza);
412  // Indices
413  // IP0 and IF0 are the index off-sets for the total K matrix
414  Index iza; // zenith angle index
415  Index ip; // pressure index
416  Matrix is; // matrix for storing LOS index
417 
418  for ( iza=0; iza<nza; iza++ )
419  {
420  W[iza].resize(los.p[iza].nelem(), np);
421  W[iza]=0.0;
422  if ( (iza%20)==0 )
423  {
424  out3 << "\n ";
425  out3 << " " << iza; cout.flush();
426  }
427  w1=0;
428  // Do something only if LOS has any points
429  if ( los.p[iza].nelem() > 0 )
430  {
431  // Get the LOS points affected by each retrieval point
432  // lplos = -1.0 * log(los.p[iza]);
433  p2grid( lplos, los.p[iza] );
434  grid2grid_index (is, lplos, lgrid);
435 
436  for ( ip=0; ip<np; ip++ )
437  {
438  // Check if there is anything to do
439 
440  if ( is(ip,0) >= 0 )
441  {
442  // Get the weights for the LOS points
443  grid2grid_weights( w1, lplos, (Index)is(ip,0), (Index)is(ip,1),
444  lgrid, ip );
445  // fill the corresponding part of the Matrix W with the weights w1
446 
447  W[iza](Range((Index)is(ip,0),(Index)(is(ip,1)-is(ip,0)+1)), ip)=w1;
448  }
449  }
450  }
451  }
452 }
453 
455 // Help functions for absloswfsCalc to calculate absorption LOS WFs
457 
459 
485  Matrix& k,
486  Vector y,
487  const Index& start_index,
488  const Index& stop_index, // this variable is used by
489  const Numeric& lstep, // absloswfs_down
490  const Matrix& tr,
491  const Matrix& s,
492  const Index& ground,
493  const Vector& e_ground,
494  const Vector& y_ground )
495 {
496  const Index nf = tr.nrows(); // number of frequencies
497  Index iv; // frequency index
498  Index q; // LOS index (same notation as in AUG)
499  Vector t(nf); // transmission to the sensor
500 
501  t = 1.0; // Set all elements of t to 1.
502 
503  if ( ground && ((ground-1==stop_index) || (ground-1==start_index)) )
504  throw logic_error("The ground cannot be at one of the end points.");
505 
506  // Resize K
507  k.resize( nf, start_index+1 );
508 
509  // We start here at the LOS point closest to the sensor, that is,
510  // reversed order compared to RTE_ITERATE
511 
512  // The LOS point closest to the sensor
513  q = stop_index;
514  for ( iv=0; iv<nf; iv++ )
515  {
516  t[iv] *= tr(iv,q);
517  y[iv] = (y[iv]-s(iv,q)*(1.0-tr(iv,q)))/tr(iv,q);
518  k(iv,q) = (-lstep/2)*(y[iv]-s(iv,q))*t[iv];
519  }
520 
521  // Points inside the LOS
522  for ( q=stop_index+1; q<start_index; q++ )
523  {
524  // Not a ground point
525  if ( q != (ground-1) )
526  {
527  for ( iv=0; iv<nf; iv++ )
528  {
529  y[iv] = (y[iv]-s(iv,q)*(1.0-tr(iv,q)))/tr(iv,q);
530  k(iv,q) = (-lstep/2)*( 2*(y[iv]-s(iv,q))*tr(iv,q) +
531  s(iv,q) - s(iv,q-1) ) *t[iv];
532  t[iv] *= tr(iv,q);
533  }
534  }
535  // A ground point
536  else
537  {
538  out1 << "WARNING: The function absloswfs_1pass not tested for "
539  "ground reflections\n";
540  for ( iv=0; iv<nf; iv++ )
541  {
542  y[iv] = ( y[iv] - e_ground[iv]*y_ground[iv] -
543  s(iv,q)*(1.0-tr(iv,q))*(1-e_ground[iv]) ) /
544  ( tr(iv,q) * (1-e_ground[iv]) );
545  k(iv,q) = (-lstep/2)*( 2*(y[iv]-s(iv,q))*tr(iv,q)*(1-e_ground[iv])+
546  s(iv,q)*(1-e_ground[iv]) +
547  e_ground[iv]*y_ground[iv] - s(iv,q-1) ) * t[iv];
548  t[iv] *= tr(iv,q) * (1-e_ground[iv]);
549  }
550  }
551  }
552 
553  // The LOS point furthest away from the sensor
554  q = start_index;
555  for ( iv=0; iv<nf; iv++ )
556  k(iv,q) = (-lstep/2)*(y[iv]-s(iv,q-1))*t[iv];
557 
558  // To check the function: Y shall now be equal to the radiation entering
559  // the atmosphere and T the total transmission
560 }
561 
562 
563 
565 
587  Matrix& k,
588  Vector y, // = y_q^q
589  const Vector& y_space,
590  const Index& start_index,
591  const Numeric& lstep,
592  const Matrix& tr,
593  const Matrix& s,
594  const Index& ground,
595  const Vector& e_ground )
596 {
597  const Index nf = tr.nrows(); // number of frequencies
598  Index iv; // frequency index
599  Vector t1q; // transmission tangent point - q squared
600  Vector tqn(nf,1.0); // transmission q - sensor
601  Index q; // LOS index (same notation as in AUG)
602  Numeric tv, tv1 = 0.; // transmission value for q and q-1
603  Vector yn(y_space); // = y_space
604 
605  // Matpack can initialize a new Vector from another Vector. See how
606  // yn is initialized from y_space.
607 
608  // Resize K
609  k.resize( nf, start_index+1 );
610 
611  // Calculate the total transmission
612  bl( t1q, start_index, start_index, tr, ground, e_ground );
613 
614  // We start at the outermost point
615  q = start_index;
616  for ( iv=0; iv<nf; iv++ )
617  {
618  tv1 = tr(iv,q-1);
619  t1q[iv] /= tv1*tv1;
620  tqn[iv] *= tv1;
621  y[iv] = ( y[iv] - s(iv,q-1)*(1-tv1)*(1+t1q[iv]*tv1) ) / tv1;
622  k(iv,q) = (-lstep/2)*( ( 2*yn[iv] + s(iv,q-1)*(1-2*tv1) ) *
623  t1q[iv]*tv1 + y[iv] - s(iv,q-1) )*tv1;
624  }
625 
626  // Points inside the LOS
627  for ( q=start_index-1; q>0; q-- )
628  {
629  for ( iv=0; iv<nf; iv++ )
630  {
631  tv1 = tr(iv,q-1);
632  tv = tr(iv,q);
633  t1q[iv] /= tv1*tv1;
634  y[iv] = ( y[iv] - s(iv,q-1)*(1-tv1)*(1+t1q[iv]*tv1) ) / tv1;
635  k(iv,q) = (-lstep/2) * (
636  ( 4*(yn[iv]-s(iv,q))*tv1*tv + 3*(s(iv,q)-s(iv,q-1))*tv1 +
637  2*s(iv,q-1) ) * t1q[iv]*tv1 +
638  2*(y[iv]-s(iv,q-1))*tv1 + s(iv,q-1) - s(iv,q) ) * tqn[iv];
639  tqn[iv] *= tv1;
640  yn[iv] = yn[iv]*tv + s(iv,q)*(1-tv);
641  }
642  }
643 
644  // The tangent or ground point
645  for ( iv=0; iv<nf; iv++ )
646  k(iv,0) = (-lstep/2)*( (2*yn[iv]*tv1+s(iv,0)*(1-2*tv1))*t1q[iv] +
647  y[iv] - s(iv,0) ) * tqn[iv];
648 
649  // To check the function
650  // Without ground reflection: T1Q=1 and Y=0
651  // With ground reflection: T1Q=(1-e) and Y=eB
652  // print_vector( t1q );
653  // print_vector( y );
654 }
655 
656 
657 
659 
683  Matrix& k,
684  const Vector& y,
685  const Vector& y_space,
686  const Index& start_index,
687  const Index& stop_index,
688  const Numeric& lstep,
689  const Matrix& tr,
690  const Matrix& s,
691  const Index& ground,
692  const Vector& e_ground,
693  const Vector& y_ground )
694 {
695  const Index nf = tr.nrows(); // number of frequencies
696  Index iv; // frequency index
697  Index q; // LOS index (same notation as in AUG)
698  Vector y0(nf); // see below
699  Matrix k2; // matrix for calling other LOS WFs functions
700  Vector tr0; // see below
701 
702  // Resize K
703  k.resize( nf, start_index+1 );
704 
705  // Calculate Y0, the intensity reaching the platform altitude at the far
706  // end of LOS, that is, from above.
707  y0 = y_space; // Matpack can copy the contents of
708  // vectors like this. The dimensions
709  // must be the same!
710  rte_iterate( y0, start_index-1, stop_index, tr, s, nf );
711 
712  // Calculate TR0, the transmission from the platform altitude down to the
713  // tangent point or the ground, and up to the platform again.
714  bl( tr0, stop_index, stop_index, tr, ground, e_ground );
715 
716  // The indeces below STOP_INDEX are handled by the limb sounding function.
717  // The limb function is given Y0 instead of cosmic radiation
718  absloswfs_rte_limb( k2, y, y0, stop_index, lstep, tr, s, ground, e_ground );
719  for ( iv=0; iv<nf; iv++ )
720  {
721  for ( q=0; q<stop_index; q++ )
722  k(iv,q) = k2(iv,q);
723  }
724 
725  // The indeces above STOP_INDEX are handled by the 1pass function.
726  // The transmission below STOP_INDEX must here be considered.
727  absloswfs_rte_1pass( k2, y0, start_index, stop_index, lstep, tr, s,
728  ground, e_ground, y_ground );
729  for ( iv=0; iv<nf; iv++ )
730  {
731  for ( q=stop_index+1; q<=start_index; q++ )
732  k(iv,q) = k2(iv,q)*tr0[iv];
733  }
734 
735  // The platform altitude must be treated seperately
736  //
737  // Calculate the intensity generated below point q-1, YQQ
738  Vector yqq(nf);
739  rte( yqq, stop_index-1, stop_index-1, tr, s, Vector(nf,0.0),
740  ground, e_ground, y_ground );
741  //
742  // Y0 is moved one step upwards and TR0 one step downwards
743  q = stop_index;
744  for ( iv=0; iv<nf; iv++ )
745  {
746  tr0[iv] /= tr(iv,q-1)*tr(iv,q-1);
747  y0[iv] = ( y0[iv] - s(iv,q)*(1-tr(iv,q)) ) / tr(iv,q);
748  k(iv,q) = (-lstep/2)*( (3*(y0[iv]-s(iv,q))*tr(iv,q-1)*tr(iv,q) +
749  2*(s(iv,q)-s(iv,q-1))*tr(iv,q-1) + s(iv,q-1) )*tr0[iv] +
750  yqq[iv] - s(iv,q-1) )*tr(iv,q-1);
751  }
752 }
753 
754 
755 
757 
762  ArrayOfMatrix& absloswfs,
763  const Los& los,
764  const ArrayOfMatrix& source,
765  const ArrayOfMatrix& trans,
766  const Vector& y,
767  const Vector& y_space,
768  const Vector& f_mono,
769  const Vector& e_ground,
770  const Numeric& t_ground )
771 {
772  const Index nza = los.start.nelem(); // number of zenith angles
773  const Index nf = f_mono.nelem(); // number of frequencies
774  Vector yp(nf); // part of Y
775  Index iy0=0; // y index
776 
777  // Set up vector for ground blackbody radiation
778  Vector y_ground(f_mono.nelem());
779  if ( any_ground(los.ground) )
780  planck( y_ground, f_mono, t_ground );
781 
782  // Resize the LOS WFs array
783  absloswfs.resize( nza );
784 
785  // Loop zenith angles
786  out3 << " Zenith angle nr:\n ";
787  for (Index i=0; i<nza; i++ )
788  {
789  if ( ((i+1)%20)==0 )
790  out3 << "\n ";
791  out3 << " " << i; cout.flush();
792 
793  // Do something only if LOS has any points
794  if ( los.p[i].nelem() > 0 )
795  {
796 
797  // Pick out the part of Y corresponding to the present zenith angle
798  yp = y[Range(iy0,nf)];
799 
800  // The calculations are performed in 3 sub-functions
801  //
802  // Upward looking (=single pass)
803  if ( los.stop[i]==0 )
804  absloswfs_rte_1pass( absloswfs[i], yp, los.start[i], 0, los.l_step[i],
805  trans[i], source[i], los.ground[i], e_ground, y_ground );
806 
807  //
808  // 1D limb sounding
809  else if ( los.start[i] == los.stop[i] )
810  absloswfs_rte_limb( absloswfs[i], yp, y_space, los.start[i],
811  los.l_step[i], trans[i], source[i], los.ground[i], e_ground );
812 
813  //
814  // 1D downward looking
815  else
816  absloswfs_rte_down( absloswfs[i], yp, y_space, los.start[i],
817  los.stop[i], los.l_step[i], trans[i], source[i],
818  los.ground[i], e_ground, y_ground );
819  }
820 
821  iy0 += nf;
822  }
823 
824  out3 << "\n";
825 }
826 
827 
828 
830 
835  ArrayOfMatrix& absloswfs,
836  const Los& los,
837  const Vector& f_mono )
838 {
839  const Index nza = los.start.nelem(); // number of zenith angles
840  const Index nf = f_mono.nelem(); // number of frequencies
841  Numeric kw, kw2;
842  Index row, col, np;
843 
844  // Resize the LOS WFs array
845  absloswfs.resize( nza );
846 
847  // Loop zenith angles
848  out3 << " Zenith angle nr:\n ";
849  for (Index i=0; i<nza; i++ )
850  {
851  if ( ((i+1)%20)==0 )
852  out3 << "\n ";
853  out3 << " " << i; cout.flush();
854 
855  np = los.start[i] + 1;
856 
857  absloswfs[i].resize( nf, np );
858 
859  // Do something only if LOS has any points
860  if ( los.p[i].nelem() > 0 )
861  {
862 
863  // Upward looking (=single pass)
864  if ( los.stop[i]==0 )
865  {
866  kw = los.l_step[i] / 2.0;
867  kw2 = los.l_step[i];
868  for( row=0; row<nf; row++ )
869  {
870  absloswfs[i](row,0) = kw;
871  absloswfs[i](row,np-1) = kw;
872  for( col=1; col<np-1; col++ )
873  absloswfs[i](row,col) = kw2;
874  }
875  }
876 
877  // 1D limb sounding
878  else if ( los.start[i] == los.stop[i] )
879  {
880  kw = los.l_step[i];
881  kw2 = los.l_step[i] * 2.0;
882  for( row=0; row<nf; row++ )
883  {
884  absloswfs[i](row,0) = kw;
885  absloswfs[i](row,np-1) = kw;
886  for( col=1; col<np-1; col++ )
887  absloswfs[i](row,col) = kw2;
888  }
889  }
890 
891  // 1D downward looking
892  else
893  {
894  kw = los.l_step[i];
895  kw2 = los.l_step[i] * 2.0;
896  for( row=0; row<nf; row++ )
897  {
898  absloswfs[i](row,0) = kw;
899  absloswfs[i](row,np-1) = kw / 2.0;
900  absloswfs[i](row,los.stop[i]) = kw * 1.5;
901  for( col=1; col<los.stop[i]; col++ )
902  absloswfs[i](row,col) = kw2;
903  for( col=los.stop[i]+1; col<np-1; col++ )
904  absloswfs[i](row,col) = kw;
905  }
906  }
907  }
908  }
909  out3 << "\n";
910 }
911 
912 
913 
915 // Functions to calculate source function LOS WFs
917 
919 
941  Matrix& k,
942  const Index& start_index,
943  const Index& stop_index, // this variable is used by 1D down
944  const Matrix& tr,
945  const Index& ground,
946  const Vector& e_ground )
947 {
948  const Index nf = tr.nrows(); // number of frequencies
949  Index iv; // frequency index
950  Vector t(nf,1.0); // transmission to the sensor
951  Index q; // LOS index (same notation as in AUG)
952 
953  if ( ground && ((ground-1==stop_index) || (ground-1==start_index)) )
954  throw logic_error("The ground cannot be at one of the end points.");
955 
956  // Resize K
957  k.resize( nf, start_index+1 );
958 
959  // We start here at the LOS point closest to the sensor, that is,
960  // reversed order compared to RTE_ITERATE
961 
962  // The LOS point closest to the sensor
963  q = stop_index;
964  for ( iv=0; iv<nf; iv++ )
965  k(iv,q) = ( 1 - tr(iv,q) ) / 2;
966 
967  // Points inside the LOS
968  for ( q=stop_index+1; q<start_index; q++ )
969  {
970  // Not a ground point
971  if ( q != ground )
972  {
973  for ( iv=0; iv<nf; iv++ )
974  {
975  k(iv,q) = ( 1 - tr(iv,q-1)*tr(iv,q) ) * t[iv] / 2;
976  t[iv] *= tr(iv,q);
977  }
978  }
979  // A ground point
980  else
981  {
982  out1 << "WARNING: The function sourceloswfs_1pass not tested "
983  "for ground reflections\n";
984 
985  for ( iv=0; iv<nf; iv++ )
986  {
987  k(iv,q) = ( (1-tr(iv,q))*(1-e_ground[iv])*tr(iv,q-1) + 1 -
988  tr(iv,q-1) ) * t[iv] / 2;
989  t[iv] *= tr(iv,q)*(1-e_ground[iv]);
990  }
991  }
992  }
993 
994  // The LOS point furthest away from the sensor
995  q = start_index;
996  for ( iv=0; iv<nf; iv++ )
997  k(iv,q) = ( 1 - tr(iv,q-1) ) * t[iv] / 2;
998 }
999 
1000 
1001 
1003 
1021  Matrix& k,
1022  const Index& start_index,
1023  const Matrix& tr,
1024  const Index& ground,
1025  const Vector& e_ground )
1026 {
1027  const Index nf = tr.nrows(); // number of frequencies
1028  Index iv; // frequency index
1029  Vector t1q; // transmission tangent point - q squared
1030  Vector tqn(nf,1); // transmission q - sensor
1031  Index q; // LOS index (same notation as in AUG)
1032 
1033  // Calculate the total transmission
1034  bl( t1q, start_index, start_index, tr, ground, e_ground );
1035 
1036  // Resize K
1037  k.resize( nf, start_index+1 );
1038 
1039  // We start at the outermost point
1040  q = start_index;
1041  for ( iv=0; iv<nf; iv++ )
1042  {
1043  t1q[iv] /= tr(iv,q-1) * tr(iv,q-1);
1044  k(iv,q) = ( (1-tr(iv,q-1))*t1q[iv]*tr(iv,q-1) + 1 - tr(iv,q-1) )/2;
1045  }
1046 
1047  // Points inside the LOS
1048  for ( q=start_index-1; q>0; q-- )
1049  {
1050  for ( iv=0; iv<nf; iv++ )
1051  {
1052  t1q[iv] /= tr(iv,q-1) * tr(iv,q-1);
1053  k(iv,q) = ( (1-tr(iv,q-1)*tr(iv,q))*t1q[iv]*tr(iv,q-1)*
1054  tr(iv,q) + (1-tr(iv,q-1))*tr(iv,q) + 1 - tr(iv,q) ) * tqn[iv] / 2;
1055  tqn[iv] *= tr(iv,q-1);
1056  }
1057  }
1058 
1059  // The tangent or ground point
1060  for ( iv=0; iv<nf; iv++ )
1061  k(iv,0) = ( (1-tr(iv,0))*(1+t1q[iv]*tr(iv,0)) ) * tqn[iv] / 2;
1062 }
1063 
1064 
1065 
1067 
1086  Matrix& k,
1087  const Index& start_index,
1088  const Index& stop_index,
1089  const Matrix& tr,
1090  const Index& ground,
1091  const Vector& e_ground )
1092 {
1093  const Index nf = tr.nrows(); // number of frequencies
1094  Index iv; // frequency index
1095  Index q; // LOS index (same notation as in AUG)
1096  Matrix k2; // matrix for calling other LOS WFs functions
1097  Vector tr0; // see below
1098 
1099  // Resize K
1100  k.resize( nf, start_index+1 );
1101 
1102  // Calculate TR0, the transmission from the platform altitude down to the
1103  // tangent point or the ground, and up to the platform again.
1104  bl( tr0, stop_index, stop_index, tr, ground, e_ground );
1105 
1106  // The indeces below STOP_INDEX are handled by the limb sounding function.
1107  sourceloswfs_limb( k2, stop_index, tr, ground, e_ground );
1108  for ( iv=0; iv<nf; iv++ )
1109  {
1110  for ( q=0; q<stop_index; q++ )
1111  k(iv,q) = k2(iv,q);
1112  }
1113 
1114  // The indecies above STOP_INDEX are handled by the 1pass function.
1115  // The transmission below STOP_INDEX must here be considered.
1116  sourceloswfs_1pass( k2, start_index, stop_index, tr, ground, e_ground );
1117  for ( iv=0; iv<nf; iv++ )
1118  {
1119  for ( q=stop_index+1; q<=start_index; q++ )
1120  k(iv,q) = k2(iv,q)*tr0[iv];
1121  }
1122 
1123  // The platform altitude must be treated seperately
1124  //
1125  // TR0 is moved one step downwards
1126  q = stop_index;
1127  for ( iv=0; iv<nf; iv++ )
1128  {
1129  tr0[iv] /= tr(iv,q-1)*tr(iv,q-1);
1130  k(iv,q) = ( (1-tr(iv,q-1)*tr(iv,q))*tr0[iv]*tr0[iv]*tr(iv,q-1) + 1 -
1131  tr(iv,q-1) ) / 2;
1132  }
1133 }
1134 
1135 
1136 
1138 
1156  const Los& los,
1157  const ArrayOfMatrix& trans,
1158  const Vector& /* f_mono */,
1159  const Vector& e_ground )
1160 {
1161  const Index nza = los.start.nelem(); // number of zenith angles
1162 
1163  // Resize the LOS WFs array
1164  sourceloswfs.resize(nza);
1165 
1166  // Loop zenith angles
1167  out3 << " Zenith angle nr: ";
1168  for (Index i=0; i<nza; i++ )
1169  {
1170  if ( (i%20)==0 )
1171  out3 << "\n ";
1172  out3 << " " << i; cout.flush();
1173 
1174  // Do something only if LOS has any points
1175  if ( los.p[i].nelem() > 0 )
1176  {
1177  // The calculations are performed in 3 sub-functions
1178  //
1179  // Upward looking (=single pass)
1180  if ( los.stop[i]==0 )
1181  sourceloswfs_1pass( sourceloswfs[i], los.start[i], 0, trans[i],
1182  los.ground[i], e_ground );
1183  //
1184  // 1D limb sounding
1185  else if ( los.start[i] == los.stop[i] )
1186  sourceloswfs_limb( sourceloswfs[i], los.start[i], trans[i],
1187  los.ground[i], e_ground );
1188  //
1189  // 1D downward looking
1190  else
1191  sourceloswfs_down( sourceloswfs[i], los.start[i], los.stop[i],
1192  trans[i], los.ground[i], e_ground );
1193  }
1194  }
1195  out3 << "\n";
1196 }
1197 
1198 
1199 
1201 // Core functions for analytical WFs.
1202 // Analytical expressions are used for species, temperature without
1203 // hydrostatic eq. and continuum absorption.
1204 // These functions are very similar and a change in one of the functions
1205 // should most likely be included in the other functions.
1207 
1209 
1245  Matrix& k,
1246  ArrayOfString& k_names,
1247  Matrix& k_aux,
1248  const Los& los,
1249  const ArrayOfMatrix& absloswfs,
1250  const Vector& p_abs,
1251  const Vector& t_abs,
1252  const TagGroups& tags,
1253  const ArrayOfMatrix& abs_per_tg,
1254  const Matrix& vmrs,
1255  const Vector& k_grid,
1256  const ArrayOfIndex& tg_nr,
1257  const String& unit )
1258 {
1259  check_lengths( p_abs, "p_abs", t_abs, "t_abs" );
1260  check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
1261  if ( tags.nelem() != abs_per_tg.nelem() )
1262  throw runtime_error(
1263  "Lengths of *wfs_tgs* and *abs_per_tg* do not match." );
1264  if ( los.p.nelem() != absloswfs.nelem() )
1265  throw runtime_error(
1266  "The number of zenith angles is not the same in *los* and *absloswfs*." );
1267 
1268  // Main sizes
1269  const Index nza = los.start.nelem(); // number of zenith angles
1270  const Index nv = abs_per_tg[0].nrows(); // number of frequencies
1271  const Index ntg = tg_nr.nelem(); // number of retrieval tags to do
1272  const Index np = k_grid.nelem(); // number of retrieval altitudes
1273 
1274  // -log(p) is used as altitude variable. The minus is included to get
1275  // increasing values, a demand for the grid functions.
1276  Vector lgrid; // -log of the retrieval pressures
1277  p2grid( lgrid, k_grid );
1278  Vector lplos; // -log of the LOS pressures
1279 
1280  // Indices
1281  // IP0 and IF0 are the index off-sets for the total K matrix
1282  Index itg; // Tag index
1283  Index iza; // Zenith angle index
1284  Index ip, ip0=0; // Retrieval point indices
1285  Index iv, iv0; // Frequency indices
1286  Index i1, iw; // weight indices
1287 
1288  // Other variables
1289  Matrix abs; // absorption at k_grid
1290  Matrix is; // matrix for storing LOS index
1291  Vector w; // weights for LOS WFs
1292  Vector a(nv); // temporary vector
1293  Index tg; // present tag nr
1294  Vector vmr, p, t; // for conversion to VMR and ND
1295  Vector nd; // number density
1296 
1297  // Set up K and additional data. Set all values of K to 0
1298  k.resize(nza*nv,ntg*np);
1299  k = 0.0; // Matpack can set all elements like this.
1300  k_names.resize(ntg);
1301  k_aux.resize(ntg*np,2);
1302 
1303  // The calculations
1304  // Loop order:
1305  // 1 tags
1306  // 2 zenith angle
1307  // 3 retrieval altitudes
1308  // 4 frequencies
1309  for ( itg=0; itg<ntg; itg++ )
1310  {
1311  // Present tag nr
1312  tg = tg_nr[itg];
1313 
1314  out2 << " Doing " << tags[tg][0].Name() << "\n";
1315 
1316  // Get the absorption of the species at the retrieval points
1317  abs.resize( nv, np );
1318  interpp( abs, p_abs, abs_per_tg[tg], k_grid );
1319 
1320  // Fill K_NAMES
1321  {
1322  ostringstream os;
1323  os << "Species: " << tags[tg][0].Name();
1324  k_names[itg] = os.str();
1325  }
1326 
1327  // Fill column 0 of K_AUX
1328  for ( ip=0; ip<np; ip++ )
1329  k_aux(ip0+ip,0) = k_grid[ip];
1330 
1331  // Fill column 1 of K_AUX
1332  // frac : fractions of the linearisation profile
1333  // vmr : VMR
1334  // nd : number density
1335  //
1336  vmr.resize( np );
1337  interpp( vmr, p_abs, vmrs(tg,Range(joker)), k_grid );
1338  // The Range(joker) expression selects the entire row.
1339 
1340  if ( unit == "frac" )
1341  {
1342  for ( ip=0; ip<np; ip++ )
1343  k_aux(ip0+ip,1) = 1.0;
1344  }
1345  else if ( unit == "vmr" )
1346  {
1347  for ( ip=0; ip<np; ip++ )
1348  {
1349  for ( iv=0; iv<nv; iv++ )
1350  abs(iv,ip) /= vmr[ip];
1351  k_aux(ip0+ip,1) = vmr[ip];
1352  }
1353  }
1354  else if ( unit == "nd" )
1355  {
1356  nd.resize( np );
1357  interpp( nd, p_abs, number_density(p_abs,t_abs), k_grid );
1358  nd *= vmr; // Matpack can do element-vise
1359  // multiplication like this.
1360  for ( ip=0; ip<np; ip++ )
1361  {
1362  for ( iv=0; iv<nv; iv++ )
1363  abs(iv,ip) /= nd[ip];
1364  k_aux(ip0+ip,1) = nd[ip];
1365  }
1366  }
1367  else
1368  throw runtime_error(
1369  "Allowed species retrieval units are \"frac\", \"vmr\" and \"nd\".");
1370 
1371  // Set frequency zenith angle index off-set to 0
1372  iv0 = 0;
1373 
1374  // Loop zenith angles
1375  out3 << " Zenith angle nr:\n ";
1376  for ( iza=0; iza<nza; iza++ )
1377  {
1378  if ( ((iza+1)%20)==0 )
1379  out3 << "\n ";
1380  out3 << " " << iza; cout.flush();
1381 
1382  // Do something only if LOS has any points
1383  if ( los.p[iza].nelem() > 0 )
1384  {
1385  // Get the LOS points affected by each retrieval point
1386  // lplos = -1.0 * log(los.p[iza]);
1387  p2grid( lplos, los.p[iza] );
1388  grid2grid_index( is, lplos, lgrid );
1389 
1390  // Loop retrieval points
1391  for ( ip=0; ip<np; ip++ )
1392  {
1393  // Check if there is anything to do
1394  if ( is(ip,0) >= 0 )
1395  {
1396  // Get the weights for the LOS points
1397  grid2grid_weights( w, lplos, (Index)is(ip,0), (Index)is(ip,1),
1398  lgrid, ip );
1399 
1400  // Calculate the WFs.
1401  // A is di/dkappa*dkappa/dkp in a compact form.
1402  // This is possible as the columns of dkappa/dkp are identical.
1403 
1404  a = 0.0; // Matpack can set all elements like this.
1405 
1406  i1 = (Index)is(ip,0); // first LOS point to consider
1407  for ( iv=0; iv<nv; iv++ )
1408  {
1409  for ( iw=i1; iw<=(Index)is(ip,1); iw++ )
1410  a[iv] += absloswfs[iza](iv,iw) * w[iw-i1];
1411  k(iv0+iv,ip0+ip) = a[iv] * abs(iv,ip);
1412  }
1413  }
1414  }
1415  }
1416 
1417  // Update the frequency index offset
1418  iv0 += nv;
1419  }
1420  out3 << "\n";
1421 
1422  // Increase retrieval altitude index off-set
1423  ip0 += np;
1424  }
1425 }
1426 
1427 
1428 
1430 
1466  Matrix& k,
1467  ArrayOfString& k_names,
1468  Matrix& k_aux,
1469  const Los& los,
1470  const ArrayOfMatrix& absloswfs,
1471  const Vector& f_mono,
1472  const Vector& k_grid,
1473  const Index& order,
1474  const Numeric& flow,
1475  const Numeric& fhigh,
1476  const String& lunit )
1477 {
1478 
1479  if ( los.p.nelem() != absloswfs.nelem() )
1480  {
1481  throw runtime_error(
1482  "The number of zenith angles is not the same in *los* and *absloswfs*." );
1483  check_length_nrow( los.p[0], "los points", absloswfs[0],
1484  "the matrices of absloswfs" );
1485  }
1486 
1487  // Main sizes
1488  const Index nza = los.start.nelem(); // number of zenith angles
1489  const Index np = k_grid.nelem(); // number of retrieval altitudes
1490  const Index npoints = order+1; // number of off-set points
1491  const Index nv = f_mono.nelem(); // number of frequencies
1492 
1493  // Check given frequency limits
1494  if ( flow >= fhigh )
1495  throw runtime_error(
1496  "The lower frequency limit equals or is above the upper limit." );
1497  if ( flow < f_mono[0] )
1498  throw runtime_error(
1499  "The lower frequency limit is below all values of f_mono." );
1500  if ( fhigh > f_mono[nv-1] )
1501  throw runtime_error(
1502  "The upper frequency limit is above all values of f_mono." );
1503 
1504  // Check length unit
1505  //
1506  Numeric scfac;
1507  //
1508  if ( lunit == "m" )
1509  scfac = 1.0;
1510  else if ( lunit == "km" )
1511  scfac = 0.001;
1512  else
1513  throw runtime_error("Allowed length units are \"m\" and \"km\".");
1514 
1515  // -log(p) is used as altitude variable. The minus is included to get
1516  // increasing values, a demand for the grid functions.
1517  Vector lgrid;
1518  p2grid( lgrid, k_grid );
1519  Vector lplos; // -log of the LOS pressures
1520 
1521  // Indices
1522  // IP0 and IF0 are the index off-sets for the total K matrix
1523  Index ipoint; // Off-set point index
1524  Index iza; // Zenith angle index
1525  Index ip, ip0=0; // Retrieval point indices
1526  Index iv, iv0; // Frequency indices
1527  Index i1, iw; // weight indices
1528 
1529  // Determine first and last frequency index inside given limits
1530  Index ilow, ihigh;
1531  for( ilow=0; ilow<(nv-1) && f_mono[ilow] < flow; ilow++ )
1532  {}
1533  for( ihigh=ilow; ihigh<(nv-1) && f_mono[ihigh+1] <= fhigh; ihigh++ )
1534  {}
1535 
1536  // Other variables
1537  Vector fpoints; // frequencies of the off-set points
1538  Vector b(nv); // fit base function
1539  Matrix is; // matrix for storing LOS index
1540  Vector w; // weights for LOS WFs
1541  Vector a(nv); // temporary vector
1542 
1543  // Check that the selected polynomial order
1544  if ( order < 0 )
1545  throw runtime_error("The polynomial order must be >= 0.");
1546 
1547  // Set up K and additional data. Set all values of K to 0
1548  k.resize(nza*nv,npoints*np);
1549  k = 0.0; // Matpack can set all elements like this.
1550  k_names.resize(npoints);
1551  k_aux.resize(npoints*np,2);
1552 
1553  // Calculate the frequencies of the off-set points
1554  if ( npoints > 1 )
1555  nlinspace( fpoints, f_mono[ilow], f_mono[ihigh], npoints );
1556  else
1557  {
1558  fpoints.resize( 1 );
1559  fpoints[0] = ( f_mono[ilow] + f_mono[ihigh] ) / 2.0;
1560  }
1561 
1562  // The calculations
1563  // Loop order:
1564  // 1 polynomial order
1565  // 2 zenith angle
1566  // 3 retrieval altitudes
1567  // 4 frequencies
1568  //
1569  // (Another loop order should be somewhat more efficient, but to keep this
1570  // function consistent with k_species, this loop order was selected.)
1571  //
1572  out2 << " You have selected " << npoints << " off-set fit points.\n";
1573  out2 << " Length unit is " << lunit << "\n";
1574  for ( ipoint=0; ipoint<npoints; ipoint++ )
1575  {
1576  out2 << " Doing point " << ipoint << "\n";
1577 
1578  // Fill K_NAMES and K_AUX
1579  {
1580  ostringstream os;
1581  os << "Continuum: " << fpoints[ipoint]/1e9 << " GHz, Point "
1582  << ipoint+1 << "/" << npoints;
1583  k_names[ipoint] = os.str();
1584  }
1585  for ( ip=0; ip<np; ip++ )
1586  {
1587  k_aux(ip0+ip,0) = k_grid[ip];
1588  k_aux(ip0+ip,1) = 0.0;
1589  }
1590 
1591  // Set-up base vector for the present fit point
1592  b = 1.0; // Matpack can set all elements like this.
1593  if ( npoints > 1 )
1594  {
1595  for ( ip=0; ip<npoints; ip++ )
1596  {
1597  if ( ip != ipoint )
1598  {
1599  for ( iv=ilow; iv<=ihigh; iv++ )
1600  b[iv] *= (f_mono[iv]-fpoints[ip]) / ( fpoints[ipoint]-fpoints[ip]);
1601  }
1602  }
1603  }
1604 
1605  // Set frequency zenith angle index off-set to 0
1606  iv0 = 0;
1607 
1608  // Loop zenith angles
1609  out3 << " Zenith angle nr:\n ";
1610  for ( iza=0; iza<nza; iza++ )
1611  {
1612  if ( ((iza+1)%20)==0 )
1613  out3 << "\n ";
1614  out3 << " " << iza; cout.flush();
1615 
1616  // Do something only if LOS has any points
1617  if ( los.p[iza].nelem() > 0 )
1618  {
1619  // Get the LOS points affected by each retrieval point
1620  // lplos = -1.0 * log(los.p[iza]);
1621  p2grid( lplos, los.p[iza] );
1622  grid2grid_index( is, lplos, lgrid );
1623 
1624  // Loop retrieval points
1625  for ( ip=0; ip<np; ip++ )
1626  {
1627  // Check if there is anything to do
1628  if ( is(ip,0) >= 0 )
1629  {
1630  // Get the weights for the LOS points
1631  grid2grid_weights( w, lplos, (Index)is(ip,0), (Index) is(ip,1),
1632  lgrid, ip );
1633 
1634  // Calculate the WFs.
1635  // A is di/dkappa*dkappa/dkp in a compact form.
1636  // This is possible as the columns of dkappa/dkp are identical.
1637 
1638  a = 0.0; // Matpack can set all elements like this.
1639 
1640  i1 = (Index)is(ip,0); // first LOS point to consider
1641  for ( iv=ilow; iv<=ihigh; iv++ )
1642  {
1643  for ( iw=i1; iw<=(Index)is(ip,1); iw++ )
1644  a[iv] += absloswfs[iza](iv,iw) * w[iw-i1];
1645  k(iv0+iv,ip0+ip) = scfac * a[iv] * b[iv];
1646  }
1647  }
1648  }
1649  }
1650 
1651  // Update the frequency index offset
1652  iv0 += nv;
1653  }
1654  out3 << "\n";
1655 
1656  // Increase retrieval altitude index off-set
1657  ip0 += np;
1658  }
1659 }
1660 
1661 
1662 
1664 
1702  Matrix& k,
1703  ArrayOfString& k_names,
1704  Matrix& k_aux,
1705  const TagGroups& tag_groups,
1706  const Los& los,
1707  const ArrayOfMatrix& absloswfs,
1708  const Vector& f_mono,
1709  const Vector& p_abs,
1710  const Vector& t_abs,
1711  const Vector& n2_abs,
1712  const Vector& h2o_abs,
1713  const Matrix& vmrs,
1714  const ArrayOfArrayOfLineRecord& lines_per_tg,
1715  const ArrayOfLineshapeSpec& lineshape,
1716  const Matrix& abs,
1717  const ArrayOfMatrix& trans,
1718  const Vector& e_ground,
1719  const Vector& k_grid,
1720  const ArrayOfString& cont_description_names,
1721  const ArrayOfVector& cont_description_parameters,
1722  const ArrayOfString& cont_description_models )
1723 {
1724  // Main sizes
1725  const Index nza = los.start.nelem(); // number of zenith angles
1726  const Index nv = f_mono.nelem(); // number of frequencies
1727  const Index np = k_grid.nelem(); // number of retrieval altitudes
1728 
1729  // -log(p) is used as altitude variable. The minus is included to get
1730  // increasing values, a demand for the grid functions.
1731  // const Vector lgrid=-1.0*log(k_grid);
1732 
1733  Vector lgrid;
1734  p2grid( lgrid, k_grid );
1735  Vector lplos; // -log of the LOS pressures
1736  ArrayOfMatrix W;
1737  Index ip;
1738  //
1739  // Indices
1740  // IP0 and IF0 are the index off-sets for the total K matrix
1741  Index iza; // zenith angle index
1742  //Index ip; // retrieval point index
1743  Index iv, iv0=0; // frequency indices
1744  Index i1, iw; // weight indices
1745 
1746  // Other variables
1747  Vector t(k_grid.nelem()); // temperature at retrieval points
1748  Matrix abs1k; // absorption for t_abs+1K
1749  Matrix dabs_dt; // see below
1750  ArrayOfMatrix abs_dummy; // dummy absorption array
1751  ArrayOfMatrix sloswfs; // source LOS WFs
1752  Matrix is; // matrix for storing LOS index
1753  Vector w; // weights for LOS WFs
1754  Vector a(nv), b(nv), pl(f_mono.nelem()); // temporary vectors
1755 
1756  // The scalars are declared to be double to avoid possible numerical problems
1757  // when using float
1758  double c,d; // temporary values
1759 
1760 
1761  // Set up K and additional data. Set all values of K to 0
1762  k.resize(nza*nv,np);
1763  k = 0.0; // Matpack can set all elements like this.
1764  k_names.resize(1);
1765  k_names[0] = "Temperature: no hydrostatic eq.";
1766  k_aux.resize(np,2);
1767  interpp( t, p_abs, t_abs, k_grid );
1768  for ( ip=0; ip<np; ip++ )
1769  {
1770  k_aux(ip,0) = k_grid[ip];
1771  k_aux(ip,1) = t[ip];
1772  }
1773 
1774  // Calculate absorption for t_abs + 1K to estimate the temperature derivative
1775  // dabs/dt, the temperature derivative of the absorption at k_grid
1776  out2 << " Calculating absorption for t_abs + 1K\n";
1777  out2 << " ----- Messages from absCalc: -----\n";
1778  //
1779  {
1780  // Dummy should hold t_abs + 1:
1781  Vector dummy(t_abs); // Matpack can initialize a Vector
1782  // from another Vector.
1783  dummy += 1; // Matpack can add element-vise like this.
1784 
1785  absCalc( abs1k, abs_dummy, tag_groups, f_mono, p_abs, dummy, n2_abs,
1786  h2o_abs, vmrs, lines_per_tg, lineshape, cont_description_names,
1787  cont_description_models, cont_description_parameters);
1788  }
1789  abs_dummy.resize(0);
1790  //
1791  out2 << " ----- Back from absCalc ----------\n";
1792  //
1793  // Compute abs1k = abs1k - abs:
1794  abs1k -= abs; // Matpack can subtract element-vise like this.
1795 
1796  dabs_dt.resize( abs1k.nrows(), k_grid.nelem() );
1797  interpp( dabs_dt, p_abs, abs1k, k_grid );
1798  abs1k.resize(0,0);
1799 
1800  // Calculate source LOS WFs
1801  out2 << " Calculating source LOS WFs\n";
1802  sourceloswfs( sloswfs, los, trans, f_mono, e_ground );
1803 
1804  // Determine the temperatures at the retrieval points
1805  out2 << " Calculating temperature at retrieval points\n";
1806  interpp( t, p_abs, t_abs, k_grid );
1807 
1808  // The calculations
1809  // Loop order:
1810  // 1 zenith angle
1811  // 2 retrieval altitudes
1812  // 3 frequencies
1813  //
1814  out2 << " Calculating the weighting functions\n";
1815  out3 << " Zenith angle nr: ";
1816  for ( iza=0; iza<nza; iza++ )
1817  {
1818  if ( (iza%20)==0 )
1819  out3 << "\n ";
1820  out3 << " " << iza; cout.flush();
1821 
1822  // Do something only if LOS has any points
1823  if ( los.p[iza].nelem() > 0 )
1824  {
1825  // Get the LOS points affected by each retrieval point
1826  // lplos = -1.0 * log(los.p[iza]);
1827  p2grid( lplos, los.p[iza] );
1828  grid2grid_index( is, lplos, lgrid );
1829 
1830  // Loop retrieval points
1831  for ( ip=0; ip<np; ip++ )
1832  {
1833  // Check if there is anything to do
1834  if ( is(ip,0) >= 0 )
1835  {
1836  // Get the weights for the LOS points
1837  grid2grid_weights( w, lplos, (Index)is(ip,0), (Index) is(ip,1),
1838  lgrid, ip );
1839 
1840  // Calculate the WFs.
1841  // A is di/dsigma*dsigma/dSp in a compact form.
1842  // B is di/dkappa*dkappa/dkp in a compact form.
1843  // This is possible as the columns of dkappa/dkp are identical and
1844  // that dkappa/dkp = dsigma/dSp
1845  // C is just a temporary value
1846  // PL is the Planck function for the present temperature value
1847  //
1848  a = 0.0; // Matpack can set all elements like this.
1849  b = 0.0;
1850  c = PLANCK_CONST / BOLTZMAN_CONST / t[ip];
1851  planck( pl, f_mono, t[ip] );
1852  i1 = (Index)is(ip,0); // first LOS point to consider
1853  //
1854  for ( iv=0; iv<nv; iv++ )
1855  {
1856  for ( iw=i1; iw<=(Index)is(ip,1); iw++ )
1857  {
1858  a[iv] += sloswfs[iza](iv,iw) * w[iw-i1];
1859  b[iv] += absloswfs[iza](iv,iw) * w[iw-i1];
1860  }
1861  d = c * f_mono[iv];
1862  k(iv0+iv,ip) = a[iv] * d/t[ip] / (exp(d)-1) * pl[iv] +
1863  b[iv] * dabs_dt(iv,ip);
1864 
1865  // The result for very small values can be NaN. So NaNs (and Infs)
1866  // are set to 0.
1867 #ifdef HPUX
1868  if ( !isfinite(k(iv0+iv,ip)) )
1869 #else
1870  if ( !finite(k(iv0+iv,ip)) )
1871 #endif
1872  k(iv0+iv,ip) = 0.0;
1873 
1874  }
1875  }
1876  }
1877  }
1878 
1879  // Update the frequency index offset
1880  iv0 += nv;
1881  }
1882  out3 << "\n";
1883 }
1884 
1885 
1920  Matrix& kb,
1921  ArrayOfString& kb_names,
1922  Matrix& /* kb_aux */,
1923  Matrix& S_S,
1924  const TagGroups& wfss_tgs,
1925  const TagGroups& tgs,
1926  const Vector& f_mono,
1927  const Vector& p_abs,
1928  const Vector& t_abs,
1929  const Vector& h2o_abs,
1930  const Matrix& vmrs,
1931  const ArrayOfArrayOfLineRecord& lines_per_tg,
1932  const ArrayOfLineshapeSpec& lineshape,
1933  const Los& los,
1934  const ArrayOfMatrix& absweight,
1935  const Index& IndexPar,
1936  const String& StrPar
1937 )
1938  {
1939  // Main sizes
1940  const Index nza = los.start.nelem(); // number of zenith angles
1941  const Index nv = f_mono.nelem(); // number of frequencies
1942  const Index np = p_abs.nelem(); // number of retrieval altitudes
1943  //----------------------------------------------------------------------
1944  // Index:
1945  Index itg, iv, nr_line_total, iza, ip, nr_line;
1946  //----------------------------------------------------------------------
1947  // Other variables:
1948  Matrix abs_line;
1949  Matrix abs_line_changed;
1950  Matrix dabs;
1951  dabs.resize(np,nv);
1952  Matrix dabs1;
1953  dabs1.resize(nv,np);
1954 
1955  //dabs.resize(nv, np);
1956  ArrayOfMatrix abs_dummy1;
1957  ArrayOfMatrix abs_dummy2;
1958  Index itg_wfss;
1959  ArrayOfIndex tag_index;
1960  tag_index.resize(wfss_tgs.nelem());
1961  tag_index = 0;
1962  //Index dummy_line=0;
1963 
1964  // Go through the spectroscopic parameters weighting function
1965  for (itg_wfss=0; itg_wfss<wfss_tgs.nelem(); ++itg_wfss)
1966  {
1967  Index n;
1968  get_tag_group_index_for_tag_group( n, tgs, wfss_tgs[itg_wfss] );
1969  tag_index[itg_wfss] =n;
1970  }
1971 
1972  // Get size for Kb
1973  nr_line_total=0;
1974  nr_line=0;
1975  if (tag_index.nelem()==0)
1976  {
1977  ostringstream os;
1978  os << "No species has been set: "<<"\n";
1979  throw runtime_error(os.str());
1980  }
1981  else
1982  {
1983  for ( itg_wfss=0; itg_wfss<tag_index.nelem(); ++itg_wfss )
1984  {
1985  itg=tag_index[itg_wfss];
1986  nr_line_total+=lines_per_tg[itg].nelem();
1987  }
1988  }
1989  kb.resize(nza*nv,nr_line_total);
1990  kb=0.0;
1991  kb_names.resize(nr_line_total);
1992  S_S.resize(nr_line_total,2);
1993  S_S=0.0;
1994 
1995  // loop:
1996  // 1: over the tags
1997  // 2: over the lines
1998  // 3: over the zenith angles
1999  // 4: over the frequencies
2000 
2001  for ( itg_wfss=0; itg_wfss<tag_index.nelem(); ++itg_wfss )
2002  {
2003  out2<< " \n";
2004  out2<<"==================================: " <<" \n";
2005  out2<<"==Calculating weighting function for species==: " <<" \n";
2006  out2<< wfss_tgs[itg_wfss]<< "\n";
2007  itg=tag_index[itg_wfss];
2008  out2<<"lines found: " <<lines_per_tg[itg].nelem()<< " \n";
2009  Index nr_line_dummy=0;
2010  if ( lines_per_tg[itg].nelem()>0)
2011  {
2012  Vector gamma;
2013  gamma.resize(lines_per_tg[itg].nelem());
2014  gamma=0.0;
2015  for ( Index li=0; li<lines_per_tg[itg].nelem(); ++li )
2016  {
2017  ArrayOfArrayOfLineRecord dummy_lines_per_tg;
2018  dummy_lines_per_tg.resize( lines_per_tg.nelem() );
2019  dummy_lines_per_tg[itg].resize(1);
2020  out3<<"==Calculating weighting function for line==: " <<" \n";
2021  out3<< lines_per_tg[itg][li]<< "\n";
2022  dummy_lines_per_tg[itg][0] = lines_per_tg[itg][li];
2023  // calculate the absorption for unperturbed line;
2024  xsec_per_tgInit( abs_dummy1, tgs, f_mono, p_abs );
2025  xsec_per_tgAddLines( abs_dummy1, tgs, f_mono, p_abs, t_abs,
2026  h2o_abs, vmrs, dummy_lines_per_tg,
2027  lineshape );
2028  absCalcFromXsec(abs_line, abs_dummy2, abs_dummy1 , vmrs );
2029  // define some local variables
2030  Numeric delta_s; // perturbation applied
2031  Numeric parameter; // spectro parameter
2032  Numeric dummy; // perturb spectro parameter
2033  Numeric ER_dummy; // accuracy from spectral database
2034  Vector ER_dummy2; // accuracy in absolute and relative units;
2035  ER_dummy2.resize(2);
2036  ER_dummy2=0.0;
2037  // apply a perturbation to one parameter
2038  switch ( IndexPar )
2039  {
2040  case 1:
2041  {
2042  delta_s = 10E-25; //perturbation in intensity units;
2043  // read the intensity and its uncertainty;
2044  parameter = dummy_lines_per_tg[itg][0].I0();
2045  ER_dummy = dummy_lines_per_tg[itg][0].dI0();
2046  // Set to a default value if there is no field for uncertainty;
2047  if (ER_dummy == -1) //
2048  {ER_dummy = 0.02;}
2049  // get uncertainty in (1) absolute values and (2) relative values;
2050  ER_dummy2[0] = ER_dummy*parameter;
2051  ER_dummy2[1] = ER_dummy*100;
2052  // apply uncertainty and update the value of the parameter;
2053  dummy = parameter +delta_s;
2054  dummy_lines_per_tg[itg][0].setI0(dummy);
2055  break;
2056  }
2057  case 2:
2058  {
2059  delta_s=10; // perturbation in HZ
2060  // read the position and and its uncertainty;
2061  parameter=dummy_lines_per_tg[itg][0].F();
2062  ER_dummy = dummy_lines_per_tg[itg][0].dF();
2063  // Set to a default value if there is no field for uncertainty;
2064  if (ER_dummy==-1)
2065  {ER_dummy=3*1E+9;}
2066  // get uncertainty in absolute values only;
2067  ER_dummy2[0] = ER_dummy;
2068  ER_dummy2[1] = ER_dummy;
2069  // apply uncertainty and update the value of the parameter;
2070  dummy = parameter +delta_s;
2071  dummy_lines_per_tg[itg][0].setF(dummy);
2072  break;
2073  }
2074  case 3:
2075  {
2076  delta_s=0.001; // perturbation in fraction
2077  // read the agam and and its uncertainty;
2078  parameter = dummy_lines_per_tg[itg][0].Agam();
2079  ER_dummy = dummy_lines_per_tg[itg][0].dAgam();
2080  // Set to a default value if there is no field for uncertainty;
2081  if (ER_dummy==-1)
2082  {ER_dummy=2;}
2083  // get uncertainty both in (1) absolute values and (2) relative values;
2084  ER_dummy2[0] = parameter*ER_dummy;
2085  ER_dummy2[1] = ER_dummy*100;
2086  // apply uncertainty and update the value of the parameter;
2087  dummy = parameter +delta_s;
2088  dummy = parameter + parameter *delta_s;
2089  dummy_lines_per_tg[itg][0].setAgam(dummy);
2090  break;
2091  }
2092  case 4:
2093  {
2094  delta_s=0.001; // perturbation in fraction
2095  // read the sgam and and its uncertainty;
2096  parameter=dummy_lines_per_tg[itg][0].Sgam();
2097  ER_dummy = dummy_lines_per_tg[itg][0].dSgam();
2098  // Set to a default value if there is no field for uncertainty;
2099  if (ER_dummy==-1)
2100  {ER_dummy=2;}
2101  // get uncertainty both in (1) absolute values and (2) relative values;
2102  ER_dummy2[0] = parameter*ER_dummy;
2103  ER_dummy2[1] = ER_dummy*100;
2104  // apply uncertainty and update the value of the parameter;
2105  dummy = parameter +parameter*delta_s;
2106  dummy_lines_per_tg[itg][0].setSgam(dummy);
2107  break;
2108  }
2109  case 5:
2110  {
2111  delta_s=0.001; // perturbation in fraction
2112  // read the Nair and and its uncertainty;
2113  parameter=dummy_lines_per_tg[itg][0].Nair();
2114  ER_dummy = dummy_lines_per_tg[itg][0].dNair();
2115  // Set to a default value (200%) if there is no field for uncertainty;
2116  if (ER_dummy==-1)
2117  {ER_dummy=2;}
2118  // get uncertainty both in (1) absolute values and (2) relative values;
2119  ER_dummy2[0] = parameter*ER_dummy;
2120  ER_dummy2[1] = ER_dummy*100;
2121  // apply uncertainty and update the value of the parameter;
2122  dummy = parameter + parameter*delta_s;
2123  dummy_lines_per_tg[itg][0].setNair(dummy);
2124  break;
2125  }
2126  case 6:
2127  {
2128  delta_s=0.01; // perturbation in fraction
2129  // read the Nair and and its uncertainty;
2130  parameter=dummy_lines_per_tg[itg][0].Nself();
2131  ER_dummy = dummy_lines_per_tg[itg][0].dNself();
2132  // Set to a default value (200%) if there is no field for uncertainty;
2133  if (ER_dummy==-1)
2134  {ER_dummy=2;}
2135  // get uncertainty both in (1) absolute values and (2) relative values;
2136  ER_dummy2[0] = parameter*ER_dummy;
2137  ER_dummy2[1] = ER_dummy*100;
2138  // apply uncertainty and update the value of the parameter;
2139  dummy = parameter +parameter*delta_s;
2140  dummy_lines_per_tg[itg][0].setNself(dummy);
2141  break;
2142  }
2143  case 7:
2144  {
2145  extern const Numeric TORR2PA;
2146  delta_s=1;// perturbation i
2147  // read the Nair and and its uncertainty;
2148  parameter=dummy_lines_per_tg[itg][0].Psf();
2149  ER_dummy = dummy_lines_per_tg[itg][0].dPsf();
2150  // Set to a default value (1MHz/Torr) if there is no field for uncertainty;
2151  if ((ER_dummy==-1)|| (parameter==0.0))
2152  {ER_dummy = 1E6 / TORR2PA;}
2153  else
2154  {ER_dummy=ER_dummy*parameter;}
2155  // apply uncertainty and update the value of the parameter;
2156  ER_dummy2[0] = ER_dummy;
2157  ER_dummy2[1] = ER_dummy;
2158  dummy = parameter + delta_s ;
2159  dummy_lines_per_tg[itg][0].setPsf(dummy);
2160  break;
2161  }
2162  default:
2163  {
2164  ostringstream os;
2165  os << "The sectroscopic parameter: " << StrPar<<"\n"
2166  << "does not exists";
2167  throw runtime_error(os.str());
2168  }
2169  }
2170  //calculate the absorption coefficient for the perturbed line
2171  xsec_per_tgInit( abs_dummy1, tgs, f_mono, p_abs );
2172  xsec_per_tgAddLines( abs_dummy1,
2173  tgs, f_mono, p_abs, t_abs, h2o_abs, vmrs,
2174  dummy_lines_per_tg, lineshape );
2175  absCalcFromXsec(abs_line_changed, abs_dummy2, abs_dummy1, vmrs );
2176  abs_line_changed-=abs_line;
2177  dabs1=abs_line_changed;
2178  dabs1/=dummy-parameter;
2179  dabs=transpose(dabs1);
2180  Index iv0=0;
2181  for ( iza=0; iza<nza; iza++ )
2182  {
2183  if ( (iza%20)==0 )
2184  out3 << "\n ";
2185  out3 << " " << iza; cout.flush();
2186  // Do something only if LOS has any points
2187  if ( los.p[iza].nelem() > 0 )
2188  {
2189  for ( iv=0; iv<nv; iv++ )
2190  {
2191  for ( ip=0; ip<np; ip++ )
2192  {
2193  kb(iv0+iv, nr_line)+= absweight[iza](iv,ip)* dabs(ip, iv);
2194  }
2195  // The result for very small values can be NaN. So NaNs (and Infs)
2196  // are set to 0.
2197 #ifdef HPUX
2198  if ( !isfinite(kb(iv0+iv, nr_line)) )
2199 #else
2200  if ( !finite(kb(iv0+iv, nr_line)) )
2201 #endif
2202  kb(iv0+iv,nr_line) = 0.0;
2203  }
2204  iv0+=nv;
2205  }
2206  }
2207  Numeric nr = dummy_lines_per_tg[itg][0].F() *1e-9;
2208  ostringstream os;
2209  // create the sting for the name parameter (written in kb_name)
2210  // line (species and center frequency)+ uncertinity + name parameter
2211  if (IndexPar == 2)
2212  {
2213  os <<tgs[itg]<<"@" <<nr<<"GHz"<<" / "<<StrPar<<": " << ER_dummy2[1] <<"Hz";
2214  }
2215  else if (IndexPar == 7)
2216  {
2217  os <<tgs[itg]<<"@" <<nr<<"GHz"<<" / "<<StrPar<<": " << ER_dummy2[1] <<"Hz/Pa";
2218  }
2219 
2220  else
2221  {
2222  os <<tgs[itg]<<"@" <<nr<<"GHz"<<" / "<<StrPar<<": " << ER_dummy2[1]<< "%";
2223  }
2224  kb_names[nr_line]= os.str();
2225  S_S(nr_line, Range(joker))= ER_dummy2;
2226  ++nr_line;
2227  ++nr_line_dummy;
2228  }
2229  }
2230  }
2231  }
2232 
2268 void kSpectro (
2269  Matrix& k,
2270  ArrayOfString& k_names,
2271  Matrix& /* kb_aux */,
2272  Matrix& S_S,
2273  const TagGroups& wfss_tgs,
2274  const TagGroups& tgs,
2275  const Vector& f_mono,
2276  const Vector& p_abs,
2277  const Vector& t_abs,
2278  const Vector& z_abs,
2279  const Vector& h2o_abs,
2280  const Matrix& vmrs,
2281  const ArrayOfArrayOfLineRecord& lines_per_tg,
2282  const ArrayOfLineshapeSpec& lineshape,
2283  const Los& los,
2284  const ArrayOfMatrix& absloswfs,
2285  // Keywords
2286  const Index& kw_intens,
2287  const Index& kw_position,
2288  const Index& kw_agam,
2289  const Index& kw_sgam,
2290  const Index& kw_nair,
2291  const Index& kw_nself,
2292  const Index& kw_pSift)
2293 {
2294 
2295  check_if_bool( kw_intens, "do_intens keyword" );
2296  check_if_bool( kw_position, "do_position keyword" );
2297  check_if_bool( kw_agam, "do_agam keyword" );
2298  check_if_bool( kw_sgam, "do_sgam keyword" );
2299  check_if_bool( kw_nair, "do_nair keyword" );
2300  check_if_bool( kw_nself, "do_nself keyword" );
2301  check_if_bool( kw_pSift, "do_pSift keyword" );
2302  check_lengths( p_abs, "p_abs", t_abs, "t_abs" );
2303  check_lengths( p_abs, "p_abs", z_abs, "z_abs" );
2304  check_lengths( p_abs, "p_abs", h2o_abs, "h2o_abs" );
2305  check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
2306 
2307  // Main sizes
2308  const Index nza = los.start.nelem(); // number of zenith angles
2309  const Index nv = f_mono.nelem(); // number of frequencies
2310  //
2311  // Indices
2312  // IP0 and IF0 are the index off-sets for the total K matrix
2313  Index iza; // zenith angle index
2314  Index itg;
2315 
2316  // Other variables
2317  ArrayOfMatrix W; // keeps dkappa/dk;
2318  ArrayOfMatrix absweight; // the product di/dkappa * dkappa/dk;
2319  absweight.resize(nza);
2320  ArrayOfIndex k_lengths;
2321  Matrix kb;
2322  ArrayOfString kb_names;
2323  Matrix kb_aux;
2324  Matrix abs_line;
2325  Matrix abs_line_changed;
2326  Matrix ER;
2327  ArrayOfMatrix abs_dummy1;
2328  Index IndexPar; // spectro parameters to be investigated
2329  String StrPar;
2330  Index ipar = 0; // index for the parameter
2331 
2332  // Calculate weights for conversion between LOS grids and pressure grid: dkappa/dk;
2333  grid2grid_weights_total(W, los, p_abs);
2334  // Calculate the product di/dkappa * dkappa/dk;
2335  for ( iza=0; iza<nza; iza++ )
2336  {
2337  absweight[iza].resize(absloswfs[iza].nrows(), W[iza].ncols());
2338  // Do something only if LOS has any points
2339  if ( los.p[iza].nelem() > 0 )
2340  {
2341  mult(absweight[iza], absloswfs[iza], W[iza]);
2342  }
2343  }
2344 
2345 // get size of k
2346  if (kw_intens)
2347  { ++ipar;}
2348  if (kw_position)
2349  { ++ipar;}
2350  if (kw_agam)
2351  { ++ipar;}
2352  if (kw_sgam)
2353  { ++ipar;}
2354  if (kw_nair)
2355  { ++ipar;}
2356  if (kw_nself)
2357  { ++ipar;}
2358  if (kw_pSift)
2359  { ++ipar;}
2360  Index nr_line_total=0;
2361  Index itg_wfss;
2362  ArrayOfIndex tag_index;
2363  tag_index.resize(wfss_tgs.nelem());
2364  tag_index = 0;
2365 
2366 
2367  // Go through the spectroscopic parameters weighting function
2368  for (itg_wfss=0; itg_wfss<wfss_tgs.nelem(); ++itg_wfss)
2369  {
2370  Index n;
2371  get_tag_group_index_for_tag_group( n, tgs, wfss_tgs[itg_wfss] );
2372  tag_index[itg_wfss] =n;
2373  }
2374 
2375  // Get size for Kb
2376  nr_line_total=0;
2377 
2378  // Calculate the total number of lines for which the weighting
2379  // function is calculated. In caz no speciaes are specified in wtgss
2380  // then an error messege is given.
2381  if (tag_index.nelem()==0)
2382  {
2383  ostringstream os;
2384  os << "No species has been set: "<<"\n";
2385  throw runtime_error(os.str());
2386  }
2387  else
2388  {
2389  for ( itg_wfss=0; itg_wfss<tag_index.nelem(); ++itg_wfss )
2390  {
2391  itg=tag_index[itg_wfss];
2392  nr_line_total+=lines_per_tg[itg].nelem();
2393  }
2394  }
2395 
2396  // Check whether the spectroscopic parameters for which to calculate the
2397  // weighting function are set or lines in the spectral data are found.
2398  if (ipar == 0)
2399  {
2400  ostringstream os;
2401  os << "No sectroscopic parameters have been set";
2402  throw runtime_error(os.str());
2403  }
2404  if (nr_line_total == 0)
2405  {
2406  ostringstream os;
2407  os << " No line for which to calculate weighting function has been found. Catalog empty?";
2408  throw runtime_error(os.str());
2409  }
2410 
2411  k.resize(nza*nv, nr_line_total*ipar);
2412  k=0.0;
2413  k_names.resize(nr_line_total*ipar);
2414  S_S.resize(nr_line_total*ipar,2);
2415  ER.resize(nr_line_total,2);
2416 
2417  // Go through the spectroscopic parameters and calculate the weighting function.
2418  Index nr_line=0;
2419 
2420  // for intemsity
2421  if (kw_intens)
2422  {
2423  IndexPar = 1;
2424  StrPar = "S";
2425  out1<< " \n";
2426  out1<<"==================================: " <<" \n";
2427  out1<<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2428  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, tgs,
2429  f_mono, p_abs, t_abs,
2430  h2o_abs, vmrs, lines_per_tg, lineshape, los, absweight,
2431  IndexPar, StrPar);
2432  k(Range(joker),Range(nr_line, kb.ncols()))= kb;
2433  // ER.resize(kb_names.nelem(),2);
2434  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2435  {
2436  k_names[nr_line+iri]= kb_names[iri];
2437  S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
2438  }
2439  nr_line+=kb.ncols();
2440  }
2441  // for line position
2442  if (kw_position)
2443  {
2444  IndexPar = 2;
2445  StrPar = "f0";
2446  out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2447  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, tgs,
2448  f_mono, p_abs, t_abs,
2449  h2o_abs, vmrs, lines_per_tg,
2450  lineshape, los, absweight, IndexPar, StrPar);
2451  k(Range(joker), Range(nr_line, kb.ncols()))= kb;
2452  // ER.resize(kb_names.nelem(),2);
2453  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2454  {
2455  k_names[nr_line+iri]= kb_names[iri];
2456  S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
2457  }
2458  nr_line+=kb.ncols();
2459  }
2460  // for air broadening parameter agam
2461  if (kw_agam)
2462  {
2463  IndexPar = 3;
2464  StrPar = "agam";
2465  out1<<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2466  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs,
2467  tgs, f_mono, p_abs, t_abs,
2468  h2o_abs, vmrs, lines_per_tg,
2469  lineshape, los, absweight, IndexPar, StrPar);
2470  k(Range(joker),Range(nr_line, kb.ncols()))= kb;
2471  //ER.resize(kb_names.nelem(),2);
2472  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2473  {
2474  k_names[nr_line+iri]= kb_names[iri];
2475  S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
2476  }
2477  nr_line+=kb.ncols();
2478  }
2479 // for self broadening parameter sgam
2480  if (kw_sgam)
2481  {
2482  IndexPar = 4;
2483  StrPar = "sgam";
2484  out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2485  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs,
2486  tgs, f_mono, p_abs, t_abs,
2487  h2o_abs, vmrs, lines_per_tg,
2488  lineshape, los, absweight, IndexPar, StrPar);
2489  k(Range(joker),Range(nr_line, kb.ncols()))= kb;
2490  //ER.resize(kb_names.nelem(),2);
2491  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2492  {
2493  k_names[nr_line+iri]= kb_names[iri];
2494  S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
2495  }
2496  nr_line+=kb.ncols();
2497  }
2498  // for air broadening parameter nair
2499  if (kw_nair)
2500  {
2501  IndexPar = 5;
2502  StrPar = "na";
2503  out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2504  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs,
2505  tgs, f_mono, p_abs, t_abs,
2506  h2o_abs, vmrs, lines_per_tg,
2507  lineshape, los, absweight, IndexPar, StrPar);
2508  k(Range(joker),Range(nr_line, kb.ncols()))= kb;
2509  //ER.resize(kb_names.nelem(),2);
2510  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2511  {
2512  k_names[nr_line+iri]= kb_names[iri];
2513  S_S(nr_line+iri, Range(joker)) = ER(iri, Range(joker));
2514  }
2515  nr_line+=kb.ncols();
2516  }
2517 // for self broadening parameter nself
2518  if (kw_nself)
2519  {
2520  IndexPar = 6;
2521  StrPar = "ns";
2522  out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2523  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs,
2524  tgs, f_mono, p_abs, t_abs,
2525  h2o_abs, vmrs, lines_per_tg, lineshape, los, absweight,
2526  IndexPar, StrPar);
2527  k(Range(joker),Range(nr_line, kb.ncols()))= kb;
2528  // ER.resize(kb_names.nelem(),2);
2529  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2530  {
2531  k_names[nr_line+iri]= kb_names[iri];
2532  S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
2533  }
2534  nr_line+=kb.ncols();
2535  }
2536  // for pressure shift
2537  if (kw_pSift)
2538  {
2539  IndexPar = 7;
2540  StrPar = "pSf";
2541  out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n";
2542  kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs,
2543  tgs, f_mono, p_abs, t_abs,
2544  h2o_abs, vmrs, lines_per_tg, lineshape, los, absweight,
2545  IndexPar, StrPar);
2546  k(Range(joker),Range(nr_line, kb.ncols()))= kb;
2547  ER.resize(kb_names.nelem(),2);
2548  for ( Index iri=0; iri<kb_names.nelem(); iri++)
2549  {
2550  k_names[nr_line+iri]= kb_names[iri];
2551  S_S(nr_line+iri, Range(joker)) = ER(iri, Range(joker));
2552  }
2553  nr_line+=kb.ncols();
2554  }
2555  if (ipar == 0)
2556  {
2557  ostringstream os;
2558  os << "No sectroscopic parameters have been set";
2559  throw runtime_error(os.str());
2560  }
2561 }
2562 
2564 // Workspace methods
2566 
2567 
2574 void wfs_tgsDefine(// WS Output:
2575  TagGroups& wfs_tag_groups,
2576  // Control Parameters:
2577  const ArrayOfString& tags)
2578 {
2579  wfs_tag_groups = TagGroups(tags.nelem());
2580 
2581  // Each element of the array of Strings tags defines one tag
2582  // group. Let's work through them one by one.
2583  for ( Index i=0; i<tags.nelem(); ++i )
2584  {
2585  // There can be a comma separated list of tag definitions, so we
2586  // need to break the String apart at the commas.
2587  ArrayOfString tag_def;
2588 
2589  bool go_on = true;
2590  String these_tags = tags[i];
2591  while (go_on)
2592  {
2593  Index n = (Index)these_tags.find(',');
2594  if ( n == these_tags.npos ) // npos indicates `not found'
2595  {
2596  // There are no more commas.
2597  tag_def.push_back(these_tags);
2598  go_on = false;
2599  }
2600  else
2601  {
2602  tag_def.push_back(these_tags.substr(0,n));
2603  these_tags.erase(0,n+1);
2604  }
2605  }
2606 
2607  // Unfortunately, MTL conatains a bug that leads to all elements of
2608  // the outer Array of an Array<Array>> pointing to the same data
2609  // after creation. So we need to fix this explicitly:
2610  wfs_tag_groups[i] = Array<OneTag>();
2611 
2612  for ( Index s=0; s<tag_def.nelem(); ++s )
2613  {
2614  // Remove leading whitespace, if there is any:
2615  while ( ' ' == tag_def[s][0] ||
2616  '\t' == tag_def[s][0] ) tag_def[s].erase(0,1);
2617 
2618  OneTag this_tag(tag_def[s]);
2619 
2620  // Safety check: For s>0 check that the tags belong
2621  // to the same species.
2622  if (s>0)
2623  if ( wfs_tag_groups[i][0].Species() != this_tag.Species() )
2624  throw runtime_error(
2625  "Tags in a tag group must belong to the same species.");
2626 
2627  wfs_tag_groups[i].push_back(this_tag);
2628  }
2629  }
2630 
2631  // Print list of tag groups to the most verbose output stream:
2632  out3 << " Defined weighting function tag groups:";
2633  for ( Index i=0; i<wfs_tag_groups.nelem(); ++i )
2634  {
2635  out3 << "\n " << i << ":";
2636  for ( Index s=0; s<wfs_tag_groups[i].nelem(); ++s )
2637  {
2638  out3 << " " << wfs_tag_groups[i][s].Name();
2639  }
2640  }
2641  out3 << '\n';
2642 }
2643 
2650 void wfss_tgsDefine(// WS Output:
2651  TagGroups& wfss_tgs,
2652  // Control Parameters:
2653  const ArrayOfString& tags)
2654 {
2655  wfss_tgs = TagGroups(tags.nelem());
2656 
2657  // Each element of the array of Strings tags defines one tag
2658  // group. Let's work through them one by one.
2659  for ( Index i=0; i<tags.nelem(); ++i )
2660  {
2661  // There can be a comma separated list of tag definitions, so we
2662  // need to break the String apart at the commas.
2663  ArrayOfString tag_def;
2664 
2665  bool go_on = true;
2666  String these_tags = tags[i];
2667  while (go_on)
2668  {
2669  Index n = (Index)these_tags.find(',');
2670  if ( n == these_tags.npos ) // npos indicates `not found'
2671  {
2672  // There are no more commas.
2673  tag_def.push_back(these_tags);
2674  go_on = false;
2675  }
2676  else
2677  {
2678  tag_def.push_back(these_tags.substr(0,n));
2679  these_tags.erase(0,n+1);
2680  }
2681  }
2682 
2683  // Unfortunately, MTL conatains a bug that leads to all elements of
2684  // the outer Array of an Array<Array>> pointing to the same data
2685  // after creation. So we need to fix this explicitly:
2686  wfss_tgs[i] = Array<OneTag>();
2687 
2688  for ( Index s=0; s<tag_def.nelem(); ++s )
2689  {
2690  // Remove leading whitespace, if there is any:
2691  while ( ' ' == tag_def[s][0] ||
2692  '\t' == tag_def[s][0] ) tag_def[s].erase(0,1);
2693 
2694  OneTag this_tag(tag_def[s]);
2695 
2696  // Safety check: For s>0 check that the tags belong
2697  // to the same species.
2698  if (s>0)
2699  if ( wfss_tgs[i][0].Species() != this_tag.Species() )
2700  throw runtime_error(
2701  "Tags in a tag group must belong to the same species.");
2702 
2703  wfss_tgs[i].push_back(this_tag);
2704  }
2705  }
2706 
2707  // Print list of tag groups to the most verbose output stream:
2708  out3 << " Defined weighting function tag groups:";
2709  for ( Index i=0; i<wfss_tgs.nelem(); ++i )
2710  {
2711  out3 << "\n " << i << ":";
2712  for ( Index s=0; s<wfss_tgs[i].nelem(); ++s )
2713  {
2714  out3 << " " << wfss_tgs[i][s].Name();
2715  }
2716  }
2717  out3 << '\n';
2718 }
2719 
2727  ArrayOfMatrix& absloswfs,
2728  const Index& emission,
2729  const Los& los,
2730  const ArrayOfMatrix& source,
2731  const ArrayOfMatrix& trans,
2732  const Vector& y,
2733  const Vector& y_space,
2734  const Vector& f_mono,
2735  const Vector& e_ground,
2736  const Numeric& t_ground )
2737 {
2738  check_if_bool( emission, "emission" );
2739 
2740  if ( emission == 0 )
2741  absloswfs_tau ( absloswfs, los, f_mono );
2742  else
2743  absloswfs_rte ( absloswfs, los, source, trans, y, y_space, f_mono,
2744  e_ground, t_ground );
2745 
2746  // The equations used can produce NaNs and Infs when the optical thickness
2747  // is very high. This corresponds to extremly low values for the ABS LOS WFs
2748  // so we set NaNs and Infs to zero.
2749  Index irow, icol, ncol;
2750  Numeric w;
2751  for( Index im=0; im<absloswfs.nelem(); im++ )
2752  {
2753  for( irow=0; irow<absloswfs[im].nrows(); irow++ )
2754  {
2755  ncol = absloswfs[im].ncols();
2756  for( icol=0; icol<ncol; icol++ )
2757  {
2758  w = absloswfs[im](irow,icol);
2759 #ifdef HPUX
2760  if ( !isfinite(w) )
2761 #else
2762  if ( !finite(w) )
2763 #endif
2764  absloswfs[im](irow,icol) = 0.0;
2765  }
2766  }
2767  }
2768 }
2769 
2770 
2771 
2778 void kSpecies (
2779  Matrix& k,
2780  ArrayOfString& k_names,
2781  Matrix& k_aux,
2782  const Los& los,
2783  const ArrayOfMatrix& absloswfs,
2784  const Vector& p_abs,
2785  const Vector& t_abs,
2786  const TagGroups& wfs_tgs,
2787  const ArrayOfMatrix& abs_per_tg,
2788  const Matrix& vmrs,
2789  const Vector& k_grid,
2790  const String& unit )
2791 {
2792  // Check of input is performed in k_species
2793 
2794  const Index ntg = wfs_tgs.nelem(); // number of retrieval tags
2795  ArrayOfIndex tg_nr(ntg);
2796 
2797  for ( Index i=0; i<ntg; i++ )
2798  tg_nr[i] = i;
2799 
2800  k_species( k, k_names, k_aux, los, absloswfs, p_abs, t_abs,
2801  wfs_tgs, abs_per_tg, vmrs, k_grid, tg_nr, unit );
2802 }
2803 
2804 
2805 
2813  Matrix& k,
2814  ArrayOfString& k_names,
2815  Matrix& k_aux,
2816  const Los& los,
2817  const ArrayOfMatrix& absloswfs,
2818  const Vector& p_abs,
2819  const Vector& t_abs,
2820  const TagGroups& wfs_tgs,
2821  const ArrayOfMatrix& abs_per_tg,
2822  const Matrix& vmrs,
2823  const Vector& k_grid,
2824  const String& tg,
2825  const String& unit )
2826 {
2827  // Check of input is performed in k_species
2828 
2829  ArrayOfString tg_name(1);
2830  tg_name[0] = tg;
2831 
2832  ArrayOfIndex tg_nr;
2833  get_tagindex_for_Strings( tg_nr, wfs_tgs, tg_name );
2834 
2835  k_species( k, k_names, k_aux, los, absloswfs, p_abs, t_abs,
2836  wfs_tgs, abs_per_tg, vmrs, k_grid, tg_nr, unit );
2837 }
2838 
2839 
2840 
2847 void kContAbs (
2848  Matrix& k,
2849  ArrayOfString& k_names,
2850  Matrix& k_aux,
2851  const Los& los,
2852  const ArrayOfMatrix& absloswfs,
2853  const Vector& f_mono,
2854  const Vector& k_grid,
2855  const Index& order,
2856  const Numeric& f_low,
2857  const Numeric& f_high,
2858  const String& l_unit )
2859 {
2860  // Input is checked in k_contabs
2861 
2862  Numeric f1=f_low, f2=f_high;
2863 
2864  if ( f1 < 0 )
2865  f1 = first( f_mono );
2866  if ( f2 < 0 )
2867  f2 = last( f_mono );
2868 
2869  k_contabs( k, k_names, k_aux, los, absloswfs, f_mono, k_grid, order, f1, f2,
2870  l_unit );
2871 }
2872 
2873 
2874 
2881 void kTemp (
2882  Matrix& k,
2883  ArrayOfString& k_names,
2884  Matrix& k_aux,
2885  const TagGroups& tgs,
2886  const Vector& f_mono,
2887  const Vector& p_abs,
2888  const Vector& t_abs,
2889  const Vector& n2_abs,
2890  const Vector& h2o_abs,
2891  const Matrix& vmrs,
2892  const Matrix& abs0,
2893  const ArrayOfArrayOfLineRecord& lines_per_tg,
2894  const ArrayOfLineshapeSpec& lineshape,
2895  const Vector& e_ground,
2896  const Index& emission,
2897  const Vector& k_grid,
2898  const ArrayOfString& cont_description_names,
2899  const ArrayOfVector& cont_description_parameters,
2900  const ArrayOfString& cont_description_models,
2901  const Los& los,
2902  const ArrayOfMatrix& absloswfs,
2903  const ArrayOfMatrix& trans,
2904  const Numeric& z_plat,
2905  const Vector& za,
2906  const Numeric& l_step,
2907  const Vector& z_abs,
2908  const Index& refr,
2909  const Index& refr_lfac,
2910  const Vector& refr_index,
2911  const String& refr_model,
2912  const Numeric& z_ground,
2913  const Numeric& t_ground,
2914  const Vector& y_space,
2915  const Numeric& r_geoid,
2916  const Vector& hse,
2917  // Keywords
2918  const Index& kw_hse,
2919  const Index& kw_fast )
2920 {
2921  check_if_bool( kw_hse, "hse keyword" );
2922  check_if_bool( kw_fast, "fast keyword" );
2923  check_if_bool( emission, "emission" );
2924  check_if_bool( refr, "refr" );
2925  check_lengths( p_abs, "p_abs", t_abs, "t_abs" );
2926  check_lengths( p_abs, "p_abs", z_abs, "z_abs" );
2927  check_lengths( p_abs, "p_abs", h2o_abs, "h2o_abs" );
2928  check_lengths( p_abs, "p_abs", n2_abs, "n2_abs" );
2929  check_length_ncol( p_abs, "p_abs", abs0, "abs" );
2930  check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
2931  check_length_nrow( f_mono, "f_mono", abs0, "abs" );
2932  if ( los.p.nelem() != za.nelem() )
2933  throw runtime_error(
2934  "The number of zenith angles of *za* and *los* are different.");
2935  //
2936  if( refr )
2937  check_lengths( p_abs, "p_abs", refr_index, "refr_index" );
2938  //
2939  if ( !kw_hse )
2940  {
2941  if ( los.p.nelem() != trans.nelem() )
2942  throw runtime_error(
2943  "The number of zenith angles of *los* and *trans* are different.");
2944 
2945  if ( los.p.nelem() != absloswfs.nelem() )
2946  throw runtime_error(
2947  "The number of zenith angles is not the same in *los* and *absloswfs*.");
2948  }
2949  else
2950  {
2951  if ( hse[0]==0 )
2952  throw runtime_error( "Hydrostatic eq. must be considered generally"
2953  "when calculating WFs with hydrostatic eq.");
2954  }
2955  //
2956  if ( any_ground(los.ground) )
2957  {
2958  if ( t_ground <= 0 )
2959  throw runtime_error(
2960  "There are intersections with the ground, but the ground\n"
2961  "temperature is set to be <=0 (are dummy values used?).");
2962  if ( e_ground.nelem() != f_mono.nelem() )
2963  throw runtime_error(
2964  "There are intersections with the ground, but the frequency and\n"
2965  "ground emission vectors have different lengths (are dummy values\n"
2966  "used?).");
2967  }
2968  if ( emission )
2969  check_lengths( f_mono, "f_mono", y_space, "y_space" );
2970 
2971  //
2972  // Three options:
2973  // 1. no hydrostatic eq., use analytical expressions
2974  // 2. hydrostatic eq., fast version
2975  // 3. hydrostatic eq., accurate version
2976  //
2977 
2978 
2979  // No hydrostatic eq., use analytical expressions
2980  //---------------------------------------------------------------------------
2981  if ( !kw_hse )
2982  {
2983  if ( !emission )
2984  throw runtime_error(
2985  "Analytical expressions for temperature and no emission have not\n"
2986  "yet been implemented. Sorry!");
2987 
2988  k_temp_nohydro( k, k_names, k_aux, tgs, los, absloswfs, f_mono,
2989  p_abs, t_abs, n2_abs, h2o_abs, vmrs, lines_per_tg, lineshape, abs0, trans,
2990  e_ground, k_grid, cont_description_names, cont_description_parameters,
2991  cont_description_models);
2992  }
2993 
2994 
2995  // Hydrostatic eq., fast version
2996  //---------------------------------------------------------------------------
2997  else if ( kw_fast )
2998  {
2999  // Main sizes
3000  const Index nza = za.nelem(); // number of zenith angles
3001  const Index nv = f_mono.nelem(); // number of frequencies
3002  const Index np = k_grid.nelem(); // number of retrieval altitudes
3003  const Index nabs = p_abs.nelem(); // number of absorption altitudes
3004 
3005  // Vectors for the reference state
3006  Vector z0(nabs), y0, t0(np);
3007 
3008  // Local copy of hse
3009  Vector hse_local( hse );
3010 
3011  // Calculate reference z_abs with a high number of iterations
3012  hse_local[4] = 5;
3013  z0 = z_abs;
3014  hseCalc( z0, p_abs, t_abs, h2o_abs, r_geoid, hse_local );
3015  hse_local[4] = hse[4];
3016 
3017  // Calculate absorption for + 1K
3018  Matrix abs1k, abs(nv,nabs);
3019  ArrayOfMatrix abs_dummy;
3020  //
3021  {
3022  Vector t(t_abs);
3023  t += 1.;
3024  //
3025  out1 << " Calculating absorption for t_abs + 1K \n";
3026  out2 << " ----- Messages from absCalc: --------\n";
3027  absCalc( abs1k, abs_dummy, tgs, f_mono, p_abs, t, n2_abs, h2o_abs, vmrs,
3028  lines_per_tg, lineshape, cont_description_names,
3029  cont_description_models, cont_description_parameters);
3030  }
3031  // Calculate reference spectrum
3032  out1 << " Calculating reference spectrum\n";
3033  out2 << " ----- Messages from losCalc: --------\n";
3034  Los los;
3035  Vector z_tan;
3036  losCalc( los, z_tan, z_plat, za, l_step, p_abs, z0, refr, refr_lfac,
3037  refr_index, z_ground, r_geoid );
3038  out2 << " -------------------------------------\n";
3039  out2 << " ----- Messages from sourceCalc: -----\n";
3040  ArrayOfMatrix source, trans;
3041  sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
3042  out2 << " -------------------------------------\n";
3043  out2 << " ----- Messages from transCalc: ------\n";
3044  transCalc( trans, los, p_abs, abs0 );
3045  out2 << " -------------------------------------\n";
3046  out2 << " ----- Messages from yRte: -----------\n";
3047  yCalc( y0, emission, los, f_mono, y_space, source, trans,
3048  e_ground, t_ground );
3049  out2 << " -------------------------------------\n";
3050 
3051  // Allocate K and fill aux. variables
3052  k.resize(nza*nv,np);
3053  k_names.resize(1);
3054  k_names[0] = "Temperature: with hydrostatic eq.";
3055  k_aux.resize(np,2);
3056  interpp( t0, p_abs, t_abs, k_grid );
3057  for ( Index ip=0; ip<np; ip++ )
3058  {
3059  k_aux(ip,0) = k_grid[ip];
3060  k_aux(ip,1) = t0[ip];
3061  }
3062 
3063  // Determine conversion between grids
3064  Matrix is;
3065  Vector lpabs, lgrid;
3066  p2grid( lpabs, p_abs );
3067  p2grid( lgrid, k_grid );
3068  grid2grid_index( is, lpabs, lgrid );
3069 
3070  // Loop retrieval altitudes and calculate new spectra
3071  //
3072  Vector y, t(nabs), w, refr4t, z4t(nabs);
3073  Index i1, iw, iv;
3074  //
3075  for ( Index ip=0; ip<np; ip++ )
3076  {
3077  out1 << " Doing altitude " << ip+1 << "/" << np << "\n";
3078 
3079  // Create absorption matrix and temperature profile corresponding to
3080  // temperature disturbance
3081  grid2grid_weights( w, lpabs, Index(is(ip,0)), Index(is(ip,1)),
3082  lgrid, ip );
3083  i1 = Index( is(ip,0) ); // first p_abs point to consider
3084 
3085  abs = abs0;
3086  t = t_abs;
3087  for ( iw=i1; iw<=Index(is(ip,1)); iw++ )
3088  {
3089  t[iw] += w[iw-i1];
3090  for ( iv=0; iv<nv; iv++ )
3091  abs(iv,iw) = (1-w[iw-i1])*abs0(iv,iw) + w[iw-i1]*abs1k(iv,iw);
3092  }
3093 
3094  out2 << " ----- Doing new refractive index ----\n";
3095  refrCalc ( refr4t, p_abs, t, h2o_abs, refr, refr_model );
3096  out2 << " ----- Doing new hydrostatic eq. -----\n";
3097  z4t = z0;
3098  hseCalc( z4t, p_abs, t, h2o_abs, r_geoid, hse );
3099  out2 << " ----- Messages from losCalc: --------\n";
3100  losCalc( los, z_tan, z_plat, za, l_step, p_abs, z4t, refr, refr_lfac,
3101  refr_index, z_ground, r_geoid );
3102  out2 << " -------------------------------------\n";
3103  out2 << " ----- Messages from sourceCalc: -----\n";
3104  ArrayOfMatrix source, trans;
3105  sourceCalc( source, emission, los, p_abs, t, f_mono );
3106  out2 << " -------------------------------------\n";
3107  out2 << " ----- Messages from transCalc: ------\n";
3108  transCalc( trans, los, p_abs, abs );
3109  out2 << " -------------------------------------\n";
3110  out2 << " ----- Messages from yRte: -----------\n";
3111  yCalc( y, emission, los, f_mono, y_space, source, trans,
3112  e_ground, t_ground );
3113  out2 << " -------------------------------------\n";
3114 
3115  // Fill K
3116  for ( iv=0; iv<nza*nv; iv++ )
3117  k(iv,ip) = y[iv] - y0[iv];
3118  }
3119  }
3120 
3121 
3122  // Hydrostatic eq., accurate version
3123  //---------------------------------------------------------------------------
3124  else
3125  {
3126  // Main sizes
3127  const Index nza = za.nelem(); // number of zenith angles
3128  const Index nv = f_mono.nelem(); // number of frequencies
3129  const Index np = k_grid.nelem(); // number of retrieval altitudes
3130  const Index nabs = p_abs.nelem(); // number of absorption altitudes
3131 
3132  // Vectors for the reference state
3133  Vector z0(nabs), y0, t0(np);
3134 
3135  // Local copy of hse
3136  Vector hse_local( hse );
3137 
3138  // Calculate reference z_abs with a high number of iterations
3139  hse_local[4] = 5;
3140  z0 = z_abs;
3141  hseCalc( z0, p_abs, t_abs, h2o_abs, r_geoid, hse_local );
3142  hse_local[4] = hse[4];
3143 
3144  // Calculate reference spectrum
3145  out1 << " Calculating reference spectrum\n";
3146  out2 << " ----- Messages from losCalc: --------\n";
3147  Los los;
3148  Vector z_tan;
3149  losCalc( los, z_tan, z_plat, za, l_step, p_abs, z0, refr, refr_lfac,
3150  refr_index, z_ground, r_geoid );
3151  out2 << " -------------------------------------\n";
3152  out2 << " ----- Messages from sourceCalc: -----\n";
3153  ArrayOfMatrix source, trans;
3154  sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
3155  out2 << " -------------------------------------\n";
3156  out2 << " ----- Messages from transCalc: ------\n";
3157  transCalc( trans, los, p_abs, abs0 );
3158  out2 << " -------------------------------------\n";
3159  out2 << " ----- Messages from yRte: -----------\n";
3160  yCalc( y0, emission, los, f_mono, y_space, source, trans,
3161  e_ground, t_ground );
3162  out2 << " -------------------------------------\n";
3163 
3164  // Allocate K and fill aux. variables
3165  k.resize(nza*nv,np);
3166  k_names.resize(1);
3167  k_names[0] = "Temperature: with hydrostatic eq.";
3168  k_aux.resize(np,2);
3169  interpp( t0, p_abs, t_abs, k_grid );
3170  for ( Index ip=0; ip<np; ip++ )
3171  {
3172  k_aux(ip,0) = k_grid[ip];
3173  k_aux(ip,1) = t0[ip];
3174  }
3175 
3176  // Determine conversion between grids
3177  Matrix is;
3178  Vector lpabs, lgrid;
3179  p2grid( lpabs, p_abs );
3180  p2grid( lgrid, k_grid );
3181  grid2grid_index( is, lpabs, lgrid );
3182 
3183  // Loop retrieval altitudes and calculate new spectra
3184  //
3185  Matrix abs;
3186  ArrayOfMatrix abs_dummy;
3187  Vector y, t(nabs), w, refr4t, z4t(nabs);
3188  Index i1, iw, iv;
3189  //
3190  for ( Index ip=0; ip<np; ip++ )
3191  {
3192  out1 << " Doing altitude " << ip+1 << "/" << np << "\n";
3193 
3194  // Create disturbed temperature profile
3195  grid2grid_weights( w, lpabs, Index(is(ip,0)), Index(is(ip,1)),
3196  lgrid, ip );
3197  i1 = Index( is(ip,0) ); // first p_abs point to consider
3198 
3199  t = t_abs;
3200  for ( iw=i1; iw<=Index(is(ip,1)); iw++ )
3201  t[iw] += w[iw-i1];
3202 
3203  out2 << " ----- Messages from absCalc: --------\n";
3204  absCalc( abs, abs_dummy, tgs, f_mono, p_abs, t, n2_abs, h2o_abs, vmrs,
3205  lines_per_tg, lineshape, cont_description_names,
3206  cont_description_models, cont_description_parameters);
3207  out2 << " ----- Doing new refractive index ----\n";
3208  refrCalc ( refr4t, p_abs, t, h2o_abs, refr, refr_model );
3209  out2 << " ----- Doing new hydrostatic eq. -----\n";
3210  z4t = z0;
3211  hseCalc( z4t, p_abs, t, h2o_abs, r_geoid, hse );
3212  out2 << " ----- Messages from losCalc: --------\n";
3213  losCalc( los, z_tan, z_plat, za, l_step, p_abs, z4t, refr, refr_lfac,
3214  refr4t, z_ground, r_geoid );
3215  out2 << " -------------------------------------\n";
3216  out2 << " ----- Messages from sourceCalc: -----\n";
3217  ArrayOfMatrix source, trans;
3218  sourceCalc( source, emission, los, p_abs, t, f_mono );
3219  out2 << " -------------------------------------\n";
3220  out2 << " ----- Messages from transCalc: ------\n";
3221  transCalc( trans, los, p_abs, abs );
3222  out2 << " -------------------------------------\n";
3223  out2 << " ----- Messages from yRte: -----------\n";
3224  yCalc( y, emission, los, f_mono, y_space, source, trans,
3225  e_ground, t_ground );
3226  out2 << " -------------------------------------\n";
3227 
3228  // Fill K
3229  for ( iv=0; iv<nza*nv; iv++ )
3230  k(iv,ip) = y[iv] - y0[iv];
3231  }
3232  }
3233 }
3234 
3235 
3236 
3244  Matrix& k,
3245  ArrayOfString& k_names,
3246  Matrix& k_aux,
3247  const TagGroups& tgs,
3248  const Vector& f_mono,
3249  const Vector& p_abs,
3250  const Vector& t_abs,
3251  const Vector& n2_abs,
3252  const Vector& h2o_abs,
3253  const Matrix& vmrs,
3254  const ArrayOfArrayOfLineRecord& lines_per_tg,
3255  const ArrayOfLineshapeSpec& lineshape,
3256  const Vector& e_ground,
3257  const Index& emission,
3258  const ArrayOfString& cont_description_names,
3259  const ArrayOfVector& cont_description_parameters,
3260  const ArrayOfString& cont_description_models,
3261  const Los& los,
3262  const Numeric& t_ground,
3263  const Vector& y_space,
3264  const Vector& y,
3265  // Keywords
3266  const Numeric& delta,
3267  const String& f_unit )
3268 {
3269  check_if_bool( emission, "emission" );
3270  check_lengths( p_abs, "p_abs", t_abs, "t_abs" );
3271  check_lengths( p_abs, "p_abs", h2o_abs, "h2o_abs" );
3272  check_lengths( p_abs, "p_abs", n2_abs, "n2_abs" );
3273  check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
3274  //
3275  if ( any_ground(los.ground) )
3276  {
3277  if ( t_ground <= 0 )
3278  throw runtime_error(
3279  "There are intersections with the ground, but the ground\n"
3280  "temperature is set to be <=0 (are dummy values used?).");
3281  if ( e_ground.nelem() != f_mono.nelem() )
3282  throw runtime_error(
3283  "There are intersections with the ground, but the frequency and\n"
3284  "ground emission vectors have different lengths (are dummy values\n"
3285  "used?).");
3286  }
3287  if ( emission )
3288  check_lengths( f_mono, "f_mono", y_space, "y_space" );
3289 
3290 
3291  // Check frequency unit
3292  //
3293  Numeric scfac;
3294  //
3295  if ( f_unit == "Hz" )
3296  scfac = 1.0;
3297  else if ( f_unit == "kHz" )
3298  scfac = 1000;
3299  else if ( f_unit == "MHz" )
3300  scfac = 1e6;
3301  else
3302  throw runtime_error("Allowed frequency units are \"Hz\", \"kHz\" and "
3303  "\"MHz\".");
3304 
3305 
3306  // Create the disturbed f_mono
3307  //
3308  Index nv = f_mono.nelem(); // number of frequencies
3309  Numeric fdelta = scfac * delta;
3310  //
3311  Vector f_dist(nv);
3312  //
3313  for( Index ii=0; ii<nv; ii++ )
3314  { f_dist[ii] = f_mono[ii] + fdelta; }
3315 
3316 
3317  // Calculate new spectra
3318  Matrix abs;
3319  ArrayOfMatrix abs_dummy;
3320  out2 << " ----- Messages from absCalc: --------\n";
3321  absCalc( abs, abs_dummy, tgs, f_dist, p_abs, t_abs, n2_abs, h2o_abs, vmrs,
3322  lines_per_tg, lineshape, cont_description_names,
3323  cont_description_models, cont_description_parameters);
3324  ArrayOfMatrix source, trans;
3325  out2 << " ----- Messages from sourceCalc: -----\n";
3326  sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
3327  out2 << " -------------------------------------\n";
3328  out2 << " ----- Messages from transCalc: ------\n";
3329  transCalc( trans, los, p_abs, abs );
3330  out2 << " -------------------------------------\n";
3331  Vector y_new;
3332  out2 << " ----- Messages from yRte: -----------\n";
3333  yCalc( y_new, emission, los, f_mono, y_space, source, trans,
3334  e_ground, t_ground );
3335  out2 << " -------------------------------------\n";
3336 
3337  // Make k one-column matrix of the right size:
3338  nv = y.nelem();
3339  k.resize( nv, 1 );
3340 
3341  // k = (y_new - y) / delta
3342  for( Index ii=0; ii<nv; ii++ )
3343  { k(ii,0) = ( y_new[ii] - y[ii] ) / delta; }
3344 
3345  k_names.resize( 1 );
3346  k_names[0] = "Frequency: off-set";
3347  k_aux.resize( 1, 2 );
3348  k_aux = 0.0; // Matpack can set all elements like this.
3349 }
3350 
3351 
3352 
3360  Matrix& k,
3361  ArrayOfString& k_names,
3362  Matrix& k_aux,
3363  const Numeric& z_plat,
3364  const Vector& za_pencil,
3365  const Numeric& l_step,
3366  const Vector& p_abs,
3367  const Vector& z_abs,
3368  const Vector& t_abs,
3369  const Vector& f_mono,
3370  const Index& refr,
3371  const Index& refr_lfac,
3372  const Vector& refr_index,
3373  const Numeric& z_ground,
3374  const Numeric& r_geoid,
3375  const Matrix& abs,
3376  const Index& emission,
3377  const Vector& y_space,
3378  const Vector& e_ground,
3379  const Numeric& t_ground,
3380  const Vector& y,
3381  const Numeric& delta )
3382 {
3383  check_if_bool( emission, "emission" );
3384  check_if_bool( refr, "refr" );
3385  check_lengths( p_abs, "p_abs", t_abs, "t_abs" );
3386  check_lengths( p_abs, "p_abs", z_abs, "z_abs" );
3387  check_length_ncol( p_abs, "p_abs", abs, "abs" );
3388  check_length_nrow( f_mono, "f_mono", abs, "abs" );
3389  if ( emission )
3390  check_lengths( f_mono, "f_mono", y_space, "y_space" );
3391  if ( refr )
3392  check_lengths( p_abs, "p_abs", refr_index, "refr_index" );
3393 
3394 
3395  // Create new zenith angle grid
3396  // const Index nza = za_pencil.nelem();
3397  Vector za_new( za_pencil ); // Matpack can initialize a
3398  // new Vector from another
3399  // Vector.
3400  za_new += delta; // With Matpack you can add delta to all
3401  // Vector elements like this.
3402 
3403  out2 << " ----- Messages from losCalc: --------\n";
3404  Los los;
3405  Vector z_tan;
3406  losCalc( los, z_tan, z_plat, za_new, l_step, p_abs, z_abs, refr, refr_lfac,
3407  refr_index, z_ground, r_geoid );
3408  out2 << " -------------------------------------\n";
3409 
3410  ArrayOfMatrix source, trans;
3411  out2 << " ----- Messages from sourceCalc: -----\n";
3412  sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
3413  out2 << " -------------------------------------\n";
3414  out2 << " ----- Messages from transCalc: ------\n";
3415  transCalc( trans, los, p_abs, abs );
3416  out2 << " -------------------------------------\n";
3417  Vector y_new;
3418  out2 << " ----- Messages from yRte: -----------\n";
3419  yCalc( y_new, emission, los, f_mono, y_space, source, trans,
3420  e_ground, t_ground );
3421  out2 << " -------------------------------------\n";
3422 
3423  // Make k one-column matrix of the right size:
3424  const Index nv = y.nelem();
3425  k.resize( nv, 1 );
3426 
3427  // k = (y_new - y) / delta
3428  // k = (y_new - y) / delta
3429  for( Index ii=0; ii<nv; ii++ )
3430  { k(ii,0) = ( y_new[ii] - y[ii] ) / delta; }
3431  //k = y_new;
3432  //k -= y;
3433  //k /= delta;
3434 
3435  k_names.resize( 1 );
3436  k_names[0] = "Pointing: off-set";
3437  k_aux.resize( 1, 2 );
3438  k_aux = 0.0;
3439 }
3440 
3441 
3442 
3450  Matrix& k,
3451  ArrayOfString& k_names,
3452  Matrix& k_aux,
3453  const Vector& za_pencil,
3454  const Vector& f_mono,
3455  const Index& emission,
3456  const Vector& y_space,
3457  const Vector& e_ground,
3458  const Numeric& t_ground,
3459  const Los& los,
3460  const ArrayOfMatrix& source,
3461  const ArrayOfMatrix& trans,
3462  const Index& single_e )
3463 {
3464  check_if_bool( emission, "emission" );
3465  check_if_bool( emission, "single_e" );
3466  check_lengths( f_mono, "f_mono", e_ground, "e_ground" );
3467  if ( los.p.nelem() != za_pencil.nelem() )
3468  throw runtime_error(
3469  "The number of zenith angles of *za* and *los* are different.");
3470  //
3471  if ( los.p.nelem() != trans.nelem() )
3472  throw runtime_error(
3473  "The number of zenith angles of *los* and *trans* are different.");
3474  //
3475  if ( emission )
3476  {
3477  if ( los.p.nelem() != source.nelem() )
3478  throw runtime_error(
3479  "The number of zenith angles of *los* and *source* are different.");
3480  check_length_nrow( f_mono, "f_mono", source[0],
3481  "the source matrices (in source)");
3482  }
3483  //
3484  if ( any_ground(los.ground) )
3485  {
3486  if ( t_ground <= 0 )
3487  throw runtime_error(
3488  "There are intersections with the ground, but the ground\n"
3489  "temperature is set to be <=0 (are dummy values used?).");
3490  if ( e_ground.nelem() != f_mono.nelem() )
3491  throw runtime_error(
3492  "There are intersections with the ground, but the frequency and\n"
3493  "ground emission vectors have different lengths (are dummy values\n"
3494  "used?).");
3495  }
3496  //
3497  if ( single_e )
3498  {
3499  for ( INDEX iv=1; iv<f_mono.nelem(); iv++ )
3500  {
3501  if ( e_ground[iv] != e_ground[0] )
3502  throw runtime_error(
3503  "A single ground emission value is assumed, but all values of\n"
3504  "*e_ground* are not the same.");
3505  }
3506  }
3507 
3508 
3509  // Main sizes
3510  const Index nza = za_pencil.nelem(); // number of zenith angles
3511  const Index nv = f_mono.nelem(); // number of frequencies
3512 
3513  // Loop variables
3514  Index iv, iza;
3515 
3516  // Make calculations assuming a single e
3517  Vector ksingle( nza*nv );
3518 
3519  // Emission
3520  if ( emission )
3521  {
3522  // Set all values to zero (k is zero if no ground intersection)
3523  ksingle = 0.0;
3524 
3525  // Local vectors
3526  Vector bground(nv), y_in(nv), tr(nv);
3527 
3528  for ( iza=0; iza<nza; iza++ )
3529  {
3530  if ( los.ground[iza] )
3531  {
3532  // Calculate blackbody radiation of the ground
3533  planck( bground, f_mono, t_ground );
3534 
3535  // Calculate the intensity reflected by the ground
3536  rte( y_in, los.start[iza], los.ground[iza]-1, trans[iza], source[iza],
3537  y_space, 0, e_ground, bground );
3538 
3539  // Calculate transmission from the ground to the sensor
3540  tr = 1.0;
3541  bl_iterate( tr, los.ground[iza]-1, los.stop[iza]-1, trans[iza], nv );
3542 
3543  for ( iv=0; iv<nv; iv++ )
3544  ksingle[iza*nv+iv] = ( bground[iv] - y_in[iv] ) * tr[iv];
3545  }
3546  }
3547  }
3548 
3549  // Optical thicknesses
3550  else
3551  {
3552  Numeric a;
3553  for ( iv=0; iv<nv; iv++ )
3554  {
3555  a = 1 / ( 1 - e_ground[iv] );
3556  for ( iza=0; iza<nza; iza++ )
3557  ksingle[iza*nv+iv] = a;
3558  }
3559  }
3560 
3561  // A single value for the ground emission, k is a column vector
3562  if ( single_e )
3563  {
3564  k_names.resize( 1 );
3565  k_names[0] = "Ground emission (single)";
3566  //
3567  k.resize( nza*nv, 1 );
3568  k = ksingle;
3569  //
3570  k_aux.resize( 1, 2 );
3571  k_aux(0,0) = 0;
3572  k_aux(0,1) = e_ground[0];
3573  }
3574 
3575  // An e for each monochromatic frequency, k has nv columns
3576  else
3577  {
3578  k_names.resize( 1 );
3579  k_names[0] = "Ground emission";
3580  //
3581  k.resize( nza*nv, nv );
3582  k = 0.0;
3583  k_aux.resize( nv, 2 );
3584  //
3585  for ( iv=0; iv<nv; iv++ )
3586  {
3587  for ( iza=0; iza<nza; iza++ )
3588  k(iza*nv+iv,iv) = ksingle[iza*nv+iv];
3589  k_aux(iv,0) = 0;
3590  k_aux(iv,1) = e_ground[iv];
3591  }
3592  }
3593 }
3594 
3595 
3596 
3604  Matrix& k,
3605  ArrayOfString& k_names,
3606  Matrix& k_aux,
3607  const Vector& y,
3608  const Vector& f_mono,
3609  const Vector& y0,
3610  const String& /* name */ )
3611 {
3612  check_lengths( f_mono, "f_mono", y0, "y0" );
3613 
3614  const Index ny = y.nelem();
3615  const Index nf = f_mono.nelem();
3616  const Index nza = ny/nf;
3617 
3618  // Make k one-column matrix of the right size:
3619  k.resize( ny, 1 );
3620 
3621  // k = y - y0
3622  Index j,i,i0;
3623  for ( j=0; j<nza; j++ )
3624  {
3625  i0 = j*nf;
3626  for ( i=0; i<nf; i++ )
3627  k(i0+i,0) = y[i0+i] - y0[i];
3628  }
3629 
3630  k_names.resize( 1 );
3631  k_names[0] = "Calibration: scaling";
3632  k_aux.resize( 1, 2 );
3633  k_aux = 0.0;
3634 }
3635 
3636 
3637 
3648 void kManual(
3649  Matrix& k,
3650  ArrayOfString& k_names,
3651  Matrix& k_aux,
3652  const Vector& y0,
3653  const Vector& y,
3654  const String& name,
3655  const Numeric& delta,
3656  const Numeric& grid,
3657  const Numeric& apriori )
3658 {
3659  check_lengths( y, "y", y0, "y0" );
3660 
3661  // Make k one-column matrix of the right size:
3662  k.resize( y.nelem(), 1 );
3663 
3664  // Compute (y-y0)
3665  k = y;
3666  k -= y0;
3667  k /= delta;
3668 
3669  k_names.resize(1);
3670  k_names[0] = name;
3671  k_aux.resize(1,2);
3672  k_aux(0,0) = grid;
3673  k_aux(0,1) = apriori;
3674 }
3675 
3676 
3677 
3684 void kxInit (
3685  Matrix& kx,
3686  ArrayOfString& kx_names,
3687  ArrayOfIndex& kx_lengths,
3688  Matrix& kx_aux )
3689 {
3690  kx.resize( 0, 0 );
3691  kx_names.resize( 0 );
3692  kx_lengths.resize( 0 );
3693  kx_aux.resize( 0, 0 );
3694 }
3695 
3696 
3697 
3704 void kbInit (
3705  Matrix& kb,
3706  ArrayOfString& kb_names,
3707  ArrayOfIndex& kb_lengths,
3708  Matrix& kb_aux )
3709 {
3710  kxInit( kb, kb_names, kb_lengths, kb_aux );
3711 }
3712 
3713 
3714 
3721 void kxAppend (
3722  Matrix& kx,
3723  ArrayOfString& kx_names,
3724  ArrayOfIndex& kx_lengths,
3725  Matrix& kx_aux,
3726  const Matrix& k,
3727  const ArrayOfString& k_names,
3728  const Matrix& k_aux )
3729 {
3730  k_append( kx, kx_names, kx_lengths, kx_aux, k, k_names, k_aux );
3731 }
3732 
3733 
3734 
3741 void kbAppend (
3742  Matrix& kb,
3743  ArrayOfString& kb_names,
3744  ArrayOfIndex& kb_lengths,
3745  Matrix& kb_aux,
3746  const Matrix& k,
3747  const ArrayOfString& k_names,
3748  const Matrix& k_aux )
3749 {
3750  k_append( kb, kb_names, kb_lengths, kb_aux, k, k_names, k_aux );
3751 }
3752 
3753 
3754 
3762  Matrix& kx,
3763  ArrayOfString& kx_names,
3764  ArrayOfIndex& kx_lengths,
3765  Matrix& kx_aux,
3766  const Vector& y,
3767  const String& /* y_name */,
3768  const Index& ni,
3769  const Index& nx )
3770 {
3771  const Index ny = y.nelem();
3772 
3773  out2 << " Allocates memory for a weighting function matrix having:\n"
3774  << " " << ny << " frequency points\n"
3775  << " " << nx << " state variables\n"
3776  << " " << ni << " retrieval identities\n";
3777 
3778  kx.resize( ny, nx );
3779  kx_names.resize( ni );
3780  kx_lengths.resize( ni );
3781  kx_aux.resize( nx, 2 );
3782 
3783  for ( Index i=0; i<ni; i++ )
3784  kx_lengths[i] = 0;
3785 }
3786 
3787 
3788 
3796  Matrix& kb,
3797  ArrayOfString& kb_names,
3798  ArrayOfIndex& kb_lengths,
3799  Matrix& kb_aux,
3800  const Vector& y,
3801  const String& y_name,
3802  const Index& ni,
3803  const Index& nx )
3804 {
3805  kxAllocate( kb, kb_names, kb_lengths, kb_aux, y, y_name, ni, nx );
3806 }
3807 
3808 
3809 
3816 void kxPutInK (
3817  Matrix& kx,
3818  ArrayOfString& kx_names,
3819  ArrayOfIndex& kx_lengths,
3820  Matrix& kx_aux,
3821  const Matrix& k,
3822  const ArrayOfString& k_names,
3823  const Matrix& k_aux )
3824 {
3825  const Index ny = kx.nrows();
3826  const Index nx = kx.ncols();
3827  const Index ni = kx_names.nelem();
3828  const Index nx2 = k.ncols();
3829  const Index ni2 = k_names.nelem();
3830 
3831  if ( ny != k.nrows() )
3832  throw runtime_error("The two WF matrices have different number of rows.");
3833 
3834  // Determine old length of x and number of identities
3835  Index ni1, nx1=0;
3836  for( ni1=0; ni1<ni && kx_lengths[ni1]>0; ni1++ )
3837  nx1 += kx_lengths[ni1];
3838  if ( ni1 == ni )
3839  throw runtime_error("All retrieval/error identity positions used.");
3840 
3841  // Check if new data fit
3842  if ( (ni1+ni2) > ni )
3843  {
3844  ostringstream os;
3845  os << "There is not room for so many retrieval/error identities.\n"
3846  << (ni1+ni2)-ni << " positions are missing";
3847  throw runtime_error(os.str());
3848  }
3849  if ( (nx1+nx2) > nx )
3850  {
3851  ostringstream os;
3852  os << "The k-matrix does not fit in kx.\n"
3853  << (nx1+nx2)-nx << " columns are missing";
3854  throw runtime_error(os.str());
3855  }
3856 
3857  out2 << " Putting k in kx as\n"
3858  << " identity " << ni1 << " - " << ni1+ni2-1 << "\n"
3859  << " column " << nx1 << " - " << nx1+nx2-1 << "\n";
3860 
3861  // Calculate the vector length for each identity in K
3862  Index l = nx2/ni2;
3863 
3864  // Move K to Kx
3865  kx( Range(joker), Range(nx1,nx2) ) = k;
3866  kx_aux( Range(nx1,nx2), Range(joker) ) = k_aux;
3867  // For the Array types kx_names and kx_lenghts we cannot use Range.
3868  for ( Index iri=0; iri<ni2; iri++ )
3869  {
3870  kx_names[ni1+iri] = k_names[iri];
3871  kx_lengths[ni1+iri] = l;
3872  }
3873 }
3874 
3875 
3876 
3883 void kbPutInK (
3884  Matrix& kb,
3885  ArrayOfString& kb_names,
3886  ArrayOfIndex& kb_lengths,
3887  Matrix& kb_aux,
3888  const Matrix& k,
3889  const ArrayOfString& k_names,
3890  const Matrix& k_aux )
3891 {
3892  kxPutInK( kb, kb_names, kb_lengths, kb_aux, k, k_names, k_aux );
3893 }
absloswfs_rte
void absloswfs_rte(ArrayOfMatrix &absloswfs, const Los &los, const ArrayOfMatrix &source, const ArrayOfMatrix &trans, const Vector &y, const Vector &y_space, const Vector &f_mono, const Vector &e_ground, const Numeric &t_ground)
Definition: m_wfs.cc:761
Matrix
The Matrix class.
Definition: matpackI.h:544
sourceloswfs_limb
void sourceloswfs_limb(Matrix &k, const Index &start_index, const Matrix &tr, const Index &ground, const Vector &e_ground)
Calculates source function LOS WFs for 1D limb sounding.
Definition: m_wfs.cc:1020
out2
Out2 out2
Level 2 output stream.
Definition: messages.cc:54
transform
void transform(VectorView y, double(&my_func)(double), ConstVectorView x)
A generic transform function for vectors, which can be used to implement mathematical functions opera...
Definition: matpackI.h:2405
yCalc
void yCalc(Vector &, const Index &, const Los &, const Vector &, const Vector &, const ArrayOfMatrix &, const ArrayOfMatrix &, const Vector &, const Numeric &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_los.cc:1483
any_ground
bool any_ground(const ArrayOfIndex &ground)
Checks if any of the pencil beam spectra corresponds to a ground reflection.
Definition: m_los.cc:86
kxAppend
void kxAppend(Matrix &kx, ArrayOfString &kx_names, ArrayOfIndex &kx_lengths, Matrix &kx_aux, const Matrix &k, const ArrayOfString &k_names, const Matrix &k_aux)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3721
auto_md.h
k_contabs
void k_contabs(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Los &los, const ArrayOfMatrix &absloswfs, const Vector &f_mono, const Vector &k_grid, const Index &order, const Numeric &flow, const Numeric &fhigh, const String &lunit)
WFs for fit of continuum absorption.
Definition: m_wfs.cc:1465
refrCalc
void refrCalc(Vector &, const Vector &, const Vector &, const Vector &, const Index &, const String &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:2763
atm_funcs.h
This file contains declerations of functions releated to atmospheric physics or geometry.
absloswfs_rte_1pass
void absloswfs_rte_1pass(Matrix &k, Vector y, const Index &start_index, const Index &stop_index, const Numeric &lstep, const Matrix &tr, const Matrix &s, const Index &ground, const Vector &e_ground, const Vector &y_ground)
Calculates absorption LOS WFs f single pass cases.
Definition: m_wfs.cc:484
check_length_ncol
void check_length_ncol(const Vector &x, const String &x_name, const Matrix &A, const String &A_name)
Checkss that the length of a vector and the number of columns of a matrix match.
Definition: math_funcs.cc:592
transpose
ConstMatrixView transpose(ConstMatrixView m)
Const version of transpose.
Definition: matpackI.h:2373
los.h
This file contains the definition of the LOS structure and functions related to this structure.
last
Numeric last(ConstVectorView x)
Gives the last value of a vector.
Definition: math_funcs.cc:83
kxInit
void kxInit(Matrix &kx, ArrayOfString &kx_names, ArrayOfIndex &kx_lengths, Matrix &kx_aux)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3684
first
Numeric first(ConstVectorView x)
Gives the first value of a vector.
Definition: math_funcs.cc:70
k_temp_nohydro
void k_temp_nohydro(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const TagGroups &tag_groups, const Los &los, const ArrayOfMatrix &absloswfs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &n2_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const Matrix &abs, const ArrayOfMatrix &trans, const Vector &e_ground, const Vector &k_grid, const ArrayOfString &cont_description_names, const ArrayOfVector &cont_description_parameters, const ArrayOfString &cont_description_models)
Temparature WFs without hydrostatic eq.
Definition: m_wfs.cc:1701
grid2grid_weights_total
void grid2grid_weights_total(ArrayOfMatrix &W, const Los &los, const Vector &k_grid)
Gives weights for conversion between vertical grids.
Definition: m_wfs.cc:395
kManual
void kManual(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Vector &y0, const Vector &y, const String &name, const Numeric &delta, const Numeric &grid, const Numeric &apriori)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3648
check_lengths
void check_lengths(const Vector &x1, const String &x1_name, const Vector &x2, const String &x2_name)
Checks that two vectors have the same length.
Definition: math_funcs.cc:527
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.h:1467
dabs
#define dabs(x)
Definition: continua.cc:12947
transCalc
void transCalc(ArrayOfMatrix &, const Los &, const Vector &, const Matrix &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_los.cc:1390
kFrequencyOffSet
void kFrequencyOffSet(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &n2_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const Vector &e_ground, const Index &emission, const ArrayOfString &cont_description_names, const ArrayOfVector &cont_description_parameters, const ArrayOfString &cont_description_models, const Los &los, const Numeric &t_ground, const Vector &y_space, const Vector &y, const Numeric &delta, const String &f_unit)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3243
OneTag::Species
Index Species() const
Molecular species index.
Definition: absorption.h:1083
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.h:1491
p2grid
void p2grid(Vector &grid, const Vector &pgrid)
Converts a pressure grid to a grid fitting the grid functions below.
Definition: m_wfs.cc:167
get_tag_group_index_for_tag_group
void get_tag_group_index_for_tag_group(Index &tgs1_index, const TagGroups &tgs1, const Array< OneTag > &tg2)
Returns the index of the tag group tg2 within the array of tag groups tgs1.
Definition: absorption.cc:2233
wfs_tgsDefine
void wfs_tgsDefine(TagGroups &wfs_tag_groups, const ArrayOfString &tags)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2574
number_density
Numeric number_density(Numeric p, Numeric t)
Calculates the number density (scalar version).
Definition: atm_funcs.cc:270
joker
Joker joker
Define the global joker objekt.
Definition: constants.cc:233
mult
void mult(VectorView y, const ConstMatrixView &M, const ConstVectorView &x)
Matrix Vector multiplication.
Definition: matpackI.h:2291
q
#define q
Definition: continua.cc:13955
rte_iterate
void rte_iterate(VectorView y, const Index start_index, const Index stop_index, ConstMatrixView tr, ConstMatrixView s, const Index n_f)
Performs a single iteration for RTE calculations (one zenith angle).
Definition: atm_funcs.cc:386
sourceCalc
void sourceCalc(ArrayOfMatrix &, const Index &, const Los &, const Vector &, const Vector &, const Vector &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_los.cc:1321
bl
void bl(Vector &y, const Index start_index, const Index stop_index, ConstMatrixView tr, const Index ground, ConstVectorView e_ground)
Performs the BL (transmission) calculations for one zenith angle.
Definition: atm_funcs.cc:560
matpackI.h
Array< String >
sourceloswfs_down
void sourceloswfs_down(Matrix &k, const Index &start_index, const Index &stop_index, const Matrix &tr, const Index &ground, const Vector &e_ground)
Calculates source function LOS WFs for 1D downward looking observations.
Definition: m_wfs.cc:1085
kTemp
void kTemp(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &n2_abs, const Vector &h2o_abs, const Matrix &vmrs, const Matrix &abs0, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const Vector &e_ground, const Index &emission, const Vector &k_grid, const ArrayOfString &cont_description_names, const ArrayOfVector &cont_description_parameters, const ArrayOfString &cont_description_models, const Los &los, const ArrayOfMatrix &absloswfs, const ArrayOfMatrix &trans, const Numeric &z_plat, const Vector &za, const Numeric &l_step, const Vector &z_abs, const Index &refr, const Index &refr_lfac, const Vector &refr_index, const String &refr_model, const Numeric &z_ground, const Numeric &t_ground, const Vector &y_space, const Numeric &r_geoid, const Vector &hse, const Index &kw_hse, const Index &kw_fast)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2881
check_if_bool
void check_if_bool(const Index &x, const String &x_name)
Checks if an integer is 0 or 1.
Definition: math_funcs.cc:468
absloswfs_rte_limb
void absloswfs_rte_limb(Matrix &k, Vector y, const Vector &y_space, const Index &start_index, const Numeric &lstep, const Matrix &tr, const Matrix &s, const Index &ground, const Vector &e_ground)
Calculates absorption LOS WFs for 1D limb sounding.
Definition: m_wfs.cc:586
bl_iterate
void bl_iterate(VectorView y, const Index start_index, const Index stop_index, ConstMatrixView tr, const Index n_f)
Performs a single iteration for BL calculations (one zenith angle).
Definition: atm_funcs.cc:518
messages.h
Declarations having to do with the four output streams.
planck
void planck(MatrixView B, ConstVectorView f, ConstVectorView t)
Calculates a blackbody radiation (the Planck function) matrix.
Definition: atm_funcs.cc:75
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.h:1497
TORR2PA
const Numeric TORR2PA
Global constant, converts torr to Pa.
my_basic_string< char >
absCalc
void absCalc(Matrix &, ArrayOfMatrix &, const TagGroups &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Matrix &, const ArrayOfArrayOfLineRecord &, const ArrayOfLineshapeSpec &, const ArrayOfString &, const ArrayOfString &, const ArrayOfVector &)
Calculates the absorption coefficients by first calculating the cross sections per tag group and then...
Definition: m_abs.cc:1956
abs
#define abs(x)
Definition: continua.cc:12946
kbInit
void kbInit(Matrix &kb, ArrayOfString &kb_names, ArrayOfIndex &kb_lengths, Matrix &kb_aux)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3704
out1
Out1 out1
Level 1 output stream.
Definition: messages.cc:52
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: arts.h:147
TagGroups
Array< Array< OneTag > > TagGroups
Contains the available tag groups.
Definition: absorption.h:1126
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.h:937
Los::p
ArrayOfVector p
Definition: los.h:104
grid2grid_index
void grid2grid_index(Matrix &is, const Vector &x0, const Vector &xp)
Gives indecies for conversion between vertical grids.
Definition: m_wfs.cc:239
kSpecies
void kSpecies(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Los &los, const ArrayOfMatrix &absloswfs, const Vector &p_abs, const Vector &t_abs, const TagGroups &wfs_tgs, const ArrayOfMatrix &abs_per_tg, const Matrix &vmrs, const Vector &k_grid, const String &unit)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2778
math_funcs.h
Contains declerations of basic mathematical and vector/matrix functions.
check_length_nrow
void check_length_nrow(const Vector &x, const String &x_name, const Matrix &A, const String &A_name)
Checks that the length of a vector and the number of rows of a matrix match.
Definition: math_funcs.cc:559
hseCalc
void hseCalc(Vector &, const Vector &, const Vector &, const Vector &, const Numeric &, const Vector &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1717
kbAppend
void kbAppend(Matrix &kb, ArrayOfString &kb_names, ArrayOfIndex &kb_lengths, Matrix &kb_aux, const Matrix &k, const ArrayOfString &k_names, const Matrix &k_aux)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3741
Matrix::resize
void resize(Index r, Index c)
Resize function.
Definition: matpackI.h:2237
kbPutInK
void kbPutInK(Matrix &kb, ArrayOfString &kb_names, ArrayOfIndex &kb_lengths, Matrix &kb_aux, const Matrix &k, const ArrayOfString &k_names, const Matrix &k_aux)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3883
losCalc
void losCalc(Los &, Vector &, const Numeric &, const Vector &, const Numeric &, const Vector &, const Vector &, const Index &, const Index &, const Vector &, const Numeric &, const Numeric &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_los.cc:1058
Los::stop
ArrayOfIndex stop
Definition: los.h:110
grid2grid_weights
void grid2grid_weights(Vector &w, const Vector &x0, const Index &i1, const Index &i2, const Vector &xp, const Index &ip)
Gives weights for conversion between vertical grids.
Definition: m_wfs.cc:335
nlinspace
void nlinspace(Vector &x, const Numeric start, const Numeric stop, const Index n)
Linearly spaced vector with specified length.
Definition: math_funcs.cc:168
BOLTZMAN_CONST
const Numeric BOLTZMAN_CONST
OneTag
A tag group can consist of the sum of several of these.
Definition: absorption.h:1061
kSpeciesSingle
void kSpeciesSingle(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Los &los, const ArrayOfMatrix &absloswfs, const Vector &p_abs, const Vector &t_abs, const TagGroups &wfs_tgs, const ArrayOfMatrix &abs_per_tg, const Matrix &vmrs, const Vector &k_grid, const String &tg, const String &unit)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2812
Range
The range class.
Definition: matpackI.h:139
xsec_per_tgInit
void xsec_per_tgInit(ArrayOfMatrix &, const TagGroups &, const Vector &, const Vector &)
Initialize xsec_per_tg.
Definition: m_abs.cc:2231
out3
Out3 out3
Level 3 output stream.
Definition: messages.cc:56
Los::start
ArrayOfIndex start
Definition: los.h:109
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: arts.h:153
kxPutInK
void kxPutInK(Matrix &kx, ArrayOfString &kx_names, ArrayOfIndex &kx_lengths, Matrix &kx_aux, const Matrix &k, const ArrayOfString &k_names, const Matrix &k_aux)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3816
kEground
void kEground(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Vector &za_pencil, const Vector &f_mono, const Index &emission, const Vector &y_space, const Vector &e_ground, const Numeric &t_ground, const Los &los, const ArrayOfMatrix &source, const ArrayOfMatrix &trans, const Index &single_e)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3449
wfss_tgsDefine
void wfss_tgsDefine(TagGroups &wfss_tgs, const ArrayOfString &tags)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2650
xsec_per_tgAddLines
void xsec_per_tgAddLines(ArrayOfMatrix &, const TagGroups &, const Vector &, const Vector &, const Vector &, const Vector &, const Matrix &, const ArrayOfArrayOfLineRecord &, const ArrayOfLineshapeSpec &)
Calculates the line spectrum for each tag group and adds it to xsec_per_tg.
Definition: m_abs.cc:2274
absloswfsCalc
void absloswfsCalc(ArrayOfMatrix &absloswfs, const Index &emission, const Los &los, const ArrayOfMatrix &source, const ArrayOfMatrix &trans, const Vector &y, const Vector &y_space, const Vector &f_mono, const Vector &e_ground, const Numeric &t_ground)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2726
k_append
void k_append(Matrix &kx, ArrayOfString &kx_names, ArrayOfIndex &kx_lengths, Matrix &kx_aux, const Matrix &k, const ArrayOfString &k_names, const Matrix &k_aux)
Appends the K matrix to either Kx or Kb.
Definition: m_wfs.cc:79
absloswfs_tau
void absloswfs_tau(ArrayOfMatrix &absloswfs, const Los &los, const Vector &f_mono)
Definition: m_wfs.cc:834
Los::l_step
Vector l_step
Definition: los.h:107
kPointingOffSet
void kPointingOffSet(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Numeric &z_plat, const Vector &za_pencil, const Numeric &l_step, const Vector &p_abs, const Vector &z_abs, const Vector &t_abs, const Vector &f_mono, const Index &refr, const Index &refr_lfac, const Vector &refr_index, const Numeric &z_ground, const Numeric &r_geoid, const Matrix &abs, const Index &emission, const Vector &y_space, const Vector &e_ground, const Numeric &t_ground, const Vector &y, const Numeric &delta)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3359
interpp
void interpp(VectorView x, ConstVectorView p0, ConstVectorView x0, ConstVectorView p)
Interpolates a vertical profile at a new set of pressures.
Definition: atm_funcs.cc:658
get_tagindex_for_Strings
void get_tagindex_for_Strings(ArrayOfIndex &tags1_index, const TagGroups &tags1, const ArrayOfString &tags2_Strings)
Returns the index among some tag groups for an array of tag Strings.
Definition: absorption.cc:2176
kCalibration
void kCalibration(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Vector &y, const Vector &f_mono, const Vector &y0, const String &)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3603
k_species
void k_species(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Los &los, const ArrayOfMatrix &absloswfs, const Vector &p_abs, const Vector &t_abs, const TagGroups &tags, const ArrayOfMatrix &abs_per_tg, const Matrix &vmrs, const Vector &k_grid, const ArrayOfIndex &tg_nr, const String &unit)
Species WFs for one or several species.
Definition: m_wfs.cc:1244
kbAllocate
void kbAllocate(Matrix &kb, ArrayOfString &kb_names, ArrayOfIndex &kb_lengths, Matrix &kb_aux, const Vector &y, const String &y_name, const Index &ni, const Index &nx)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3795
sourceloswfs
void sourceloswfs(ArrayOfMatrix &sourceloswfs, const Los &los, const ArrayOfMatrix &trans, const Vector &, const Vector &e_ground)
Calculates source function LOS WFs,.
Definition: m_wfs.cc:1154
my_basic_string::npos
static const Index npos
Define npos:
Definition: mystring.h:87
kSpectro
void kSpectro(Matrix &k, ArrayOfString &k_names, Matrix &, Matrix &S_S, const TagGroups &wfss_tgs, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &z_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const Los &los, const ArrayOfMatrix &absloswfs, const Index &kw_intens, const Index &kw_position, const Index &kw_agam, const Index &kw_sgam, const Index &kw_nair, const Index &kw_nself, const Index &kw_pSift)
Spectroscopic parameters weighting function.
Definition: m_wfs.cc:2268
Vector
The Vector class.
Definition: matpackI.h:389
Los::ground
ArrayOfIndex ground
Definition: los.h:108
kContAbs
void kContAbs(Matrix &k, ArrayOfString &k_names, Matrix &k_aux, const Los &los, const ArrayOfMatrix &absloswfs, const Vector &f_mono, const Vector &k_grid, const Index &order, const Numeric &f_low, const Numeric &f_high, const String &l_unit)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:2847
Los
The line of sight (LOS).
Definition: los.h:103
absloswfs_rte_down
void absloswfs_rte_down(Matrix &k, const Vector &y, const Vector &y_space, const Index &start_index, const Index &stop_index, const Numeric &lstep, const Matrix &tr, const Matrix &s, const Index &ground, const Vector &e_ground, const Vector &y_ground)
Calculates absorption LOS WFs for 1D downward looking observations.
Definition: m_wfs.cc:682
absCalcFromXsec
void absCalcFromXsec(Matrix &, ArrayOfMatrix &, const ArrayOfMatrix &, const Matrix &)
Calculates the absorption from a given cross section.
Definition: m_abs.cc:2152
kxAllocate
void kxAllocate(Matrix &kx, ArrayOfString &kx_names, ArrayOfIndex &kx_lengths, Matrix &kx_aux, const Vector &y, const String &, const Index &ni, const Index &nx)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_wfs.cc:3761
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:115
auto_wsv.h
Declares the enum type that acts as a handle for workspace variables. Also declares the workspace its...
kb_spectro
void kb_spectro(Matrix &kb, ArrayOfString &kb_names, Matrix &, Matrix &S_S, const TagGroups &wfss_tgs, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const Los &los, const ArrayOfMatrix &absweight, const Index &IndexPar, const String &StrPar)
Spectroscopic parameters weighting function.
Definition: m_wfs.cc:1919
arts.h
The global header file for ARTS.
rte
void rte(VectorView y, const Index start_index, const Index stop_index, ConstMatrixView tr, ConstMatrixView s, ConstVectorView y_space, const Index ground, ConstVectorView e_ground, ConstVectorView y_ground)
Performs the RTE calculations for one zenith angle.
Definition: atm_funcs.cc:433
sourceloswfs_1pass
void sourceloswfs_1pass(Matrix &k, const Index &start_index, const Index &stop_index, const Matrix &tr, const Index &ground, const Vector &e_ground)
Calculates source function LOS WFs for single pass cases.
Definition: m_wfs.cc:940
PLANCK_CONST
const Numeric PLANCK_CONST