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 }