00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00020 
00022 
00036 
00037 
00039 
00040 #ifdef SUNOS
00041 # include <ieeefp.h>
00042 #endif
00043 
00044 #include <math.h>
00045 #include "arts.h"
00046 #include "auto_md.h"
00047 #include "matpackI.h"
00048 #include "messages.h"          
00049 #include "auto_wsv.h"          
00050 #include "math_funcs.h"          
00051 #include "atm_funcs.h"          
00052 #include "los.h"
00053 extern const Numeric PLANCK_CONST;
00054 extern const Numeric BOLTZMAN_CONST;
00055 
00056 
00057 
00059 
00061 
00063 
00079 void k_append (
00080                     Matrix&          kx,
00081                     ArrayOfString&   kx_names,
00082                     ArrayOfIndex&    kx_lengths,
00083                     Matrix&          kx_aux,
00084               const Matrix&          k,
00085               const ArrayOfString&   k_names,
00086               const Matrix&          k_aux )
00087 {
00088   
00089   const Index  ny1  = kx.nrows();         
00090   const Index  nx1  = kx.ncols();         
00091   const Index  nri1 = kx_names.nelem();    
00092   const Index  ny2  = k.nrows();  
00093   const Index  nx2  = k.ncols();  
00094   const Index  nri2 = k_names.nelem();
00095   Index        iri;
00096 
00097   
00098   Matrix          ktemp(kx);
00099   ArrayOfString   ktemp_names(kx_names);
00100   ArrayOfIndex    ktemp_lengths(kx_lengths);
00101   Matrix          ktemp_aux(kx_aux);
00102   
00103 
00104 
00105 
00106 
00107 
00108   if ( nx1 > 0 )
00109   {
00110     if ( ny1 != ny2 )
00111       throw runtime_error(
00112             "The two WF matrices have different number of rows." ); 
00113   }
00114 
00115   
00116   kx.resize(         ny2,       nx1+nx2 );
00117   kx_names.resize(   nri1+nri2          );
00118   kx_lengths.resize( nri1+nri2          );
00119   kx_aux.resize(     nx1+nx2,   2       );
00120 
00121   
00122   if ( nx1 > 0 )
00123   {
00124     kx( Range(joker), Range(0,nx1) )     = ktemp;
00125     kx_aux( Range(0,nx1), Range(joker) ) = ktemp_aux;
00126     
00127     for ( iri=0; iri<nri1; iri++ )
00128     {
00129       kx_lengths[iri]  = ktemp_lengths[iri];
00130       kx_names[iri]    = ktemp_names[iri];
00131     }
00132   }
00133 
00134   
00135   Index l = nx2/nri2;
00136 
00137   
00138   kx( Range(joker), Range(nx1,nx2) )     = k;
00139   kx_aux( Range(nx1,nx2), Range(joker) ) = k_aux;
00140   
00141   for ( iri=0; iri<nri2; iri++ )
00142   {
00143     kx_names[nri1+iri]   = k_names[iri];
00144     kx_lengths[nri1+iri] = l;
00145   } 
00146 }
00147 
00148 
00149 
00151 
00153 
00155 
00167 void p2grid(
00168               Vector&   grid,
00169         const Vector&   pgrid )
00170 {
00171   grid.resize( pgrid.nelem() );
00172   grid = pgrid;                 
00173                                 
00174                                 
00175   transform( grid, log, grid ); 
00176                                 
00177                                 
00178                                 
00179   grid *= -1;                   
00180 }
00181 
00182 
00183 
00185 
00239 void grid2grid_index (
00240                     Matrix&   is,
00241               const Vector&   x0,
00242               const Vector&   xp )
00243 {
00244   const Index n0 = x0.nelem();        
00245   const Index np = xp.nelem();        
00246   Index       i0, ip;                
00247 
00248   
00249   is.resize( np, 2 );
00250   is = -1.0;                    
00251  
00252   
00253   if ( np < 2 )
00254     throw logic_error("The retrieval grid must have a length > 1.");
00255   for ( i0=1; i0<n0; i0++ )
00256   {
00257     if ( x0[i0-1] >= x0[i0] )
00258       throw logic_error("The grids must be sorted with increasing values.");
00259   }
00260   for ( ip=1; ip<np; ip++ )
00261   {
00262     if ( xp[ip-1] >= xp[ip] )
00263       throw logic_error("The grids must be sorted with increasing values.");
00264   }
00265 
00266   
00267   if ( !( (x0[0]>xp[np-1]) || (x0[n0-1]<xp[0]) ) )
00268   {
00269 
00270     
00271     i0 = 0;
00272     for ( ; x0[i0] < xp[0]; i0++ ) {}
00273     if ( x0[i0] < xp[1] )
00274     {
00275       is(0,0) = (Numeric) i0;
00276       for ( ; (i0<n0) && (x0[i0]<xp[1]); i0++ ) {}
00277       is(0,1) = (Numeric) (i0 - 1);
00278     }
00279 
00280     
00281     for ( ip=1; ip<(np-1); ip++ )
00282     {
00283       i0 = 0;
00284       for ( ; (i0<n0) && (x0[i0]<=xp[ip-1]); i0++ ) {}
00285       if ( (i0<n0) && (x0[i0]<xp[ip+1]) )
00286       {
00287         is(ip,0) = (Numeric) i0;
00288         for ( ; (i0<n0) && (x0[i0]<xp[ip+1]); i0++ ) {}
00289         is(ip,1) = (Numeric) (i0 - 1);
00290       }
00291     }
00292 
00293     
00294     i0 = 0;
00295     for ( ; (i0<n0) && (x0[i0]<=xp[np-2]); i0++ ) {}
00296     if ( (i0<n0) && (x0[i0]<=xp[np-1]) )
00297     {
00298       is(np-1,0) = (Numeric) i0;
00299       for ( ; (i0<n0) && (x0[i0]<=xp[np-1]); i0++ ) {}
00300       is(np-1,1) = (Numeric) (i0 - 1);
00301     }
00302   }
00303 }
00304 
00305 
00306 
00308 
00335 void grid2grid_weights (
00336                     Vector&   w,
00337               const Vector&   x0,
00338               const Index&   i1,
00339               const Index&   i2,
00340               const Vector&   xp,
00341               const Index&   ip )
00342 {
00343   const Index   np = xp.nelem();        
00344   const Index   nw = i2-i1+1;          
00345   Index         i;
00346 
00347   
00348   w.resize(nw);
00349 
00350   
00351   if ( ip == 0 )
00352   {
00353     for ( i=0; i<nw; i++ )
00354       w[i] = ( xp[1] - x0[i1+i] ) / ( xp[1] - xp[0] );
00355   }
00356   
00357   else if ( ip < (np-1) )  
00358   {
00359     for ( i=0; i<nw; i++ )
00360     {
00361       if ( x0[i1+i] <= xp[ip] )
00362         w[i] = ( x0[i1+i] - xp[ip-1] ) / ( xp[ip] - xp[ip-1] );
00363       else
00364         w[i] = ( xp[ip+1] - x0[i1+i] ) / ( xp[ip+1] - xp[ip] );
00365     }
00366   }
00367   
00368   else
00369   {
00370     for ( i=0; i<nw; i++ )
00371       w[i] = ( x0[i1+i] - xp[np-2] ) / ( xp [np-1] - xp[np-2] );
00372   }
00373 }
00374 
00376 
00395 void grid2grid_weights_total (
00396                           ArrayOfMatrix&     W,
00397                     const  Los&               los, 
00398                     const  Vector&            k_grid) 
00399          
00400 {
00401   
00402   const Index  nza = los.start.nelem();     
00403   const Index  np  = k_grid.nelem();        
00404   
00405   
00406   
00407   Vector  lgrid;
00408   p2grid( lgrid, k_grid );
00409   Vector  lplos;    
00410   Vector w1;
00411   W.resize(nza);
00412   
00413   
00414   Index  iza;                       
00415   Index  ip;                        
00416   Matrix is;                       
00417 
00418   for ( iza=0; iza<nza; iza++ ) 
00419     {
00420       W[iza].resize(los.p[iza].nelem(), np);
00421       W[iza]=0.0;
00422       if ( (iza%20)==0 )
00423         {
00424           out3 << "\n      ";
00425           out3 << " " << iza; cout.flush();
00426         }
00427       w1=0;
00428       
00429       if ( los.p[iza].nelem() > 0 )
00430         {
00431           
00432           
00433           p2grid( lplos, los.p[iza] );
00434           grid2grid_index (is, lplos, lgrid);
00435           
00436           for ( ip=0; ip<np; ip++ ) 
00437             {
00438               
00439               
00440               if ( is(ip,0) >= 0 )
00441                 {
00442                   
00443                   grid2grid_weights( w1, lplos, (Index)is(ip,0),  (Index)is(ip,1),
00444                                      lgrid, ip );
00445                   
00446 
00447                   W[iza](Range((Index)is(ip,0),(Index)(is(ip,1)-is(ip,0)+1)), ip)=w1;
00448                 }
00449             }
00450         }
00451     }
00452 }
00453 
00455 
00457 
00459 
00484 void absloswfs_rte_1pass (
00485                     Matrix&   k,
00486                     Vector    y,
00487               const Index&   start_index,
00488               const Index&   stop_index,   
00489               const Numeric&  lstep,        
00490               const Matrix&   tr,
00491               const Matrix&   s,
00492               const Index&    ground,
00493               const Vector&   e_ground,
00494               const Vector&   y_ground )
00495 {
00496   const Index   nf = tr.nrows();     
00497   Index         iv;                  
00498   Index         q;                   
00499   Vector        t(nf);               
00500   
00501   t = 1.0;              
00502 
00503   if ( ground && ((ground-1==stop_index) || (ground-1==start_index)) )
00504     throw logic_error("The ground cannot be at one of the end points."); 
00505 
00506   
00507   k.resize( nf, start_index+1 );
00508 
00509   
00510   
00511 
00512   
00513   q  = stop_index;
00514   for ( iv=0; iv<nf; iv++ )    
00515   {
00516     t[iv]   *= tr(iv,q);
00517     y[iv]    = (y[iv]-s(iv,q)*(1.0-tr(iv,q)))/tr(iv,q);
00518     k(iv,q) = (-lstep/2)*(y[iv]-s(iv,q))*t[iv];
00519   }
00520 
00521   
00522   for ( q=stop_index+1; q<start_index; q++ )
00523   {
00524     
00525     if ( q != (ground-1) )
00526     {
00527       for ( iv=0; iv<nf; iv++ )    
00528       {
00529         y[iv]    = (y[iv]-s(iv,q)*(1.0-tr(iv,q)))/tr(iv,q);
00530         k(iv,q) = (-lstep/2)*( 2*(y[iv]-s(iv,q))*tr(iv,q) + 
00531                                              s(iv,q) - s(iv,q-1) ) *t[iv];
00532         t[iv]   *= tr(iv,q); 
00533       }
00534     }
00535     
00536     else
00537     {
00538       out1 << "WARNING: The function absloswfs_1pass not tested for "
00539               "ground reflections\n";
00540       for ( iv=0; iv<nf; iv++ )    
00541       {
00542         y[iv]    = ( y[iv] - e_ground[iv]*y_ground[iv] - 
00543                             s(iv,q)*(1.0-tr(iv,q))*(1-e_ground[iv]) ) / 
00544                                              ( tr(iv,q) * (1-e_ground[iv]) );
00545         k(iv,q) = (-lstep/2)*( 2*(y[iv]-s(iv,q))*tr(iv,q)*(1-e_ground[iv])+ 
00546                                 s(iv,q)*(1-e_ground[iv]) + 
00547                              e_ground[iv]*y_ground[iv] - s(iv,q-1) ) * t[iv];
00548         t[iv]   *= tr(iv,q) * (1-e_ground[iv]); 
00549       }
00550     }
00551   }
00552 
00553   
00554   q = start_index;
00555   for ( iv=0; iv<nf; iv++ )    
00556     k(iv,q)  = (-lstep/2)*(y[iv]-s(iv,q-1))*t[iv];
00557 
00558   
00559   
00560 }
00561 
00562 
00563 
00565 
00586 void absloswfs_rte_limb (
00587                     Matrix&   k,
00588                     Vector    y,              
00589               const Vector&   y_space,             
00590               const Index&   start_index,
00591               const Numeric&  lstep,
00592               const Matrix&   tr,
00593               const Matrix&   s,
00594               const Index&    ground,
00595               const Vector&   e_ground )
00596 {
00597   const Index nf = tr.nrows();     
00598   Index       iv;                  
00599   Vector      t1q;                 
00600   Vector      tqn(nf,1.0);         
00601   Index       q;                   
00602   Numeric     tv, tv1 = 0.;             
00603   Vector      yn(y_space);         
00604 
00605   
00606   
00607 
00608   
00609   k.resize( nf, start_index+1 );
00610 
00611   
00612   bl( t1q, start_index, start_index, tr, ground, e_ground );
00613 
00614   
00615   q  = start_index;       
00616   for ( iv=0; iv<nf; iv++ )    
00617   {
00618     tv1      = tr(iv,q-1);
00619     t1q[iv] /= tv1*tv1;
00620     tqn[iv] *= tv1;
00621     y[iv]    = ( y[iv] - s(iv,q-1)*(1-tv1)*(1+t1q[iv]*tv1) ) / tv1;
00622     k(iv,q)  = (-lstep/2)*( ( 2*yn[iv] + s(iv,q-1)*(1-2*tv1) ) * 
00623                               t1q[iv]*tv1 + y[iv] - s(iv,q-1) )*tv1;
00624   }
00625 
00626   
00627   for ( q=start_index-1; q>0; q-- )
00628   {
00629     for ( iv=0; iv<nf; iv++ )    
00630     {
00631       tv1      = tr(iv,q-1);    
00632       tv       = tr(iv,q);
00633       t1q[iv] /= tv1*tv1;
00634       y[iv]    = ( y[iv] - s(iv,q-1)*(1-tv1)*(1+t1q[iv]*tv1) ) / tv1;
00635       k(iv,q) = (-lstep/2) * ( 
00636            ( 4*(yn[iv]-s(iv,q))*tv1*tv + 3*(s(iv,q)-s(iv,q-1))*tv1 + 
00637                                         2*s(iv,q-1) ) * t1q[iv]*tv1 + 
00638              2*(y[iv]-s(iv,q-1))*tv1 + s(iv,q-1) - s(iv,q) ) * tqn[iv];
00639       tqn[iv] *= tv1;
00640       yn[iv]   = yn[iv]*tv + s(iv,q)*(1-tv);
00641     } 
00642   }
00643 
00644   
00645   for ( iv=0; iv<nf; iv++ )    
00646     k(iv,0)  = (-lstep/2)*( (2*yn[iv]*tv1+s(iv,0)*(1-2*tv1))*t1q[iv] +
00647                        y[iv] - s(iv,0) ) * tqn[iv];
00648 
00649   
00650   
00651   
00652   
00653   
00654 }
00655 
00656 
00657 
00659 
00682 void absloswfs_rte_down (
00683                     Matrix&   k,
00684               const Vector&   y,
00685               const Vector&   y_space,
00686               const Index&   start_index,
00687               const Index&   stop_index,
00688               const Numeric&  lstep,
00689               const Matrix&   tr,
00690               const Matrix&   s,
00691               const Index&    ground,
00692               const Vector&   e_ground,
00693               const Vector&   y_ground )
00694 {
00695   const Index   nf = tr.nrows(); 
00696         Index   iv;              
00697         Index   q;               
00698         Vector   y0(nf);          
00699         Matrix   k2;              
00700         Vector   tr0;             
00701 
00702   
00703   k.resize( nf, start_index+1 );
00704 
00705   
00706   
00707   y0 = y_space;                 
00708                                 
00709                                 
00710   rte_iterate( y0, start_index-1, stop_index, tr, s, nf );
00711 
00712   
00713   
00714   bl( tr0, stop_index, stop_index, tr, ground, e_ground );
00715 
00716   
00717   
00718   absloswfs_rte_limb( k2, y, y0, stop_index, lstep, tr, s, ground, e_ground );
00719   for ( iv=0; iv<nf; iv++ )
00720   {
00721     for ( q=0; q<stop_index; q++ )
00722       k(iv,q) = k2(iv,q);
00723   }
00724 
00725   
00726   
00727   absloswfs_rte_1pass( k2, y0, start_index, stop_index, lstep, tr, s, 
00728                      ground, e_ground, y_ground );
00729   for ( iv=0; iv<nf; iv++ )
00730   {
00731     for ( q=stop_index+1; q<=start_index; q++ )
00732       k(iv,q) = k2(iv,q)*tr0[iv];
00733   }
00734 
00735   
00736   
00737   
00738   Vector yqq(nf);
00739   rte( yqq, stop_index-1, stop_index-1, tr, s, Vector(nf,0.0), 
00740                                             ground, e_ground, y_ground );
00741   
00742   
00743   q = stop_index; 
00744   for ( iv=0; iv<nf; iv++ )
00745   {
00746     tr0[iv] /= tr(iv,q-1)*tr(iv,q-1);    
00747     y0[iv]   = ( y0[iv] - s(iv,q)*(1-tr(iv,q)) ) / tr(iv,q);
00748     k(iv,q) = (-lstep/2)*( (3*(y0[iv]-s(iv,q))*tr(iv,q-1)*tr(iv,q) + 
00749                   2*(s(iv,q)-s(iv,q-1))*tr(iv,q-1) + s(iv,q-1) )*tr0[iv] + 
00750                                          yqq[iv] - s(iv,q-1) )*tr(iv,q-1);
00751   }
00752 }
00753 
00754 
00755 
00757 
00761 void absloswfs_rte (
00762                     ArrayOfMatrix&   absloswfs,
00763               const Los&             los,   
00764               const ArrayOfMatrix&   source,
00765               const ArrayOfMatrix&   trans,
00766               const Vector&          y,
00767               const Vector&          y_space,
00768               const Vector&          f_mono,
00769               const Vector&          e_ground,
00770               const Numeric&         t_ground )
00771 {
00772   const Index  nza = los.start.nelem();   
00773   const Index  nf  = f_mono.nelem();      
00774         Vector  yp(nf);                   
00775         Index  iy0=0;                    
00776 
00777   
00778   Vector   y_ground(f_mono.nelem()); 
00779   if ( any_ground(los.ground) )
00780     planck( y_ground, f_mono, t_ground );
00781 
00782   
00783   absloswfs.resize( nza );
00784 
00785   
00786   out3 << "    Zenith angle nr:\n      ";
00787   for (Index i=0; i<nza; i++ ) 
00788   {
00789     if ( ((i+1)%20)==0 )
00790       out3 << "\n      ";
00791     out3 << " " << i; cout.flush();
00792     
00793     
00794     if ( los.p[i].nelem() > 0 )
00795     {
00796 
00797       
00798       yp = y[Range(iy0,nf)];
00799 
00800       
00801       
00802       
00803       if ( los.stop[i]==0 )
00804         absloswfs_rte_1pass( absloswfs[i], yp, los.start[i], 0, los.l_step[i], 
00805                      trans[i], source[i], los.ground[i], e_ground, y_ground );
00806 
00807       
00808       
00809       else if ( los.start[i] == los.stop[i] )
00810         absloswfs_rte_limb( absloswfs[i], yp, y_space, los.start[i], 
00811                 los.l_step[i], trans[i], source[i], los.ground[i], e_ground );
00812 
00813       
00814       
00815       else 
00816         absloswfs_rte_down( absloswfs[i], yp, y_space, los.start[i], 
00817                             los.stop[i], los.l_step[i], trans[i], source[i], 
00818                                            los.ground[i], e_ground, y_ground );
00819     }
00820 
00821     iy0 += nf;        
00822   }
00823 
00824   out3 << "\n";
00825 }
00826 
00827 
00828 
00830 
00834 void absloswfs_tau (
00835                     ArrayOfMatrix&   absloswfs,
00836               const Los&             los,
00837               const Vector&          f_mono )
00838 {
00839   const Index  nza = los.start.nelem();   
00840   const Index  nf  = f_mono.nelem();      
00841   Numeric      kw, kw2;
00842   Index        row, col, np;
00843 
00844   
00845   absloswfs.resize( nza );
00846 
00847   
00848   out3 << "    Zenith angle nr:\n      ";
00849   for (Index i=0; i<nza; i++ ) 
00850   {
00851     if ( ((i+1)%20)==0 )
00852       out3 << "\n      ";
00853     out3 << " " << i; cout.flush();
00854 
00855     np = los.start[i] + 1;
00856 
00857     absloswfs[i].resize( nf, np );
00858     
00859     
00860     if ( los.p[i].nelem() > 0 )
00861     {
00862 
00863       
00864       if ( los.stop[i]==0 )
00865       {
00866         kw  = los.l_step[i] / 2.0;
00867         kw2 = los.l_step[i];
00868         for( row=0; row<nf; row++ )
00869         {
00870           absloswfs[i](row,0) = kw;
00871           absloswfs[i](row,np-1) = kw;
00872           for( col=1; col<np-1; col++ )
00873             absloswfs[i](row,col) = kw2;
00874         }
00875       }
00876 
00877       
00878       else if ( los.start[i] == los.stop[i] )
00879       {
00880         kw  = los.l_step[i];
00881         kw2 = los.l_step[i] * 2.0;
00882         for( row=0; row<nf; row++ )
00883         {
00884           absloswfs[i](row,0) = kw;
00885           absloswfs[i](row,np-1) = kw;
00886           for( col=1; col<np-1; col++ )
00887             absloswfs[i](row,col) = kw2;
00888         }
00889       }
00890 
00891       
00892       else 
00893       {
00894         kw  = los.l_step[i];
00895         kw2 = los.l_step[i] * 2.0;
00896         for( row=0; row<nf; row++ )
00897         {
00898           absloswfs[i](row,0) = kw;
00899           absloswfs[i](row,np-1) = kw / 2.0;
00900           absloswfs[i](row,los.stop[i]) = kw * 1.5;
00901           for( col=1; col<los.stop[i]; col++ )
00902             absloswfs[i](row,col) = kw2;
00903           for( col=los.stop[i]+1; col<np-1; col++ )
00904             absloswfs[i](row,col) = kw;
00905         }
00906       }
00907     }
00908   }
00909   out3 << "\n";
00910 }
00911 
00912 
00913 
00915 
00917 
00919 
00940 void sourceloswfs_1pass (
00941                     Matrix&   k,
00942               const Index&   start_index,
00943               const Index&   stop_index,   
00944               const Matrix&   tr,
00945               const Index&    ground,
00946               const Vector&   e_ground )
00947 {
00948   const Index   nf = tr.nrows();     
00949         Index   iv;                  
00950         Vector   t(nf,1.0);           
00951         Index   q;                   
00952 
00953   if ( ground && ((ground-1==stop_index) || (ground-1==start_index)) )
00954     throw logic_error("The ground cannot be at one of the end points."); 
00955 
00956   
00957   k.resize( nf, start_index+1 );
00958 
00959   
00960   
00961 
00962   
00963   q  = stop_index;
00964   for ( iv=0; iv<nf; iv++ )    
00965     k(iv,q)  = ( 1 - tr(iv,q) ) / 2;
00966 
00967   
00968   for ( q=stop_index+1; q<start_index; q++ )
00969   {
00970     
00971     if ( q != ground )
00972     {
00973       for ( iv=0; iv<nf; iv++ )    
00974       {
00975         k(iv,q) = ( 1 - tr(iv,q-1)*tr(iv,q) ) * t[iv] / 2;
00976         t[iv]  *= tr(iv,q); 
00977       }
00978     }
00979     
00980     else
00981     {
00982       out1 << "WARNING: The function sourceloswfs_1pass not tested "
00983               "for ground reflections\n";
00984 
00985       for ( iv=0; iv<nf; iv++ )    
00986       {
00987         k(iv,q) = ( (1-tr(iv,q))*(1-e_ground[iv])*tr(iv,q-1) + 1 - 
00988                                                      tr(iv,q-1) ) * t[iv] / 2;
00989         t[iv]  *= tr(iv,q)*(1-e_ground[iv]); 
00990       }
00991     }
00992   }
00993 
00994   
00995   q = start_index;
00996   for ( iv=0; iv<nf; iv++ )    
00997     k(iv,q)  = ( 1 - tr(iv,q-1) ) * t[iv] / 2;
00998 }
00999 
01000 
01001 
01003 
01020 void sourceloswfs_limb (
01021                     Matrix&   k,
01022               const Index&   start_index,
01023               const Matrix&   tr,
01024               const Index&    ground,
01025               const Vector&   e_ground )
01026 {
01027   const Index   nf = tr.nrows();      
01028         Index   iv;                  
01029         Vector   t1q;                 
01030         Vector   tqn(nf,1);           
01031         Index   q;                   
01032 
01033   
01034   bl( t1q, start_index, start_index, tr, ground, e_ground );
01035 
01036   
01037   k.resize( nf, start_index+1 );
01038 
01039   
01040   q  = start_index;       
01041   for ( iv=0; iv<nf; iv++ )    
01042   {
01043     t1q[iv] /= tr(iv,q-1) * tr(iv,q-1);
01044     k(iv,q)  = ( (1-tr(iv,q-1))*t1q[iv]*tr(iv,q-1) + 1 - tr(iv,q-1) )/2;
01045   }
01046 
01047   
01048   for ( q=start_index-1; q>0; q-- )
01049   {
01050     for ( iv=0; iv<nf; iv++ )    
01051     {
01052       t1q[iv]  /= tr(iv,q-1) * tr(iv,q-1);
01053       k(iv,q)  = ( (1-tr(iv,q-1)*tr(iv,q))*t1q[iv]*tr(iv,q-1)*
01054          tr(iv,q) + (1-tr(iv,q-1))*tr(iv,q) + 1 - tr(iv,q) ) * tqn[iv] / 2;
01055       tqn[iv]  *= tr(iv,q-1);
01056     } 
01057   }
01058 
01059   
01060   for ( iv=0; iv<nf; iv++ )    
01061     k(iv,0)  = ( (1-tr(iv,0))*(1+t1q[iv]*tr(iv,0)) ) * tqn[iv] / 2;
01062 }
01063 
01064 
01065 
01067 
01085 void sourceloswfs_down (
01086                     Matrix&   k,
01087               const Index&   start_index,
01088               const Index&   stop_index,
01089               const Matrix&   tr,
01090               const Index&    ground,
01091               const Vector&   e_ground )
01092 {
01093   const Index   nf = tr.nrows(); 
01094         Index   iv;             
01095         Index   q;              
01096         Matrix   k2;             
01097         Vector   tr0;            
01098 
01099   
01100   k.resize( nf, start_index+1 );
01101 
01102   
01103   
01104   bl( tr0, stop_index, stop_index, tr, ground, e_ground );
01105 
01106   
01107   sourceloswfs_limb( k2, stop_index, tr, ground, e_ground );  
01108   for ( iv=0; iv<nf; iv++ )
01109   {
01110     for ( q=0; q<stop_index; q++ )
01111       k(iv,q) = k2(iv,q);
01112   }
01113 
01114   
01115   
01116   sourceloswfs_1pass( k2, start_index, stop_index, tr, ground, e_ground );
01117   for ( iv=0; iv<nf; iv++ )
01118   {
01119     for ( q=stop_index+1; q<=start_index; q++ )
01120       k(iv,q) = k2(iv,q)*tr0[iv];
01121   }
01122 
01123   
01124   
01125   
01126   q = stop_index; 
01127   for ( iv=0; iv<nf; iv++ )
01128   {
01129     tr0[iv] /= tr(iv,q-1)*tr(iv,q-1);    
01130     k(iv,q)  = ( (1-tr(iv,q-1)*tr(iv,q))*tr0[iv]*tr0[iv]*tr(iv,q-1) + 1 - 
01131                  tr(iv,q-1) ) / 2;
01132   }
01133 }
01134 
01135 
01136 
01138 
01154 void sourceloswfs (
01155                     ArrayOfMatrix&   sourceloswfs,
01156               const Los&             los,   
01157               const ArrayOfMatrix&   trans,
01158               const Vector&          ,
01159               const Vector&          e_ground )
01160 {
01161   const Index  nza = los.start.nelem();   
01162 
01163   
01164   sourceloswfs.resize(nza);
01165 
01166   
01167   out3 << "    Zenith angle nr:      ";
01168   for (Index i=0; i<nza; i++ ) 
01169   {
01170     if ( (i%20)==0 )
01171       out3 << "\n      ";
01172     out3 << " " << i; cout.flush();
01173     
01174     
01175     if ( los.p[i].nelem() > 0 )
01176     {
01177       
01178       
01179       
01180       if ( los.stop[i]==0 )
01181         sourceloswfs_1pass( sourceloswfs[i], los.start[i], 0, trans[i], 
01182                                                      los.ground[i], e_ground );
01183       
01184       
01185       else if ( los.start[i] == los.stop[i] )
01186         sourceloswfs_limb( sourceloswfs[i], los.start[i], trans[i], 
01187                                                      los.ground[i], e_ground );
01188       
01189       
01190       else 
01191         sourceloswfs_down( sourceloswfs[i], los.start[i], los.stop[i], 
01192                                            trans[i], los.ground[i], e_ground );
01193     }
01194   }
01195   out3 << "\n";
01196 }
01197 
01198 
01199 
01201 
01202 
01203 
01204 
01205 
01207 
01209 
01244 void k_species (
01245                     Matrix&          k,
01246                     ArrayOfString&   k_names,
01247                     Matrix&          k_aux,
01248               const Los&             los,           
01249               const ArrayOfMatrix&   absloswfs,
01250               const Vector&          p_abs,
01251               const Vector&          t_abs,             
01252               const TagGroups&       tags,
01253               const ArrayOfMatrix&   abs_per_tg,
01254               const Matrix&          vmrs,
01255               const Vector&          k_grid,
01256               const ArrayOfIndex&    tg_nr,
01257               const String&          unit )
01258 {
01259   check_lengths( p_abs, "p_abs", t_abs, "t_abs" );  
01260   check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
01261   if ( tags.nelem() != abs_per_tg.nelem() )
01262     throw runtime_error(
01263                        "Lengths of *wfs_tgs* and *abs_per_tg* do not match." );
01264   if ( los.p.nelem() != absloswfs.nelem() )
01265     throw runtime_error(
01266      "The number of zenith angles is not the same in *los* and *absloswfs*." );
01267 
01268   
01269   const Index  nza = los.start.nelem();      
01270   const Index  nv  = abs_per_tg[0].nrows();  
01271   const Index  ntg = tg_nr.nelem();          
01272   const Index  np  = k_grid.nelem();         
01273 
01274   
01275   
01276   Vector  lgrid;                      
01277   p2grid( lgrid, k_grid );
01278   Vector  lplos;                      
01279 
01280   
01281   
01282         Index  itg;                       
01283         Index  iza;                       
01284         Index  ip, ip0=0;                 
01285         Index  iv, iv0;                   
01286         Index  i1, iw;                    
01287 
01288   
01289         Matrix  abs;                       
01290         Matrix  is;                        
01291         Vector  w;                         
01292         Vector  a(nv);                     
01293         Index  tg;                        
01294         Vector  vmr, p, t;                 
01295         Vector  nd;                        
01296 
01297   
01298   k.resize(nza*nv,ntg*np);
01299   k = 0.0;                      
01300   k_names.resize(ntg);
01301   k_aux.resize(ntg*np,2);
01302 
01303   
01304   
01305   
01306   
01307   
01308   
01309   for ( itg=0; itg<ntg; itg++ ) 
01310   {
01311     
01312     tg = tg_nr[itg];
01313 
01314     out2 << "  Doing " << tags[tg][0].Name() << "\n";
01315 
01316     
01317     abs.resize( nv, np );
01318     interpp( abs, p_abs, abs_per_tg[tg], k_grid );
01319 
01320     
01321     {
01322       ostringstream os;
01323       os << "Species: " << tags[tg][0].Name();
01324       k_names[itg] = os.str();
01325     }
01326 
01327     
01328     for ( ip=0; ip<np; ip++ )
01329        k_aux(ip0+ip,0) = k_grid[ip];
01330 
01331     
01332     
01333     
01334     
01335     
01336     vmr.resize( np );
01337     interpp( vmr, p_abs, vmrs(tg,Range(joker)), k_grid ); 
01338     
01339 
01340     if ( unit == "frac" )
01341     {
01342       for ( ip=0; ip<np; ip++ )
01343         k_aux(ip0+ip,1) = 1.0;
01344     }
01345     else if ( unit == "vmr" )
01346     {
01347       for ( ip=0; ip<np; ip++ )
01348       {
01349         for ( iv=0; iv<nv; iv++ )
01350           abs(iv,ip)   /= vmr[ip];
01351         k_aux(ip0+ip,1) = vmr[ip];
01352       }
01353     }  
01354     else if ( unit == "nd" )
01355     {
01356       nd.resize( np );
01357       interpp(  nd, p_abs, number_density(p_abs,t_abs), k_grid );
01358       nd *= vmr;                
01359                                 
01360       for ( ip=0; ip<np; ip++ )
01361       {
01362         for ( iv=0; iv<nv; iv++ )
01363           abs(iv,ip)   /= nd[ip];
01364         k_aux(ip0+ip,1) = nd[ip];
01365       }
01366     }
01367     else
01368       throw runtime_error(
01369         "Allowed species retrieval units are \"frac\", \"vmr\" and \"nd\"."); 
01370 
01371     
01372     iv0 = 0;                 
01373 
01374     
01375     out3 << "    Zenith angle nr:\n      ";
01376     for ( iza=0; iza<nza; iza++ ) 
01377     {
01378       if ( ((iza+1)%20)==0 )
01379         out3 << "\n      ";
01380       out3 << " " << iza; cout.flush();
01381       
01382       
01383       if ( los.p[iza].nelem() > 0 )
01384       {
01385         
01386         
01387         p2grid( lplos, los.p[iza] );
01388         grid2grid_index( is, lplos, lgrid );
01389 
01390         
01391         for ( ip=0; ip<np; ip++ ) 
01392         {
01393           
01394           if ( is(ip,0) >= 0 )
01395           {
01396             
01397             grid2grid_weights( w, lplos, (Index)is(ip,0), (Index)is(ip,1), 
01398                                                                  lgrid, ip );
01399 
01400             
01401             
01402             
01403 
01404             a = 0.0;            
01405 
01406             i1 = (Index)is(ip,0);       
01407             for ( iv=0; iv<nv; iv++ )
01408             {
01409               for ( iw=i1; iw<=(Index)is(ip,1); iw++ )
01410                 a[iv] += absloswfs[iza](iv,iw) * w[iw-i1];
01411               k(iv0+iv,ip0+ip) = a[iv] * abs(iv,ip);                    
01412             }
01413           }            
01414         }
01415       }
01416 
01417       
01418       iv0 += nv;
01419     }  
01420     out3 << "\n";
01421 
01422     
01423     ip0 += np;
01424   }  
01425 }
01426 
01427 
01428 
01430 
01465 void k_contabs (
01466                     Matrix&          k,
01467                     ArrayOfString&   k_names,
01468                     Matrix&          k_aux,
01469               const Los&             los,           
01470               const ArrayOfMatrix&   absloswfs,
01471               const Vector&          f_mono,
01472               const Vector&          k_grid,
01473               const Index&           order,
01474               const Numeric&         flow,
01475               const Numeric&         fhigh,
01476               const String&          lunit )
01477 {
01478 
01479   if ( los.p.nelem() != absloswfs.nelem() )
01480     {
01481     throw runtime_error(
01482                     "The number of zenith angles is not the same in *los* and *absloswfs*." ); 
01483     check_length_nrow( los.p[0], "los points", absloswfs[0], 
01484                                                  "the matrices of absloswfs" );
01485     }
01486   
01487   
01488   const Index  nza = los.start.nelem();     
01489   const Index  np  = k_grid.nelem();        
01490   const Index  npoints = order+1;           
01491   const Index  nv  = f_mono.nelem();        
01492 
01493   
01494   if ( flow >= fhigh )
01495     throw runtime_error(
01496              "The lower frequency limit equals or is above the upper limit." );
01497   if ( flow < f_mono[0] )
01498     throw runtime_error(
01499                   "The lower frequency limit is below all values of f_mono." );
01500   if ( fhigh > f_mono[nv-1] )
01501     throw runtime_error(
01502                   "The upper frequency limit is above all values of f_mono." );
01503 
01504   
01505   
01506   Numeric scfac;
01507   
01508   if ( lunit == "m" )
01509     scfac = 1.0;
01510   else if ( lunit == "km" )
01511     scfac = 0.001;
01512   else
01513     throw runtime_error("Allowed length units are \"m\" and \"km\".");
01514 
01515   
01516   
01517   Vector  lgrid;
01518   p2grid( lgrid, k_grid );
01519   Vector  lplos;                      
01520 
01521   
01522   
01523         Index  ipoint;                    
01524         Index  iza;                       
01525         Index  ip, ip0=0;                 
01526         Index  iv, iv0;                   
01527         Index  i1, iw;                    
01528 
01529   
01530   Index   ilow, ihigh;
01531   for( ilow=0; ilow<(nv-1) && f_mono[ilow] < flow; ilow++ )
01532     {}
01533   for( ihigh=ilow; ihigh<(nv-1) && f_mono[ihigh+1] <= fhigh; ihigh++ )
01534     {}
01535 
01536   
01537         Vector  fpoints;                   
01538         Vector  b(nv);                     
01539         Matrix  is;                        
01540         Vector  w;                         
01541         Vector  a(nv);                     
01542 
01543   
01544   if ( order < 0 )
01545     throw runtime_error("The polynomial order must be >= 0."); 
01546 
01547   
01548   k.resize(nza*nv,npoints*np);
01549   k = 0.0;                      
01550   k_names.resize(npoints);
01551   k_aux.resize(npoints*np,2);
01552 
01553   
01554   if ( npoints > 1 )
01555     nlinspace( fpoints, f_mono[ilow], f_mono[ihigh], npoints );
01556   else
01557   {
01558     fpoints.resize( 1 );
01559     fpoints[0] = ( f_mono[ilow] + f_mono[ihigh] ) / 2.0;
01560   }  
01561 
01562   
01563   
01564   
01565   
01566   
01567   
01568   
01569   
01570   
01571   
01572   out2 << "  You have selected " << npoints << " off-set fit points.\n";
01573   out2 << "  Length unit is " << lunit << "\n";
01574   for ( ipoint=0; ipoint<npoints; ipoint++ ) 
01575   {
01576     out2 << "  Doing point " << ipoint << "\n";
01577 
01578     
01579     {
01580       ostringstream os;
01581       os << "Continuum: " << fpoints[ipoint]/1e9 << " GHz, Point " 
01582          << ipoint+1 << "/" << npoints;
01583       k_names[ipoint] = os.str();
01584     }
01585     for ( ip=0; ip<np; ip++ )
01586     {
01587        k_aux(ip0+ip,0) = k_grid[ip];
01588        k_aux(ip0+ip,1) = 0.0;
01589     }
01590 
01591     
01592     b = 1.0;                    
01593     if ( npoints > 1 )
01594     {
01595       for ( ip=0; ip<npoints; ip++ )
01596       {
01597         if ( ip != ipoint )
01598         { 
01599           for ( iv=ilow; iv<=ihigh; iv++ )
01600             b[iv] *= (f_mono[iv]-fpoints[ip]) / ( fpoints[ipoint]-fpoints[ip]);
01601         }
01602       }
01603     }
01604 
01605     
01606     iv0 = 0;                 
01607 
01608     
01609     out3 << "    Zenith angle nr:\n      ";
01610     for ( iza=0; iza<nza; iza++ ) 
01611     {
01612       if ( ((iza+1)%20)==0 )
01613         out3 << "\n      ";
01614       out3 << " " << iza; cout.flush();
01615       
01616       
01617       if ( los.p[iza].nelem() > 0 )
01618       {
01619         
01620         
01621         p2grid( lplos, los.p[iza] );
01622         grid2grid_index( is, lplos, lgrid );
01623 
01624         
01625         for ( ip=0; ip<np; ip++ ) 
01626         {
01627           
01628           if ( is(ip,0) >= 0 )
01629           {
01630             
01631             grid2grid_weights( w, lplos, (Index)is(ip,0), (Index) is(ip,1),
01632                                                                  lgrid, ip );
01633 
01634             
01635             
01636             
01637 
01638             a = 0.0;            
01639 
01640             i1 = (Index)is(ip,0);       
01641             for ( iv=ilow; iv<=ihigh; iv++ )
01642             {
01643               for ( iw=i1; iw<=(Index)is(ip,1); iw++ )
01644                 a[iv] += absloswfs[iza](iv,iw) * w[iw-i1];
01645               k(iv0+iv,ip0+ip) = scfac * a[iv] * b[iv];                    
01646             }
01647           }            
01648         }
01649       }
01650 
01651       
01652       iv0 += nv;
01653     }  
01654     out3 << "\n";
01655 
01656     
01657     ip0 += np;
01658   }  
01659 }
01660 
01661 
01662 
01664 
01701 void k_temp_nohydro (
01702               Matrix&                     k,
01703               ArrayOfString&              k_names,
01704               Matrix&                     k_aux,
01705         const TagGroups&                  tag_groups,
01706         const Los&                        los,           
01707         const ArrayOfMatrix&              absloswfs,
01708         const Vector&                     f_mono,
01709         const Vector&                     p_abs,
01710         const Vector&                     t_abs,
01711         const Vector&                     n2_abs,          
01712         const Vector&                     h2o_abs,         
01713         const Matrix&                     vmrs,
01714         const ArrayOfArrayOfLineRecord&   lines_per_tg,
01715         const ArrayOfLineshapeSpec&       lineshape,
01716         const Matrix&                     abs,            
01717         const ArrayOfMatrix&              trans,
01718         const Vector&                     e_ground,
01719         const Vector&                     k_grid,
01720         const ArrayOfString&              cont_description_names,
01721         const ArrayOfVector&              cont_description_parameters,
01722         const ArrayOfString&              cont_description_models )
01723 {
01724   
01725   const Index  nza = los.start.nelem();     
01726   const Index  nv  = f_mono.nelem();        
01727   const Index  np  = k_grid.nelem();        
01728 
01729   
01730   
01731   
01732 
01733   Vector  lgrid;
01734   p2grid( lgrid, k_grid );
01735   Vector  lplos;                     
01736   ArrayOfMatrix W;
01737   Index ip;
01738   
01739   
01740   
01741         Index  iza;                       
01742         
01743         Index  iv, iv0=0;                 
01744         Index  i1, iw;                    
01745 
01746   
01747         Vector  t(k_grid.nelem());          
01748         Matrix  abs1k;                     
01749         Matrix  dabs_dt;                   
01750  ArrayOfMatrix  abs_dummy;                 
01751  ArrayOfMatrix  sloswfs;                   
01752         Matrix  is;                        
01753         Vector  w;                         
01754         Vector  a(nv), b(nv), pl(f_mono.nelem());  
01755 
01756  
01757  
01758         double  c,d;                       
01759 
01760 
01761   
01762   k.resize(nza*nv,np);
01763   k = 0.0;                      
01764   k_names.resize(1);
01765   k_names[0] = "Temperature: no hydrostatic eq.";
01766   k_aux.resize(np,2);
01767   interpp( t, p_abs, t_abs, k_grid ); 
01768   for ( ip=0; ip<np; ip++ )
01769   {
01770      k_aux(ip,0) = k_grid[ip];
01771      k_aux(ip,1) = t[ip];
01772   }
01773 
01774   
01775   
01776   out2 << "  Calculating absorption for t_abs + 1K\n";
01777   out2 << "  ----- Messages from absCalc: -----\n";
01778   
01779   {
01780     
01781     Vector dummy(t_abs);        
01782                                 
01783     dummy += 1;                 
01784 
01785     absCalc( abs1k, abs_dummy, tag_groups, f_mono, p_abs, dummy, n2_abs, 
01786              h2o_abs, vmrs, lines_per_tg, lineshape, cont_description_names, 
01787                         cont_description_models, cont_description_parameters);
01788   }
01789   abs_dummy.resize(0);
01790   
01791   out2 << "  ----- Back from absCalc ----------\n";
01792   
01793   
01794   abs1k -= abs;                 
01795 
01796   dabs_dt.resize( abs1k.nrows(), k_grid.nelem() );
01797   interpp( dabs_dt, p_abs, abs1k, k_grid );
01798   abs1k.resize(0,0);
01799 
01800   
01801   out2 << "  Calculating source LOS WFs\n";
01802   sourceloswfs( sloswfs, los, trans, f_mono, e_ground );
01803 
01804   
01805   out2 << "  Calculating temperature at retrieval points\n";
01806   interpp( t, p_abs, t_abs, k_grid );
01807 
01808   
01809   
01810   
01811   
01812   
01813   
01814   out2 << "  Calculating the weighting functions\n";
01815   out3 << "    Zenith angle nr:      ";
01816   for ( iza=0; iza<nza; iza++ ) 
01817   {
01818     if ( (iza%20)==0 )
01819       out3 << "\n      ";
01820     out3 << " " << iza; cout.flush();
01821     
01822     
01823     if ( los.p[iza].nelem() > 0 )
01824     {
01825       
01826       
01827       p2grid( lplos, los.p[iza] );
01828       grid2grid_index( is, lplos, lgrid );
01829 
01830       
01831       for ( ip=0; ip<np; ip++ ) 
01832       {
01833         
01834         if ( is(ip,0) >= 0 )
01835          {
01836           
01837           grid2grid_weights( w, lplos, (Index)is(ip,0), (Index) is(ip,1), 
01838                                                                  lgrid, ip );
01839 
01840           
01841           
01842           
01843           
01844           
01845           
01846           
01847           
01848           a = 0.0;              
01849           b = 0.0;                    
01850           c  = PLANCK_CONST / BOLTZMAN_CONST / t[ip];
01851           planck( pl, f_mono, t[ip] );
01852           i1 = (Index)is(ip,0);       
01853           
01854           for ( iv=0; iv<nv; iv++ )
01855           {
01856             for ( iw=i1; iw<=(Index)is(ip,1); iw++ )
01857             {
01858               a[iv] += sloswfs[iza](iv,iw) * w[iw-i1];
01859               b[iv] += absloswfs[iza](iv,iw) * w[iw-i1];
01860             }
01861             d = c * f_mono[iv];
01862             k(iv0+iv,ip) = a[iv] * d/t[ip] / (exp(d)-1) * pl[iv] +
01863                                                       b[iv] * dabs_dt(iv,ip);
01864             
01865             
01866             
01867 #ifdef HPUX
01868             if ( !isfinite(k(iv0+iv,ip)) )
01869 #else
01870             if ( !finite(k(iv0+iv,ip)) )
01871 #endif
01872               k(iv0+iv,ip) = 0.0;
01873 
01874           }
01875         }            
01876       }
01877     }
01878 
01879     
01880     iv0 += nv;
01881   }  
01882    out3 << "\n";
01883 }
01884 
01885 
01919 void kb_spectro(
01920                 Matrix&                             kb,
01921                 ArrayOfString&                      kb_names,
01922                 Matrix&                             ,
01923                 Matrix&                             S_S,
01924           const TagGroups&                          wfss_tgs,
01925           const TagGroups&                          tgs,
01926           const Vector&                             f_mono,
01927                 const Vector&                             p_abs,
01928                 const Vector&                             t_abs,
01929                 const Vector&                             h2o_abs,
01930                 const Matrix&                             vmrs,
01931                 const ArrayOfArrayOfLineRecord&     lines_per_tg,
01932                 const ArrayOfLineshapeSpec&   lineshape,
01933                 const Los&                                 los,           
01934           const ArrayOfMatrix&                absweight,
01935           const Index&                              IndexPar,
01936           const String&                             StrPar
01937 )
01938  { 
01939  
01940   const Index  nza = los.start.nelem();     
01941   const Index  nv  = f_mono.nelem();        
01942   const Index  np  = p_abs.nelem();         
01943   
01944   
01945   Index itg, iv, nr_line_total, iza, ip, nr_line; 
01946   
01947  
01948   Matrix        abs_line;
01949   Matrix        abs_line_changed;
01950   Matrix        dabs;
01951   dabs.resize(np,nv);
01952   Matrix        dabs1;
01953   dabs1.resize(nv,np);
01954 
01955   
01956   ArrayOfMatrix abs_dummy1;
01957   ArrayOfMatrix abs_dummy2;
01958   Index itg_wfss;
01959   ArrayOfIndex tag_index;
01960   tag_index.resize(wfss_tgs.nelem()); 
01961   tag_index = 0;
01962   
01963 
01964  
01965   for (itg_wfss=0; itg_wfss<wfss_tgs.nelem(); ++itg_wfss)
01966     {
01967       Index n;
01968       get_tag_group_index_for_tag_group( n, tgs, wfss_tgs[itg_wfss] );
01969       tag_index[itg_wfss] =n;
01970     }
01971 
01972  
01973   nr_line_total=0;
01974   nr_line=0;
01975   if (tag_index.nelem()==0)
01976     {
01977       ostringstream os;
01978       os << "No species has been set:   "<<"\n";        
01979       throw runtime_error(os.str());
01980     }
01981   else
01982     {  
01983       for ( itg_wfss=0; itg_wfss<tag_index.nelem(); ++itg_wfss )
01984         {
01985           itg=tag_index[itg_wfss];
01986           nr_line_total+=lines_per_tg[itg].nelem();
01987         }  
01988     }
01989   kb.resize(nza*nv,nr_line_total);
01990   kb=0.0;
01991   kb_names.resize(nr_line_total);
01992   S_S.resize(nr_line_total,2);
01993   S_S=0.0;
01994   
01995    
01996    
01997    
01998    
01999    
02000 
02001      for ( itg_wfss=0; itg_wfss<tag_index.nelem(); ++itg_wfss )
02002        {  
02003         out2<< " \n"; 
02004         out2<<"==================================: " <<" \n"; 
02005         out2<<"==Calculating weighting function for species==: " <<" \n"; 
02006         out2<< wfss_tgs[itg_wfss]<< "\n";  
02007         itg=tag_index[itg_wfss];
02008         out2<<"lines found: " <<lines_per_tg[itg].nelem()<< " \n"; 
02009         Index nr_line_dummy=0;
02010          if ( lines_per_tg[itg].nelem()>0)
02011            {
02012              Vector gamma;
02013              gamma.resize(lines_per_tg[itg].nelem());
02014              gamma=0.0;
02015              for ( Index li=0; li<lines_per_tg[itg].nelem(); ++li )
02016                { 
02017                  ArrayOfArrayOfLineRecord dummy_lines_per_tg; 
02018                  dummy_lines_per_tg.resize( lines_per_tg.nelem() ); 
02019                  dummy_lines_per_tg[itg].resize(1);
02020                  out3<<"==Calculating weighting function for line==: " <<" \n"; 
02021                  out3<< lines_per_tg[itg][li]<< "\n"; 
02022                  dummy_lines_per_tg[itg][0] = lines_per_tg[itg][li];
02023                  
02024                  xsec_per_tgInit( abs_dummy1, tgs, f_mono, p_abs );
02025                  xsec_per_tgAddLines( abs_dummy1, tgs, f_mono, p_abs, t_abs,
02026                                       h2o_abs, vmrs, dummy_lines_per_tg, 
02027                                       lineshape );               
02028                  absCalcFromXsec(abs_line, abs_dummy2, abs_dummy1 , vmrs );
02029                 
02030                  Numeric delta_s;   
02031                  Numeric parameter; 
02032                  Numeric dummy;     
02033                  Numeric ER_dummy;  
02034                  Vector ER_dummy2;  
02035                  ER_dummy2.resize(2);
02036                  ER_dummy2=0.0;
02037                 
02038                  switch ( IndexPar )
02039                    {
02040                    case 1: 
02041                      {
02042                        delta_s = 10E-25; 
02043                        
02044                        parameter  = dummy_lines_per_tg[itg][0].I0();
02045                        ER_dummy   = dummy_lines_per_tg[itg][0].dI0();
02046                        
02047                        if (ER_dummy == -1) 
02048                          {ER_dummy = 0.02;}
02049                        
02050                        ER_dummy2[0] = ER_dummy*parameter;
02051                        ER_dummy2[1] = ER_dummy*100;
02052                        
02053                        dummy = parameter +delta_s;       
02054                        dummy_lines_per_tg[itg][0].setI0(dummy);
02055                        break;
02056                      }
02057                    case 2: 
02058                      {
02059                        delta_s=10; 
02060                                   
02061                        parameter=dummy_lines_per_tg[itg][0].F();
02062                        ER_dummy = dummy_lines_per_tg[itg][0].dF();
02063                                  
02064                        if (ER_dummy==-1)
02065                          {ER_dummy=3*1E+9;}
02066                                     
02067                        ER_dummy2[0] = ER_dummy;
02068                        ER_dummy2[1] = ER_dummy;
02069                                   
02070                        dummy = parameter +delta_s;       
02071                        dummy_lines_per_tg[itg][0].setF(dummy);
02072                        break;
02073                      }
02074                    case 3: 
02075                      {  
02076                        delta_s=0.001; 
02077                                   
02078                        parameter = dummy_lines_per_tg[itg][0].Agam();                 
02079                        ER_dummy = dummy_lines_per_tg[itg][0].dAgam();
02080                                     
02081                        if (ER_dummy==-1)
02082                          {ER_dummy=2;}
02083                                    
02084                        ER_dummy2[0] = parameter*ER_dummy;
02085                        ER_dummy2[1] = ER_dummy*100;
02086                                    
02087                        dummy = parameter +delta_s;       
02088                        dummy = parameter + parameter *delta_s;   
02089                        dummy_lines_per_tg[itg][0].setAgam(dummy);
02090                        break;
02091                      }
02092                    case 4: 
02093                      {
02094                        delta_s=0.001; 
02095                                    
02096                        parameter=dummy_lines_per_tg[itg][0].Sgam();
02097                        ER_dummy = dummy_lines_per_tg[itg][0].dSgam();
02098                                    
02099                        if (ER_dummy==-1)
02100                          {ER_dummy=2;}
02101                                    
02102                        ER_dummy2[0] = parameter*ER_dummy;
02103                        ER_dummy2[1] = ER_dummy*100;
02104                                   
02105                        dummy    = parameter +parameter*delta_s;          
02106                        dummy_lines_per_tg[itg][0].setSgam(dummy);
02107                        break;
02108                      }
02109                    case 5: 
02110                      {
02111                        delta_s=0.001; 
02112                                  
02113                        parameter=dummy_lines_per_tg[itg][0].Nair();
02114                        ER_dummy = dummy_lines_per_tg[itg][0].dNair();
02115                                   
02116                        if (ER_dummy==-1)
02117                          {ER_dummy=2;}
02118                        
02119                        ER_dummy2[0] = parameter*ER_dummy;
02120                        ER_dummy2[1] = ER_dummy*100;
02121                                    
02122                        dummy = parameter + parameter*delta_s;            
02123                        dummy_lines_per_tg[itg][0].setNair(dummy);
02124                        break; 
02125                      }
02126                    case 6: 
02127                      { 
02128                        delta_s=0.01; 
02129                                   
02130                        parameter=dummy_lines_per_tg[itg][0].Nself();
02131                        ER_dummy = dummy_lines_per_tg[itg][0].dNself();
02132                                    
02133                        if (ER_dummy==-1)
02134                          {ER_dummy=2;}
02135                                    
02136                        ER_dummy2[0] = parameter*ER_dummy;
02137                        ER_dummy2[1] = ER_dummy*100;
02138                                     
02139                        dummy = parameter +parameter*delta_s;             
02140                        dummy_lines_per_tg[itg][0].setNself(dummy);
02141                        break;
02142                      }
02143                    case 7: 
02144                      {
02145                        extern const Numeric TORR2PA;
02146                        delta_s=1;
02147                                   
02148                        parameter=dummy_lines_per_tg[itg][0].Psf();
02149                        ER_dummy = dummy_lines_per_tg[itg][0].dPsf();
02150                                     
02151                        if ((ER_dummy==-1)|| (parameter==0.0))
02152                          {ER_dummy = 1E6 / TORR2PA;}
02153                        else 
02154                          {ER_dummy=ER_dummy*parameter;}
02155                        
02156                        ER_dummy2[0] = ER_dummy;
02157                        ER_dummy2[1] = ER_dummy;
02158                        dummy = parameter + delta_s                 ;     
02159                        dummy_lines_per_tg[itg][0].setPsf(dummy);         
02160                        break; 
02161                      }
02162                    default: 
02163                      {
02164                        ostringstream os;
02165                        os << "The sectroscopic parameter:   "  << StrPar<<"\n"
02166                           << "does not exists"; 
02167                        throw runtime_error(os.str());
02168                      }
02169                    }
02170                  
02171                  xsec_per_tgInit( abs_dummy1, tgs, f_mono, p_abs );
02172                  xsec_per_tgAddLines( abs_dummy1,
02173                                       tgs, f_mono, p_abs, t_abs, h2o_abs, vmrs,
02174                                       dummy_lines_per_tg, lineshape );  
02175                  absCalcFromXsec(abs_line_changed, abs_dummy2, abs_dummy1, vmrs ); 
02176                  abs_line_changed-=abs_line; 
02177                  dabs1=abs_line_changed;
02178                  dabs1/=dummy-parameter;
02179                  dabs=transpose(dabs1);
02180                  Index iv0=0;
02181                  for ( iza=0; iza<nza; iza++ ) 
02182                    { 
02183                      if ( (iza%20)==0 )
02184                        out3 << "\n      ";
02185                      out3 << " " << iza; cout.flush();
02186                      
02187                      if ( los.p[iza].nelem() > 0 ) 
02188                        {
02189                          for ( iv=0; iv<nv; iv++ ) 
02190                            {         
02191                              for ( ip=0; ip<np; ip++ )
02192                                { 
02193                                  kb(iv0+iv, nr_line)+= absweight[iza](iv,ip)* dabs(ip, iv);
02194                                }
02195                              
02196                              
02197 #ifdef HPUX
02198                              if ( !isfinite(kb(iv0+iv, nr_line)) )
02199 #else
02200                                if ( !finite(kb(iv0+iv, nr_line)) )
02201 #endif
02202                                  kb(iv0+iv,nr_line) = 0.0;
02203                            }
02204                          iv0+=nv;
02205                        }
02206                    }        
02207                  Numeric nr = dummy_lines_per_tg[itg][0].F() *1e-9;
02208                  ostringstream os;
02209                  
02210                  
02211                  if (IndexPar == 2)
02212                    {
02213                      os <<tgs[itg]<<"@" <<nr<<"GHz"<<" / "<<StrPar<<": " << ER_dummy2[1] <<"Hz";
02214                    }
02215                  else if (IndexPar == 7)
02216                    {
02217                      os <<tgs[itg]<<"@" <<nr<<"GHz"<<" / "<<StrPar<<": "  << ER_dummy2[1] <<"Hz/Pa";
02218                    }
02219 
02220                  else
02221                    {
02222                      os <<tgs[itg]<<"@" <<nr<<"GHz"<<" / "<<StrPar<<": "  << ER_dummy2[1]<< "%";
02223                    }
02224                  kb_names[nr_line]= os.str();
02225                  S_S(nr_line, Range(joker))= ER_dummy2;
02226                  ++nr_line;
02227                  ++nr_line_dummy;
02228                } 
02229        }
02230  }
02231  }
02232 
02268 void kSpectro (
02269                     Matrix&                               k,
02270                     ArrayOfString&                   k_names,
02271                     Matrix&                               ,
02272                     Matrix&                               S_S,
02273           const TagGroups&                          wfss_tgs,
02274           const TagGroups&                          tgs,
02275           const Vector&                               f_mono,
02276           const Vector&                               p_abs,
02277           const Vector&                               t_abs,
02278           const Vector&                               z_abs,
02279           const Vector&                               h2o_abs,
02280           const Matrix&                               vmrs,
02281           const ArrayOfArrayOfLineRecord&             lines_per_tg,
02282           const ArrayOfLineshapeSpec&                    lineshape,
02283           const Los&                                  los,           
02284           const ArrayOfMatrix&                 absloswfs,
02285           
02286           const  Index&                               kw_intens,
02287           const  Index&                               kw_position,
02288                 const  Index&                               kw_agam,
02289                 const  Index&                               kw_sgam,
02290                 const  Index&                               kw_nair,
02291           const  Index&                               kw_nself,
02292                 const  Index&                               kw_pSift)
02293 {
02294 
02295   check_if_bool( kw_intens, "do_intens keyword" );
02296   check_if_bool( kw_position, "do_position keyword" );
02297   check_if_bool( kw_agam, "do_agam keyword" );
02298   check_if_bool( kw_sgam, "do_sgam keyword" );
02299   check_if_bool( kw_nair, "do_nair keyword" );
02300   check_if_bool( kw_nself, "do_nself keyword" );
02301   check_if_bool( kw_pSift,  "do_pSift keyword" );
02302   check_lengths( p_abs, "p_abs", t_abs, "t_abs" );  
02303   check_lengths( p_abs, "p_abs", z_abs, "z_abs" );  
02304   check_lengths( p_abs, "p_abs", h2o_abs, "h2o_abs" );  
02305   check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
02306 
02307  
02308   const Index  nza = los.start.nelem();     
02309   const Index  nv  = f_mono.nelem();        
02310   
02311   
02312   
02313   Index  iza;                       
02314   Index itg;
02315   
02316   
02317   ArrayOfMatrix W; 
02318   ArrayOfMatrix absweight; 
02319   absweight.resize(nza);
02320   ArrayOfIndex  k_lengths;
02321   Matrix        kb;
02322   ArrayOfString kb_names;
02323   Matrix        kb_aux;
02324   Matrix        abs_line;
02325   Matrix        abs_line_changed;
02326   Matrix        ER;
02327   ArrayOfMatrix abs_dummy1;
02328   Index         IndexPar; 
02329   String        StrPar;
02330   Index         ipar = 0;              
02331 
02332   
02333   grid2grid_weights_total(W, los, p_abs);
02334   
02335   for ( iza=0; iza<nza; iza++ ) 
02336     {
02337       absweight[iza].resize(absloswfs[iza].nrows(), W[iza].ncols());  
02338       
02339       if ( los.p[iza].nelem() > 0 )
02340         {
02341           mult(absweight[iza], absloswfs[iza], W[iza]); 
02342         }
02343     }
02344 
02345 
02346   if (kw_intens) 
02347     {  ++ipar;}
02348   if (kw_position) 
02349     {  ++ipar;}
02350   if (kw_agam) 
02351     {  ++ipar;}
02352   if (kw_sgam) 
02353     {  ++ipar;}
02354   if (kw_nair) 
02355     {  ++ipar;}
02356   if (kw_nself) 
02357     {  ++ipar;}
02358   if (kw_pSift) 
02359     {  ++ipar;}
02360   Index nr_line_total=0;
02361   Index itg_wfss;
02362   ArrayOfIndex tag_index;
02363   tag_index.resize(wfss_tgs.nelem()); 
02364   tag_index = 0;
02365 
02366 
02367   
02368   for (itg_wfss=0; itg_wfss<wfss_tgs.nelem(); ++itg_wfss)
02369     {
02370       Index n;
02371       get_tag_group_index_for_tag_group( n, tgs, wfss_tgs[itg_wfss] );
02372       tag_index[itg_wfss] =n;
02373     }
02374 
02375   
02376   nr_line_total=0;
02377 
02378   
02379   
02380   
02381  if (tag_index.nelem()==0)
02382     {
02383       ostringstream os;
02384       os << "No species has been set:   "<<"\n";        
02385       throw runtime_error(os.str());
02386     }
02387   else
02388     {  
02389       for ( itg_wfss=0; itg_wfss<tag_index.nelem(); ++itg_wfss )
02390         {
02391           itg=tag_index[itg_wfss];
02392           nr_line_total+=lines_per_tg[itg].nelem();
02393         }  
02394     }
02395 
02396  
02397  
02398   if (ipar == 0)
02399     {
02400       ostringstream os;
02401       os << "No sectroscopic parameters have been set"; 
02402       throw runtime_error(os.str());
02403     }
02404   if (nr_line_total == 0)
02405     {
02406       ostringstream os;
02407       os << " No line for which to calculate weighting function has been found. Catalog empty?";        
02408       throw runtime_error(os.str());
02409     }
02410   
02411   k.resize(nza*nv, nr_line_total*ipar);
02412   k=0.0;
02413   k_names.resize(nr_line_total*ipar);
02414   S_S.resize(nr_line_total*ipar,2);
02415   ER.resize(nr_line_total,2);
02416 
02417   
02418   Index nr_line=0;
02419  
02420   
02421   if (kw_intens) 
02422     {  
02423       IndexPar = 1;
02424       StrPar = "S";
02425       out1<< " \n"; 
02426       out1<<"==================================: " <<" \n"; 
02427       out1<<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02428       kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, tgs, 
02429                   f_mono, p_abs, t_abs, 
02430                   h2o_abs, vmrs, lines_per_tg, lineshape, los, absweight, 
02431                   IndexPar, StrPar); 
02432       k(Range(joker),Range(nr_line,  kb.ncols()))= kb;
02433      
02434       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02435         {
02436           k_names[nr_line+iri]= kb_names[iri]; 
02437           S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
02438         } 
02439         nr_line+=kb.ncols();
02440     }
02441   
02442   if (kw_position)
02443     { 
02444       IndexPar  = 2;
02445       StrPar = "f0";
02446       out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02447       kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, tgs, 
02448                   f_mono, p_abs, t_abs, 
02449                   h2o_abs, vmrs, lines_per_tg, 
02450                   lineshape, los, absweight, IndexPar, StrPar);
02451       k(Range(joker), Range(nr_line,  kb.ncols()))= kb;
02452       
02453       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02454         {
02455           k_names[nr_line+iri]= kb_names[iri];
02456           S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
02457         } 
02458               nr_line+=kb.ncols();
02459         }
02460   
02461   if (kw_agam)
02462     { 
02463       IndexPar = 3;
02464       StrPar = "agam";
02465       out1<<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02466       kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs,
02467                   tgs, f_mono, p_abs, t_abs,
02468                   h2o_abs, vmrs, lines_per_tg, 
02469                   lineshape, los, absweight, IndexPar, StrPar);
02470       k(Range(joker),Range(nr_line,  kb.ncols()))= kb;
02471       
02472       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02473         {
02474           k_names[nr_line+iri]= kb_names[iri]; 
02475           S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
02476         } 
02477              nr_line+=kb.ncols();
02478         }
02479 
02480   if (kw_sgam)
02481     { 
02482       IndexPar = 4;
02483       StrPar = "sgam";
02484       out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02485       kb_spectro( kb, kb_names, kb_aux, ER,  wfss_tgs,
02486                   tgs, f_mono, p_abs, t_abs, 
02487                   h2o_abs, vmrs, lines_per_tg, 
02488                   lineshape, los, absweight, IndexPar, StrPar);
02489       k(Range(joker),Range(nr_line,  kb.ncols()))= kb;
02490       
02491       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02492         {
02493           k_names[nr_line+iri]= kb_names[iri]; 
02494           S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker));
02495         } 
02496       nr_line+=kb.ncols();
02497     }
02498  
02499   if (kw_nair)
02500     { 
02501       IndexPar = 5;
02502       StrPar = "na";
02503       out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02504       kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, 
02505                   tgs, f_mono, p_abs, t_abs, 
02506                   h2o_abs, vmrs, lines_per_tg, 
02507                   lineshape, los, absweight, IndexPar, StrPar);
02508       k(Range(joker),Range(nr_line,  kb.ncols()))= kb;
02509       
02510       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02511         {
02512           k_names[nr_line+iri]= kb_names[iri];
02513           S_S(nr_line+iri, Range(joker)) = ER(iri, Range(joker));
02514         } 
02515       nr_line+=kb.ncols();      
02516         }
02517 
02518   if (kw_nself)
02519     { 
02520       IndexPar = 6;
02521       StrPar = "ns";
02522       out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02523       kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, 
02524                   tgs, f_mono, p_abs, t_abs, 
02525                   h2o_abs, vmrs, lines_per_tg, lineshape, los, absweight, 
02526                   IndexPar, StrPar);
02527       k(Range(joker),Range(nr_line,  kb.ncols()))= kb;
02528       
02529       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02530         {
02531           k_names[nr_line+iri]= kb_names[iri];
02532           S_S(nr_line+iri, Range(joker))=ER(iri, Range(joker)); 
02533         } 
02534       nr_line+=kb.ncols();        
02535         }
02536   
02537   if (kw_pSift)
02538     { 
02539       IndexPar = 7;
02540       StrPar = "pSf";
02541       out1 <<" ******* Calculating Wfs for "<< StrPar<<" ******\n"; 
02542       kb_spectro( kb, kb_names, kb_aux, ER, wfss_tgs, 
02543                   tgs, f_mono, p_abs, t_abs,
02544                   h2o_abs, vmrs, lines_per_tg, lineshape, los, absweight,
02545                   IndexPar, StrPar);
02546       k(Range(joker),Range(nr_line,  kb.ncols()))= kb;
02547       ER.resize(kb_names.nelem(),2);
02548       for ( Index iri=0; iri<kb_names.nelem(); iri++)
02549         {
02550           k_names[nr_line+iri]= kb_names[iri]; 
02551           S_S(nr_line+iri, Range(joker)) = ER(iri, Range(joker));
02552         } 
02553       nr_line+=kb.ncols();
02554         }
02555   if (ipar == 0)
02556      {
02557        ostringstream os;
02558        os << "No sectroscopic parameters have been set";        
02559        throw runtime_error(os.str());
02560      }
02561 } 
02562  
02564 
02566 
02567 
02574 void wfs_tgsDefine(
02575                    TagGroups& wfs_tag_groups,
02576                    
02577                    const ArrayOfString& tags)
02578 {
02579   wfs_tag_groups = TagGroups(tags.nelem());
02580 
02581   
02582   
02583   for ( Index i=0; i<tags.nelem(); ++i )
02584     {
02585       
02586       
02587       ArrayOfString tag_def;
02588 
02589       bool go_on = true;
02590       String these_tags = tags[i];
02591       while (go_on)
02592         {
02593           Index n = these_tags.find(',');
02594           if ( n == these_tags.npos ) 
02595             {
02596               
02597               tag_def.push_back(these_tags);
02598               go_on = false;
02599             }
02600           else
02601             {
02602               tag_def.push_back(these_tags.substr(0,n));
02603               these_tags.erase(0,n+1);
02604             }
02605         }
02606 
02607       
02608       
02609       
02610       wfs_tag_groups[i] = Array<OneTag>();
02611 
02612       for ( Index s=0; s<tag_def.nelem(); ++s )
02613         {
02614           
02615           while ( ' '  == tag_def[s][0] ||
02616                   '\t' == tag_def[s][0]    )    tag_def[s].erase(0,1);
02617 
02618           OneTag this_tag(tag_def[s]);
02619 
02620           
02621           
02622           if (s>0)
02623             if ( wfs_tag_groups[i][0].Species() != this_tag.Species() )
02624               throw runtime_error(
02625                        "Tags in a tag group must belong to the same species.");
02626 
02627           wfs_tag_groups[i].push_back(this_tag);
02628         }
02629     }
02630 
02631   
02632   out3 << "  Defined weighting function tag groups:";
02633   for ( Index i=0; i<wfs_tag_groups.nelem(); ++i )
02634     {
02635       out3 << "\n  " << i << ":";
02636       for ( Index s=0; s<wfs_tag_groups[i].nelem(); ++s )
02637         {
02638           out3 << " " << wfs_tag_groups[i][s].Name();
02639         }
02640     }
02641   out3 << '\n';
02642 }
02643 
02650 void wfss_tgsDefine(
02651                    TagGroups& wfss_tgs,
02652                    
02653                    const ArrayOfString& tags)
02654 {
02655   wfss_tgs = TagGroups(tags.nelem());
02656 
02657   
02658   
02659   for ( Index i=0; i<tags.nelem(); ++i )
02660     {
02661       
02662       
02663       ArrayOfString tag_def;
02664 
02665       bool go_on = true;
02666       String these_tags = tags[i];
02667       while (go_on)
02668         {
02669           Index n = these_tags.find(',');
02670           if ( n == these_tags.npos ) 
02671             {
02672               
02673               tag_def.push_back(these_tags);
02674               go_on = false;
02675             }
02676           else
02677             {
02678               tag_def.push_back(these_tags.substr(0,n));
02679               these_tags.erase(0,n+1);
02680             }
02681         }
02682 
02683       
02684       
02685       
02686       wfss_tgs[i] = Array<OneTag>();
02687 
02688       for ( Index s=0; s<tag_def.nelem(); ++s )
02689         {
02690           
02691           while ( ' '  == tag_def[s][0] ||
02692                   '\t' == tag_def[s][0]    )    tag_def[s].erase(0,1);
02693 
02694           OneTag this_tag(tag_def[s]);
02695 
02696           
02697           
02698           if (s>0)
02699             if ( wfss_tgs[i][0].Species() != this_tag.Species() )
02700               throw runtime_error(
02701                        "Tags in a tag group must belong to the same species.");
02702 
02703           wfss_tgs[i].push_back(this_tag);
02704         }
02705     }
02706 
02707   
02708   out3 << "  Defined weighting function tag groups:";
02709   for ( Index i=0; i<wfss_tgs.nelem(); ++i )
02710     {
02711       out3 << "\n  " << i << ":";
02712       for ( Index s=0; s<wfss_tgs[i].nelem(); ++s )
02713         {
02714           out3 << " " << wfss_tgs[i][s].Name();
02715         }
02716     }
02717   out3 << '\n';
02718 }
02719 
02726 void absloswfsCalc (
02727                     ArrayOfMatrix&   absloswfs,
02728               const Index&             emission,
02729               const Los&             los,   
02730               const ArrayOfMatrix&   source,
02731               const ArrayOfMatrix&   trans,
02732               const Vector&          y,
02733               const Vector&          y_space,
02734               const Vector&          f_mono,
02735               const Vector&          e_ground,
02736               const Numeric&         t_ground )
02737 {
02738   check_if_bool( emission, "emission" );                                      
02739 
02740   if ( emission == 0 )
02741     absloswfs_tau ( absloswfs, los, f_mono );
02742   else
02743     absloswfs_rte ( absloswfs, los, source, trans, y, y_space, f_mono,     
02744                                                           e_ground, t_ground );
02745 
02746   
02747   
02748   
02749   Index     irow, icol, ncol;
02750   Numeric   w;
02751   for( Index im=0; im<absloswfs.nelem(); im++ )
02752   {
02753     for( irow=0; irow<absloswfs[im].nrows(); irow++ )
02754     {
02755       ncol = absloswfs[im].ncols();
02756       for( icol=0; icol<ncol; icol++ )
02757       {
02758         w = absloswfs[im](irow,icol);
02759 #ifdef HPUX
02760         if ( !isfinite(w) )
02761 #else
02762         if ( !finite(w) )
02763 #endif
02764           absloswfs[im](irow,icol) = 0.0;
02765       }
02766     }
02767   }
02768 }
02769 
02770 
02771 
02778 void kSpecies (
02779                     Matrix&          k,
02780                     ArrayOfString&   k_names,
02781                     Matrix&          k_aux,
02782               const Los&             los,           
02783               const ArrayOfMatrix&   absloswfs,
02784               const Vector&          p_abs,
02785               const Vector&          t_abs,             
02786               const TagGroups&       wfs_tgs,
02787               const ArrayOfMatrix&   abs_per_tg,
02788               const Matrix&          vmrs,
02789               const Vector&          k_grid,
02790               const String&          unit )
02791 {
02792   
02793 
02794   const Index   ntg = wfs_tgs.nelem();     
02795   ArrayOfIndex  tg_nr(ntg);
02796 
02797   for ( Index i=0; i<ntg; i++ )
02798     tg_nr[i] = i;
02799 
02800   k_species( k, k_names, k_aux, los, absloswfs, p_abs, t_abs, 
02801              wfs_tgs, abs_per_tg, vmrs, k_grid, tg_nr, unit );
02802 }
02803 
02804 
02805 
02812 void kSpeciesSingle (
02813                     Matrix&          k,
02814                     ArrayOfString&   k_names,
02815                     Matrix&          k_aux,
02816               const Los&             los,           
02817               const ArrayOfMatrix&   absloswfs,
02818               const Vector&          p_abs,
02819               const Vector&          t_abs,             
02820               const TagGroups&       wfs_tgs,
02821               const ArrayOfMatrix&   abs_per_tg,
02822               const Matrix&          vmrs,
02823               const Vector&          k_grid,
02824               const String&          tg,
02825               const String&          unit )
02826 {
02827   
02828 
02829   ArrayOfString  tg_name(1);
02830   tg_name[0] = tg;
02831 
02832   ArrayOfIndex   tg_nr; 
02833   get_tagindex_for_Strings( tg_nr, wfs_tgs, tg_name );
02834   
02835   k_species( k, k_names, k_aux, los, absloswfs, p_abs, t_abs, 
02836                              wfs_tgs, abs_per_tg, vmrs, k_grid, tg_nr, unit );
02837 }
02838 
02839 
02840 
02847 void kContAbs (
02848                     Matrix&          k,
02849                     ArrayOfString&   k_names,
02850                     Matrix&          k_aux,
02851               const Los&             los,           
02852               const ArrayOfMatrix&   absloswfs,
02853               const Vector&          f_mono,
02854               const Vector&          k_grid,
02855               const Index&           order,
02856               const Numeric&         f_low,
02857               const Numeric&         f_high,
02858               const String&          l_unit )
02859 {
02860   
02861 
02862   Numeric f1=f_low, f2=f_high;
02863 
02864   if ( f1 < 0 )
02865     f1 = first( f_mono );
02866   if ( f2 < 0 )
02867     f2 = last( f_mono );
02868 
02869   k_contabs( k, k_names, k_aux, los, absloswfs, f_mono, k_grid, order, f1, f2,
02870                                                                       l_unit );
02871 }
02872 
02873 
02874 
02881 void kTemp (
02882                 Matrix&                      k,
02883                 ArrayOfString&               k_names,
02884                 Matrix&                      k_aux,
02885           const TagGroups&                   tgs,
02886           const Vector&                      f_mono,
02887           const Vector&                      p_abs,
02888           const Vector&                      t_abs,
02889           const Vector&                      n2_abs,
02890           const Vector&                      h2o_abs,
02891           const Matrix&                      vmrs,
02892           const Matrix&                      abs0,
02893           const ArrayOfArrayOfLineRecord&    lines_per_tg,
02894           const ArrayOfLineshapeSpec&        lineshape,
02895           const Vector&                      e_ground,
02896           const Index&                       emission,
02897           const Vector&                      k_grid,
02898           const ArrayOfString&               cont_description_names,
02899           const ArrayOfVector&               cont_description_parameters,
02900           const ArrayOfString&               cont_description_models,
02901           const Los&                         los,           
02902           const ArrayOfMatrix&               absloswfs,
02903           const ArrayOfMatrix&               trans,
02904           const Numeric&                     z_plat,
02905           const Vector&                      za,
02906           const Numeric&                     l_step,
02907           const Vector&                      z_abs,
02908           const Index&                       refr,
02909           const Index&                       refr_lfac,
02910           const Vector&                      refr_index,
02911           const String&                      refr_model,
02912           const Numeric&                     z_ground,
02913           const Numeric&                     t_ground,
02914           const Vector&                      y_space,
02915           const Numeric&                     r_geoid,
02916           const Vector&                      hse,
02917           
02918           const Index&                       kw_hse,
02919           const Index&                       kw_fast )
02920 {
02921   check_if_bool( kw_hse, "hse keyword" );
02922   check_if_bool( kw_fast, "fast keyword" );      
02923   check_if_bool( emission, "emission" );
02924   check_if_bool( refr, "refr" );
02925   check_lengths( p_abs, "p_abs", t_abs, "t_abs" );  
02926   check_lengths( p_abs, "p_abs", z_abs, "z_abs" );  
02927   check_lengths( p_abs, "p_abs", h2o_abs, "h2o_abs" );  
02928   check_lengths( p_abs, "p_abs", n2_abs, "n2_abs" );  
02929   check_length_ncol( p_abs, "p_abs", abs0, "abs" );
02930   check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
02931   check_length_nrow( f_mono, "f_mono", abs0, "abs" );
02932   if ( los.p.nelem() != za.nelem() )
02933     throw runtime_error(
02934                "The number of zenith angles of *za* and *los* are different.");
02935   
02936   if( refr ) 
02937     check_lengths( p_abs, "p_abs", refr_index, "refr_index" );  
02938   
02939   if ( !kw_hse )
02940   {
02941     if ( los.p.nelem() != trans.nelem() )
02942       throw runtime_error(
02943             "The number of zenith angles of *los* and *trans* are different.");
02944 
02945     if ( los.p.nelem() != absloswfs.nelem() )
02946       throw runtime_error(
02947       "The number of zenith angles is not the same in *los* and *absloswfs*.");
02948   }
02949   else
02950   { 
02951     if ( hse[0]==0 )
02952       throw runtime_error( "Hydrostatic eq. must be considered generally" 
02953                            "when calculating WFs with hydrostatic eq.");
02954   }
02955   
02956   if ( any_ground(los.ground) )  
02957   {
02958     if ( t_ground <= 0 )
02959       throw runtime_error(
02960           "There are intersections with the ground, but the ground\n"
02961           "temperature is set to be <=0 (are dummy values used?).");
02962     if ( e_ground.nelem() != f_mono.nelem() )
02963       throw runtime_error(
02964           "There are intersections with the ground, but the frequency and\n"
02965           "ground emission vectors have different lengths (are dummy values\n"
02966           "used?).");
02967   }
02968   if ( emission ) 
02969     check_lengths( f_mono, "f_mono", y_space, "y_space" );
02970 
02971   
02972   
02973   
02974   
02975   
02976   
02977 
02978 
02979   
02980   
02981   if ( !kw_hse )
02982   {
02983     if ( !emission )
02984       throw runtime_error(
02985           "Analytical expressions for temperature and no emission have not\n"
02986           "yet been implemented. Sorry!");
02987 
02988     k_temp_nohydro( k, k_names, k_aux, tgs, los, absloswfs, f_mono, 
02989      p_abs, t_abs, n2_abs, h2o_abs, vmrs, lines_per_tg, lineshape, abs0, trans,
02990      e_ground, k_grid, cont_description_names, cont_description_parameters,
02991      cont_description_models);
02992   }
02993 
02994 
02995   
02996   
02997   else if ( kw_fast )
02998   {
02999     
03000     const Index  nza  = za.nelem();          
03001     const Index  nv   = f_mono.nelem();      
03002     const Index  np   = k_grid.nelem();      
03003     const Index  nabs = p_abs.nelem();       
03004   
03005     
03006     Vector z0(nabs), y0, t0(np);
03007   
03008     
03009     Vector hse_local( hse );
03010   
03011     
03012     hse_local[4] = 5;
03013     z0 = z_abs;
03014     hseCalc( z0, p_abs, t_abs, h2o_abs, r_geoid,  hse_local );
03015     hse_local[4] = hse[4];
03016   
03017     
03018     Matrix         abs1k, abs(nv,nabs);
03019     ArrayOfMatrix  abs_dummy;
03020     
03021     {
03022       Vector  t(t_abs);
03023       t += 1.;
03024       
03025       out1 << "  Calculating absorption for t_abs + 1K \n";
03026       out2 << "  ----- Messages from absCalc: --------\n";
03027       absCalc( abs1k, abs_dummy, tgs, f_mono, p_abs, t, n2_abs, h2o_abs, vmrs, 
03028                  lines_per_tg, lineshape, cont_description_names, 
03029                          cont_description_models, cont_description_parameters);
03030     }
03031     
03032     out1 << "  Calculating reference spectrum\n";
03033     out2 << "  ----- Messages from losCalc: --------\n";
03034     Los    los;
03035     Vector z_tan;
03036     losCalc( los, z_tan, z_plat, za, l_step, p_abs, z0, refr, refr_lfac, 
03037                                                refr_index, z_ground, r_geoid );
03038     out2 << "  -------------------------------------\n";
03039     out2 << "  ----- Messages from sourceCalc: -----\n";
03040     ArrayOfMatrix source, trans;
03041     sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
03042     out2 << "  -------------------------------------\n";
03043     out2 << "  ----- Messages from transCalc: ------\n";
03044     transCalc( trans, los, p_abs, abs0 );
03045     out2 << "  -------------------------------------\n";
03046     out2 << "  ----- Messages from yRte: -----------\n";
03047     yCalc( y0, emission, los, f_mono, y_space, source, trans, 
03048                                                           e_ground, t_ground );
03049     out2 << "  -------------------------------------\n";
03050   
03051     
03052     k.resize(nza*nv,np);
03053     k_names.resize(1);
03054     k_names[0] = "Temperature: with hydrostatic eq.";
03055     k_aux.resize(np,2);
03056     interpp( t0, p_abs, t_abs, k_grid ); 
03057     for ( Index ip=0; ip<np; ip++ )
03058     {
03059        k_aux(ip,0) = k_grid[ip];
03060        k_aux(ip,1) = t0[ip];
03061     }
03062   
03063     
03064     Matrix is;
03065     Vector lpabs, lgrid;
03066     p2grid( lpabs, p_abs );
03067     p2grid( lgrid, k_grid );
03068     grid2grid_index( is, lpabs, lgrid );
03069   
03070     
03071     
03072     Vector y, t(nabs), w, refr4t, z4t(nabs);
03073     Index  i1, iw, iv;
03074     
03075     for ( Index ip=0; ip<np; ip++ )
03076     {
03077       out1 << "  Doing altitude " << ip+1 << "/" << np << "\n";   
03078   
03079       
03080       
03081       grid2grid_weights( w, lpabs, Index(is(ip,0)), Index(is(ip,1)), 
03082                                                                    lgrid, ip );
03083       i1 = Index( is(ip,0) );    
03084 
03085       abs = abs0;       
03086       t   = t_abs;      
03087       for ( iw=i1; iw<=Index(is(ip,1)); iw++ )
03088       {
03089         t[iw] += w[iw-i1];
03090         for ( iv=0; iv<nv; iv++ )
03091           abs(iv,iw) = (1-w[iw-i1])*abs0(iv,iw) + w[iw-i1]*abs1k(iv,iw);
03092       }
03093   
03094       out2 << "  ----- Doing new refractive index ----\n";
03095       refrCalc ( refr4t, p_abs, t, h2o_abs, refr, refr_model );
03096       out2 << "  ----- Doing new hydrostatic eq. -----\n";
03097       z4t = z0;
03098       hseCalc( z4t, p_abs, t, h2o_abs, r_geoid,  hse );
03099       out2 << "  ----- Messages from losCalc: --------\n";
03100       losCalc( los, z_tan, z_plat, za, l_step, p_abs, z4t, refr, refr_lfac, 
03101                                                refr_index, z_ground, r_geoid );
03102       out2 << "  -------------------------------------\n";
03103       out2 << "  ----- Messages from sourceCalc: -----\n";
03104       ArrayOfMatrix source, trans;
03105       sourceCalc( source, emission, los, p_abs, t, f_mono );
03106       out2 << "  -------------------------------------\n";
03107       out2 << "  ----- Messages from transCalc: ------\n";
03108       transCalc( trans, los, p_abs, abs );
03109       out2 << "  -------------------------------------\n";
03110       out2 << "  ----- Messages from yRte: -----------\n";
03111       yCalc( y, emission, los, f_mono, y_space, source, trans, 
03112                                                           e_ground, t_ground );
03113       out2 << "  -------------------------------------\n";
03114   
03115       
03116       for ( iv=0; iv<nza*nv; iv++ )
03117         k(iv,ip) = y[iv] - y0[iv];
03118     }
03119   }
03120 
03121 
03122   
03123   
03124   else
03125   {
03126     
03127     const Index  nza  = za.nelem();          
03128     const Index  nv   = f_mono.nelem();      
03129     const Index  np   = k_grid.nelem();      
03130     const Index  nabs = p_abs.nelem();       
03131   
03132     
03133     Vector z0(nabs), y0, t0(np);
03134   
03135     
03136     Vector hse_local( hse );
03137   
03138     
03139     hse_local[4] = 5;
03140     z0 = z_abs; 
03141     hseCalc( z0, p_abs, t_abs, h2o_abs, r_geoid,  hse_local );
03142     hse_local[4] = hse[4];
03143   
03144     
03145     out1 << "  Calculating reference spectrum\n";
03146     out2 << "  ----- Messages from losCalc: --------\n";
03147     Los    los;
03148     Vector z_tan;
03149     losCalc( los, z_tan, z_plat, za, l_step, p_abs, z0, refr, refr_lfac, 
03150                                                refr_index, z_ground, r_geoid );
03151     out2 << "  -------------------------------------\n";
03152     out2 << "  ----- Messages from sourceCalc: -----\n";
03153     ArrayOfMatrix source, trans;
03154     sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
03155     out2 << "  -------------------------------------\n";
03156     out2 << "  ----- Messages from transCalc: ------\n";
03157     transCalc( trans, los, p_abs, abs0 );
03158     out2 << "  -------------------------------------\n";
03159     out2 << "  ----- Messages from yRte: -----------\n";
03160     yCalc( y0, emission, los, f_mono, y_space, source, trans, 
03161                                                           e_ground, t_ground );
03162     out2 << "  -------------------------------------\n";
03163   
03164     
03165     k.resize(nza*nv,np);
03166     k_names.resize(1);
03167     k_names[0] = "Temperature: with hydrostatic eq.";
03168     k_aux.resize(np,2);
03169     interpp( t0, p_abs, t_abs, k_grid ); 
03170     for ( Index ip=0; ip<np; ip++ )
03171     {
03172        k_aux(ip,0) = k_grid[ip];
03173        k_aux(ip,1) = t0[ip];
03174     }
03175   
03176     
03177     Matrix is;
03178     Vector lpabs, lgrid;
03179     p2grid( lpabs, p_abs );
03180     p2grid( lgrid, k_grid );
03181     grid2grid_index( is, lpabs, lgrid );
03182   
03183     
03184     
03185     Matrix         abs;
03186     ArrayOfMatrix  abs_dummy;
03187     Vector y, t(nabs), w, refr4t, z4t(nabs);
03188     Index  i1, iw, iv;
03189     
03190     for ( Index ip=0; ip<np; ip++ )
03191     {
03192       out1 << "  Doing altitude " << ip+1 << "/" << np << "\n";   
03193   
03194       
03195       grid2grid_weights( w, lpabs, Index(is(ip,0)), Index(is(ip,1)), 
03196                                                                    lgrid, ip );
03197       i1 = Index( is(ip,0) );    
03198 
03199       t = t_abs;        
03200       for ( iw=i1; iw<=Index(is(ip,1)); iw++ )
03201         t[iw] += w[iw-i1];
03202   
03203       out2 << "  ----- Messages from absCalc: --------\n";
03204       absCalc( abs, abs_dummy, tgs, f_mono, p_abs, t, n2_abs, h2o_abs, vmrs, 
03205                     lines_per_tg, lineshape, cont_description_names, 
03206                          cont_description_models, cont_description_parameters);
03207       out2 << "  ----- Doing new refractive index ----\n";
03208       refrCalc ( refr4t, p_abs, t, h2o_abs, refr, refr_model );
03209       out2 << "  ----- Doing new hydrostatic eq. -----\n";
03210       z4t = z0;
03211       hseCalc( z4t, p_abs, t, h2o_abs, r_geoid,  hse );
03212       out2 << "  ----- Messages from losCalc: --------\n";
03213       losCalc( los, z_tan, z_plat, za, l_step, p_abs, z4t, refr, refr_lfac, 
03214                                                    refr4t, z_ground, r_geoid );
03215       out2 << "  -------------------------------------\n";
03216       out2 << "  ----- Messages from sourceCalc: -----\n";
03217       ArrayOfMatrix source, trans;
03218       sourceCalc( source, emission, los, p_abs, t, f_mono );
03219       out2 << "  -------------------------------------\n";
03220       out2 << "  ----- Messages from transCalc: ------\n";
03221       transCalc( trans, los, p_abs, abs );
03222       out2 << "  -------------------------------------\n";
03223       out2 << "  ----- Messages from yRte: -----------\n";
03224       yCalc( y, emission, los, f_mono, y_space, source, trans, 
03225                                                           e_ground, t_ground );
03226       out2 << "  -------------------------------------\n";
03227   
03228       
03229       for ( iv=0; iv<nza*nv; iv++ )
03230         k(iv,ip) = y[iv] - y0[iv];
03231     }
03232   }
03233 }
03234 
03235 
03236 
03243 void kFrequencyOffSet (
03244                 Matrix&                      k,
03245                 ArrayOfString&               k_names,
03246                 Matrix&                      k_aux,
03247           const TagGroups&                   tgs,
03248           const Vector&                      f_mono,
03249           const Vector&                      p_abs,
03250           const Vector&                      t_abs,
03251           const Vector&                      n2_abs,
03252           const Vector&                      h2o_abs,
03253           const Matrix&                      vmrs,
03254           const ArrayOfArrayOfLineRecord&    lines_per_tg,
03255           const ArrayOfLineshapeSpec&        lineshape,
03256           const Vector&                      e_ground,
03257           const Index&                       emission,
03258           const ArrayOfString&               cont_description_names,
03259           const ArrayOfVector&               cont_description_parameters,
03260           const ArrayOfString&               cont_description_models,
03261           const Los&                         los,           
03262           const Numeric&                     t_ground,
03263           const Vector&                      y_space,
03264           const Vector&                      y,
03265           
03266           const Numeric&                     delta,
03267           const String&                      f_unit )
03268 {
03269   check_if_bool( emission, "emission" );
03270   check_lengths( p_abs, "p_abs", t_abs, "t_abs" );  
03271   check_lengths( p_abs, "p_abs", h2o_abs, "h2o_abs" );  
03272   check_lengths( p_abs, "p_abs", n2_abs, "n2_abs" );  
03273   check_length_ncol( p_abs, "p_abs", vmrs, "vmrs" );
03274   
03275   if ( any_ground(los.ground) )  
03276   {
03277     if ( t_ground <= 0 )
03278       throw runtime_error(
03279           "There are intersections with the ground, but the ground\n"
03280           "temperature is set to be <=0 (are dummy values used?).");
03281     if ( e_ground.nelem() != f_mono.nelem() )
03282       throw runtime_error(
03283           "There are intersections with the ground, but the frequency and\n"
03284           "ground emission vectors have different lengths (are dummy values\n"
03285           "used?).");
03286   }
03287   if ( emission ) 
03288     check_lengths( f_mono, "f_mono", y_space, "y_space" );
03289 
03290 
03291   
03292   
03293   Numeric scfac;
03294   
03295   if ( f_unit == "Hz" )
03296     scfac = 1.0;
03297   else if ( f_unit == "kHz" )
03298     scfac = 1000;
03299   else if ( f_unit == "MHz" )
03300     scfac = 1e6;
03301   else
03302     throw runtime_error("Allowed frequency units are \"Hz\", \"kHz\" and "
03303                                                                    "\"MHz\".");
03304 
03305 
03306   
03307   
03308   Index    nv     = f_mono.nelem();      
03309   Numeric  fdelta = scfac * delta;
03310   
03311   Vector f_dist(nv);
03312   
03313   for( Index ii=0; ii<nv; ii++ )
03314     { f_dist[ii] = f_mono[ii] + fdelta; }
03315 
03316 
03317   
03318   Matrix         abs;
03319   ArrayOfMatrix  abs_dummy;
03320   out2 << "  ----- Messages from absCalc: --------\n";
03321   absCalc( abs, abs_dummy, tgs, f_dist, p_abs, t_abs, n2_abs, h2o_abs, vmrs, 
03322                     lines_per_tg, lineshape, cont_description_names, 
03323                          cont_description_models, cont_description_parameters);
03324   ArrayOfMatrix source, trans;
03325   out2 << "  ----- Messages from sourceCalc: -----\n";
03326   sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
03327   out2 << "  -------------------------------------\n";
03328   out2 << "  ----- Messages from transCalc: ------\n";
03329   transCalc( trans, los, p_abs, abs );
03330   out2 << "  -------------------------------------\n";
03331   Vector y_new;
03332   out2 << "  ----- Messages from yRte: -----------\n";
03333   yCalc( y_new, emission, los, f_mono, y_space, source, trans, 
03334                                                          e_ground, t_ground );
03335   out2 << "  -------------------------------------\n";
03336 
03337   
03338   nv = y.nelem();
03339   k.resize( nv, 1 );
03340 
03341   
03342   for( Index ii=0; ii<nv; ii++ )
03343     { k(ii,0) = ( y_new[ii] - y[ii] ) / delta; }
03344 
03345   k_names.resize( 1 );
03346   k_names[0] = "Frequency: off-set";
03347   k_aux.resize( 1, 2 );
03348   k_aux = 0.0;                  
03349 }
03350 
03351 
03352 
03359 void kPointingOffSet(
03360                     Matrix&          k,
03361                     ArrayOfString&   k_names,
03362                     Matrix&          k_aux,
03363               const Numeric&         z_plat,
03364               const Vector&          za_pencil,
03365               const Numeric&         l_step,
03366               const Vector&          p_abs,
03367               const Vector&          z_abs,
03368               const Vector&          t_abs,
03369               const Vector&          f_mono,
03370               const Index&           refr,
03371               const Index&           refr_lfac,
03372               const Vector&          refr_index,
03373               const Numeric&         z_ground,
03374               const Numeric&         r_geoid,
03375               const Matrix&          abs,
03376               const Index&           emission,
03377               const Vector&          y_space,
03378               const Vector&          e_ground,
03379               const Numeric&         t_ground,
03380               const Vector&          y,
03381               const Numeric&         delta )
03382 {
03383   check_if_bool( emission, "emission" );
03384   check_if_bool( refr, "refr" );
03385   check_lengths( p_abs, "p_abs", t_abs, "t_abs" );  
03386   check_lengths( p_abs, "p_abs", z_abs, "z_abs" );  
03387   check_length_ncol( p_abs, "p_abs", abs, "abs" );
03388   check_length_nrow( f_mono, "f_mono", abs, "abs" );
03389   if ( emission ) 
03390     check_lengths( f_mono, "f_mono", y_space, "y_space" );
03391   if ( refr )
03392     check_lengths( p_abs, "p_abs", refr_index, "refr_index" );  
03393 
03394 
03395   
03396   
03397   Vector za_new( za_pencil );   
03398                                 
03399                                 
03400   za_new += delta;              
03401                                 
03402 
03403   out2 << "  ----- Messages from losCalc: --------\n";
03404   Los    los;
03405   Vector z_tan;
03406   losCalc( los, z_tan, z_plat, za_new, l_step, p_abs, z_abs, refr, refr_lfac, 
03407                                               refr_index, z_ground, r_geoid );
03408   out2 << "  -------------------------------------\n";
03409 
03410   ArrayOfMatrix source, trans;
03411   out2 << "  ----- Messages from sourceCalc: -----\n";
03412   sourceCalc( source, emission, los, p_abs, t_abs, f_mono );
03413   out2 << "  -------------------------------------\n";
03414   out2 << "  ----- Messages from transCalc: ------\n";
03415   transCalc( trans, los, p_abs, abs );
03416   out2 << "  -------------------------------------\n";
03417   Vector y_new;
03418   out2 << "  ----- Messages from yRte: -----------\n";
03419   yCalc( y_new, emission, los, f_mono, y_space, source, trans, 
03420                                                          e_ground, t_ground );
03421   out2 << "  -------------------------------------\n";
03422 
03423   
03424   const Index   nv = y.nelem();
03425   k.resize( nv, 1 );
03426 
03427   
03428   
03429   for( Index ii=0; ii<nv; ii++ )
03430     { k(ii,0) = ( y_new[ii] - y[ii] ) / delta; }
03431   
03432   
03433   
03434 
03435   k_names.resize( 1 );
03436   k_names[0] = "Pointing: off-set";
03437   k_aux.resize( 1, 2 );
03438   k_aux = 0.0;
03439 }
03440 
03441 
03442 
03449 void kEground(
03450                     Matrix&          k,
03451                     ArrayOfString&   k_names,
03452                     Matrix&          k_aux,
03453               const Vector&          za_pencil,
03454               const Vector&          f_mono,
03455               const Index&           emission,
03456               const Vector&          y_space,
03457               const Vector&          e_ground,
03458               const Numeric&         t_ground,
03459               const Los&             los,           
03460               const ArrayOfMatrix&   source,
03461               const ArrayOfMatrix&   trans,
03462               const Index&           single_e )
03463 {
03464   check_if_bool( emission, "emission" );                                      
03465   check_if_bool( emission, "single_e" );                                      
03466   check_lengths( f_mono, "f_mono", e_ground, "e_ground" );
03467   if ( los.p.nelem() != za_pencil.nelem() )
03468     throw runtime_error(
03469                "The number of zenith angles of *za* and *los* are different.");
03470   
03471   if ( los.p.nelem() != trans.nelem() )
03472     throw runtime_error(
03473             "The number of zenith angles of *los* and *trans* are different.");
03474   
03475   if ( emission )
03476   {
03477     if ( los.p.nelem() != source.nelem() )
03478       throw runtime_error(
03479            "The number of zenith angles of *los* and *source* are different.");
03480     check_length_nrow( f_mono, "f_mono", source[0], 
03481                                             "the source matrices (in source)");
03482   }
03483   
03484   if ( any_ground(los.ground) )  
03485   {
03486     if ( t_ground <= 0 )
03487       throw runtime_error(
03488           "There are intersections with the ground, but the ground\n"
03489           "temperature is set to be <=0 (are dummy values used?).");
03490     if ( e_ground.nelem() != f_mono.nelem() )
03491       throw runtime_error(
03492           "There are intersections with the ground, but the frequency and\n"
03493           "ground emission vectors have different lengths (are dummy values\n"
03494           "used?).");
03495   }
03496   
03497   if ( single_e ) 
03498   {
03499     for ( INDEX iv=1; iv<f_mono.nelem(); iv++ )
03500     {
03501       if ( e_ground[iv] != e_ground[0] )
03502         throw runtime_error(
03503           "A single ground emission value is assumed, but all values of\n"
03504           "*e_ground* are not the same.");
03505     }    
03506   }
03507 
03508 
03509   
03510   const Index  nza  = za_pencil.nelem();   
03511   const Index  nv   = f_mono.nelem();      
03512 
03513   
03514   Index iv, iza;
03515 
03516   
03517   Vector ksingle( nza*nv );
03518 
03519   
03520   if ( emission )
03521   {
03522     
03523     ksingle = 0.0;
03524 
03525     
03526     Vector bground(nv), y_in(nv), tr(nv);
03527 
03528     for ( iza=0; iza<nza; iza++ )
03529     {
03530       if ( los.ground[iza] )
03531       {
03532         
03533         planck( bground, f_mono, t_ground );
03534 
03535         
03536         rte( y_in, los.start[iza], los.ground[iza]-1, trans[iza], source[iza], 
03537                                                y_space, 0, e_ground, bground );
03538 
03539         
03540         tr = 1.0;
03541         bl_iterate( tr, los.ground[iza]-1, los.stop[iza]-1, trans[iza], nv );
03542 
03543         for ( iv=0; iv<nv; iv++ )
03544           ksingle[iza*nv+iv] = ( bground[iv] - y_in[iv] ) * tr[iv];      
03545       }
03546     }
03547   }
03548 
03549   
03550   else
03551   {
03552     Numeric a;
03553     for ( iv=0; iv<nv; iv++ )
03554     {
03555       a = 1 / ( 1 - e_ground[iv] );
03556       for ( iza=0; iza<nza; iza++ )
03557         ksingle[iza*nv+iv] = a;
03558     }
03559   }
03560 
03561   
03562   if ( single_e )
03563   {
03564     k_names.resize( 1 );
03565     k_names[0] = "Ground emission (single)";
03566     
03567     k.resize( nza*nv, 1 );
03568     k = ksingle;
03569     
03570     k_aux.resize( 1, 2 );
03571     k_aux(0,0) = 0;
03572     k_aux(0,1) = e_ground[0];    
03573   }
03574 
03575   
03576   else
03577   {
03578     k_names.resize( 1 );
03579     k_names[0] = "Ground emission";
03580     
03581     k.resize( nza*nv, nv );
03582     k = 0.0;
03583     k_aux.resize( nv, 2 );
03584     
03585     for ( iv=0; iv<nv; iv++ )
03586     {
03587       for ( iza=0; iza<nza; iza++ )
03588         k(iza*nv+iv,iv) = ksingle[iza*nv+iv];
03589       k_aux(iv,0) = 0;
03590       k_aux(iv,1) = e_ground[iv];    
03591     }
03592   }
03593 }
03594 
03595 
03596 
03603 void kCalibration(
03604                     Matrix&          k,
03605                     ArrayOfString&   k_names,
03606                     Matrix&          k_aux,
03607               const Vector&          y,
03608               const Vector&          f_mono,
03609               const Vector&          y0,
03610               const String&           )
03611 {
03612   check_lengths( f_mono, "f_mono", y0, "y0" );
03613 
03614   const Index   ny = y.nelem();
03615   const Index   nf = f_mono.nelem();
03616   const Index   nza = ny/nf;
03617 
03618   
03619   k.resize( ny, 1 );
03620 
03621   
03622   Index j,i,i0;
03623   for ( j=0; j<nza; j++ )    
03624   {
03625     i0 = j*nf;
03626     for ( i=0; i<nf; i++ )
03627       k(i0+i,0) = y[i0+i] - y0[i];
03628   }
03629 
03630   k_names.resize( 1 );
03631   k_names[0] = "Calibration: scaling";
03632   k_aux.resize( 1, 2 );
03633   k_aux = 0.0;          
03634 }
03635 
03636 
03637 
03648 void kManual(
03649                     Matrix&          k,
03650                     ArrayOfString&   k_names,
03651                     Matrix&          k_aux,
03652               const Vector&          y0,      
03653               const Vector&          y,
03654               const String&          name,
03655               const Numeric&         delta,
03656               const Numeric&         grid,
03657               const Numeric&         apriori )
03658 {
03659   check_lengths( y, "y", y0, "y0" );
03660 
03661   
03662   k.resize( y.nelem(), 1 );
03663 
03664   
03665   k = y;
03666   k -= y0;
03667   k /= delta;
03668 
03669   k_names.resize(1);
03670   k_names[0] = name;
03671   k_aux.resize(1,2);
03672   k_aux(0,0) = grid;
03673   k_aux(0,1) = apriori;
03674 }
03675 
03676 
03677 
03684 void kxInit (
03685                     Matrix&          kx,
03686                     ArrayOfString&   kx_names,
03687                     ArrayOfIndex&    kx_lengths,
03688                     Matrix&          kx_aux )
03689 {
03690   kx.resize(         0, 0 );
03691   kx_names.resize(   0    );
03692   kx_lengths.resize( 0    );
03693   kx_aux.resize(     0, 0 );
03694 }
03695 
03696 
03697 
03704 void kbInit (
03705                     Matrix&          kb,
03706                     ArrayOfString&   kb_names,
03707                     ArrayOfIndex&    kb_lengths,
03708                     Matrix&          kb_aux )
03709 {
03710   kxInit( kb, kb_names, kb_lengths, kb_aux );
03711 }
03712 
03713 
03714 
03721 void kxAppend (
03722                     Matrix&          kx,
03723                     ArrayOfString&   kx_names,
03724                     ArrayOfIndex&    kx_lengths,
03725                     Matrix&          kx_aux,
03726               const Matrix&          k,
03727               const ArrayOfString&   k_names,
03728               const Matrix&          k_aux )
03729 {
03730   k_append( kx, kx_names, kx_lengths, kx_aux, k, k_names, k_aux );
03731 }
03732 
03733 
03734 
03741 void kbAppend (
03742                     Matrix&          kb,
03743                     ArrayOfString&   kb_names,
03744                     ArrayOfIndex&    kb_lengths,
03745                     Matrix&          kb_aux,
03746               const Matrix&          k,
03747               const ArrayOfString&   k_names,
03748               const Matrix&          k_aux )
03749 {
03750   k_append( kb, kb_names, kb_lengths, kb_aux, k, k_names, k_aux );
03751 }
03752 
03753 
03754 
03761 void kxAllocate (
03762                     Matrix&          kx,
03763                     ArrayOfString&   kx_names,
03764                     ArrayOfIndex&    kx_lengths,
03765                     Matrix&          kx_aux,
03766               const Vector&          y,
03767               const String&          ,
03768               const Index&             ni,
03769               const Index&             nx )
03770 {
03771   const Index  ny = y.nelem();
03772 
03773   out2 << "  Allocates memory for a weighting function matrix having:\n" 
03774        << "    " << ny << " frequency points\n"
03775        << "    " << nx << " state variables\n"
03776        << "    " << ni << " retrieval identities\n";
03777 
03778   kx.resize(         ny, nx );
03779   kx_names.resize(   ni     );
03780   kx_lengths.resize( ni     );
03781   kx_aux.resize(     nx, 2  );
03782 
03783   for ( Index i=0; i<ni; i++ )
03784     kx_lengths[i] = 0;
03785 }
03786 
03787 
03788 
03795 void kbAllocate (
03796                     Matrix&          kb,
03797                     ArrayOfString&   kb_names,
03798                     ArrayOfIndex&    kb_lengths,
03799                     Matrix&          kb_aux,
03800               const Vector&          y,
03801               const String&          y_name,
03802               const Index&             ni,
03803               const Index&             nx )
03804 {
03805   kxAllocate( kb, kb_names, kb_lengths, kb_aux, y, y_name, ni, nx );
03806 }
03807 
03808 
03809 
03816 void kxPutInK (
03817                     Matrix&          kx,
03818                     ArrayOfString&   kx_names,
03819                     ArrayOfIndex&    kx_lengths,
03820                     Matrix&          kx_aux,
03821               const Matrix&          k,
03822               const ArrayOfString&   k_names,
03823               const Matrix&          k_aux )
03824 {
03825   const Index  ny  = kx.nrows();
03826   const Index  nx  = kx.ncols();
03827   const Index  ni  = kx_names.nelem();
03828   const Index  nx2 = k.ncols();
03829   const Index  ni2 = k_names.nelem();
03830 
03831   if ( ny != k.nrows() )
03832     throw runtime_error("The two WF matrices have different number of rows.");
03833 
03834   
03835   Index  ni1, nx1=0;
03836   for( ni1=0; ni1<ni && kx_lengths[ni1]>0; ni1++ )
03837     nx1 += kx_lengths[ni1];
03838   if ( ni1 == ni )
03839     throw runtime_error("All retrieval/error identity positions used.");
03840 
03841   
03842   if ( (ni1+ni2) > ni )
03843   {
03844     ostringstream os;
03845     os << "There is not room for so many retrieval/error identities.\n" 
03846        << (ni1+ni2)-ni << " positions are missing";
03847       throw runtime_error(os.str());
03848   }
03849   if ( (nx1+nx2) > nx )
03850   {
03851     ostringstream os;
03852     os << "The k-matrix does not fit in kx.\n" 
03853        << (nx1+nx2)-nx << " columns are missing";
03854       throw runtime_error(os.str());
03855   }
03856 
03857   out2 << "  Putting k in kx as\n" 
03858        << "    identity " << ni1 << " - " << ni1+ni2-1 << "\n"
03859        << "      column " << nx1 << " - " << nx1+nx2-1 << "\n";
03860  
03861   
03862   Index l = nx2/ni2;
03863 
03864   
03865   kx(     Range(joker),   Range(nx1,nx2) ) = k;
03866   kx_aux( Range(nx1,nx2), Range(joker)   ) = k_aux;
03867   
03868   for ( Index iri=0; iri<ni2; iri++ )
03869   {
03870     kx_names[ni1+iri]   = k_names[iri];
03871     kx_lengths[ni1+iri] = l;
03872   }   
03873 }
03874 
03875 
03876 
03883 void kbPutInK (
03884                     Matrix&          kb,
03885                     ArrayOfString&   kb_names,
03886                     ArrayOfIndex&    kb_lengths,
03887                     Matrix&          kb_aux,
03888               const Matrix&          k,
03889               const ArrayOfString&   k_names,
03890               const Matrix&          k_aux )
03891 {
03892   kxPutInK( kb, kb_names, kb_lengths, kb_aux, k, k_names, k_aux );
03893 }