00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00040
00041
00042
00043
00044 #include <cmath>
00045 #include "agenda_class.h"
00046 #include "arts.h"
00047 #include "check_input.h"
00048 #include "matpackIII.h"
00049 #include "messages.h"
00050 #include "special_interp.h"
00051 #include "absorption.h"
00052 #include "abs_species_tags.h"
00053 #include "gridded_fields.h"
00054 #include "interpolation.h"
00055 #include "xml_io.h"
00056
00057 extern const Index GFIELD3_P_GRID;
00058 extern const Index GFIELD3_LAT_GRID;
00059 extern const Index GFIELD3_LON_GRID;
00060 extern const Index GFIELD4_FIELD_NAMES;
00061 extern const Index GFIELD4_P_GRID;
00062 extern const Index GFIELD4_LAT_GRID;
00063 extern const Index GFIELD4_LON_GRID;
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 void atm_fields_compactFromMatrix(
00075 GField4& af,
00076
00077 const Index& atmosphere_dim,
00078
00079 const Matrix& im,
00080
00081 const ArrayOfString& field_names )
00082 {
00083 if (1!=atmosphere_dim)
00084 {
00085 ostringstream os;
00086 os << "Atmospheric dimension must be one.";
00087 throw runtime_error( os.str() );
00088 }
00089
00090 const Index np = im.nrows();
00091 const Index nf = im.ncols()-1;
00092
00093 if (field_names.nelem()!=nf)
00094 {
00095 ostringstream os;
00096 os << "Cannot copy Matrix.\n"
00097 << "*field_names* must have one element less than there are\n"
00098 << "matrix columns.";
00099 throw runtime_error( os.str() );
00100 }
00101
00102
00103
00104 af.set_grid(GFIELD4_FIELD_NAMES, field_names);
00105
00106 af.set_grid(GFIELD4_P_GRID, im(Range(joker),0));
00107
00108 af.set_grid(GFIELD4_LAT_GRID, Vector());
00109 af.set_grid(GFIELD4_LON_GRID, Vector());
00110
00111 af.resize(nf,np,1,1);
00112 af(Range(joker),Range(joker),0,0) = transpose(im(Range(joker),Range(1,nf)));
00113 }
00114
00115
00116
00117
00118
00119 void atm_fields_compactAddConstant(
00120 GField4& af,
00121
00122 const String& name,
00123 const Numeric& value)
00124 {
00125
00126 const Index nf = af.get_string_grid(GFIELD4_FIELD_NAMES).nelem();
00127
00128 if (0==nf)
00129 {
00130 ostringstream os;
00131 os << "The *atm_fields_compact* must already contain at least one field,\n"
00132 << "so that we can infer the dimensions from that.";
00133 throw runtime_error( os.str() );
00134 }
00135
00136
00137 af.get_string_grid(GFIELD4_FIELD_NAMES).push_back(name);
00138
00139
00140 const Tensor4 dummy = af;
00141
00142
00143 af.resize( nf+1, dummy.npages(), dummy.nrows(), dummy.ncols() );
00144
00145
00146 af( Range(0,nf), Range(joker), Range(joker), Range(joker) ) = dummy;
00147
00148
00149 af( nf, Range(joker), Range(joker), Range(joker) ) = value;
00150 }
00151
00152
00153
00154 void batch_atm_fields_compactFromArrayOfMatrix(
00155 ArrayOfGField4& batch_atm_fields_compact,
00156
00157 const Index& atmosphere_dim,
00158
00159 const ArrayOfMatrix& am,
00160
00161 const ArrayOfString& field_names,
00162 const ArrayOfString& extra_field_names,
00163 const Vector& extra_field_values)
00164 {
00165 const Index amnelem = am.nelem();
00166
00167
00168
00169
00170
00171
00172 if (extra_field_names.nelem() != extra_field_values.nelem())
00173 {
00174 ostringstream os;
00175 os << "The keyword arguments extra_field_names and\n"
00176 << "extra_field_values must have matching dimensions.";
00177 throw runtime_error( os.str() );
00178 }
00179
00180
00181 batch_atm_fields_compact.resize(amnelem);
00182
00183
00184 #pragma omp parallel
00185 #pragma omp for
00186 for (Index i=0; i<amnelem; ++i)
00187 {
00188
00189
00190 try
00191 {
00192 atm_fields_compactFromMatrix(batch_atm_fields_compact[i],
00193 atmosphere_dim,
00194 am[i],
00195 field_names);
00196
00197 for (Index j=0; j<extra_field_names.nelem(); ++j)
00198 atm_fields_compactAddConstant(batch_atm_fields_compact[i],
00199 extra_field_names[j],
00200 extra_field_values[j]);
00201 }
00202 catch (runtime_error e)
00203 {
00204 exit_or_rethrow(e.what());
00205 }
00206 }
00207 }
00208
00209
00210
00211
00212 void AtmFieldsFromCompact(
00213 Vector& p_grid,
00214 Vector& lat_grid,
00215 Vector& lon_grid,
00216 Tensor3& t_field,
00217 Tensor3& z_field,
00218 Tensor4& vmr_field,
00219
00220 const ArrayOfArrayOfSpeciesTag& abs_species,
00221 const GField4& atm_fields_compact,
00222 const Index& atmosphere_dim )
00223 {
00224
00225 const GField4& c = atm_fields_compact;
00226
00227
00228
00229 chk_atm_grids(atmosphere_dim,
00230 c.get_numeric_grid(GFIELD4_P_GRID),
00231 c.get_numeric_grid(GFIELD4_LAT_GRID),
00232 c.get_numeric_grid(GFIELD4_LON_GRID));
00233
00234 const Index nf = c.get_grid_size(GFIELD4_FIELD_NAMES);
00235 const Index np = c.get_grid_size(GFIELD4_P_GRID);
00236 const Index nlat = c.get_grid_size(GFIELD4_LAT_GRID);
00237 const Index nlon = c.get_grid_size(GFIELD4_LON_GRID);
00238
00239
00240 p_grid = c.get_numeric_grid(GFIELD4_P_GRID);
00241 lat_grid = c.get_numeric_grid(GFIELD4_LAT_GRID);
00242 lon_grid = c.get_numeric_grid(GFIELD4_LON_GRID);
00243
00244
00245
00246
00247
00248 const Index ns = nf-2;
00249
00250
00251 if (ns<1)
00252 {
00253 ostringstream os;
00254 os << "There must be at least three fields in *atm_fields_compact*.\n"
00255 << "T, z, and at least one VMR.";
00256 throw runtime_error( os.str() );
00257 }
00258
00259
00260 if (c.get_string_grid(GFIELD4_FIELD_NAMES)[0] != "T")
00261 {
00262 ostringstream os;
00263 os << "The first field must be \"T\", but it is:"
00264 << c.get_string_grid(GFIELD4_FIELD_NAMES)[0];
00265 throw runtime_error( os.str() );
00266 }
00267
00268
00269 if (c.get_string_grid(GFIELD4_FIELD_NAMES)[1] != "z")
00270 {
00271 ostringstream os;
00272 os << "The second field must be \"z\"*, but it is:"
00273 << c.get_string_grid(GFIELD4_FIELD_NAMES)[1];
00274 throw runtime_error( os.str() );
00275 }
00276
00277
00278 for (Index i=0; i<ns; ++i)
00279 {
00280 const String tf_species = c.get_string_grid(GFIELD4_FIELD_NAMES)[2+i];
00281
00282
00283 extern const Array<SpeciesRecord> species_data;
00284 const String as_species = species_data[abs_species[i][0].Species()].Name();
00285
00286
00287 if (tf_species != as_species)
00288 {
00289 ostringstream os;
00290 os << "Field name not valid: "
00291 << tf_species << "\n"
00292 << "Based on *abs_species*, the field name should be: "
00293 << as_species;
00294 throw runtime_error( os.str() );
00295 }
00296 }
00297
00298
00299 t_field.resize(np,nlat,nlon);
00300 t_field = c(0,Range(joker),Range(joker),Range(joker));
00301
00302
00303 z_field.resize(np,nlat,nlon);
00304 z_field = c(1,Range(joker),Range(joker),Range(joker));
00305
00306
00307 vmr_field.resize(ns,np,nlat,nlon);
00308 vmr_field = c(Range(2,ns),Range(joker),Range(joker),Range(joker));
00309 }
00310
00311
00312
00313 void AtmosphereSet1D(
00314
00315 Index& atmosphere_dim,
00316 Vector& lat_grid,
00317 Vector& lon_grid )
00318 {
00319 out2 << " Sets the atmospheric dimensionality to 1.\n";
00320 out3 << " atmosphere_dim = 1\n";
00321 out3 << " lat_grid is set to be an empty vector\n";
00322 out3 << " lon_grid is set to be an empty vector\n";
00323 atmosphere_dim = 1;
00324 lat_grid.resize(0);
00325 lon_grid.resize(0);
00326
00327 }
00328
00329
00330
00331 void AtmosphereSet2D(
00332
00333 Index& atmosphere_dim,
00334 Vector& lon_grid,
00335 Numeric& lat_1d,
00336 Numeric& meridian_angle_1d )
00337 {
00338 out2 << " Sets the atmospheric dimensionality to 2.\n";
00339 out3 << " atmosphere_dim = 2\n";
00340 out3 << " lon_grid is set to be an empty vector\n";
00341 out3 << " lat_1d = -999\n";
00342 out3 << " meridian_angle_1d = -999\n";
00343 atmosphere_dim = 2;
00344 lon_grid.resize(0);
00345 lat_1d = -999;
00346 meridian_angle_1d = -999;
00347 }
00348
00349
00350
00351 void AtmosphereSet3D(
00352
00353 Index& atmosphere_dim,
00354 Numeric& latitude_1d,
00355 Numeric& meridian_angle_1d )
00356 {
00357 out2 << " Sets the atmospheric dimensionality to 3.\n";
00358 out3 << " atmosphere_dim = 3\n";
00359 out3 << " lat_1d = -999\n";
00360 out3 << " meridian_angle_1d = -999\n";
00361 atmosphere_dim = 3;
00362 latitude_1d = -999;
00363 meridian_angle_1d = -999;
00364 }
00365
00366
00367
00368
00369 void AtmFieldsCalc(
00370 Tensor3& t_field,
00371 Tensor3& z_field,
00372 Tensor4& vmr_field,
00373
00374 const Vector& p_grid,
00375 const Vector& lat_grid,
00376 const Vector& lon_grid,
00377 const GField3& t_field_raw,
00378 const GField3& z_field_raw,
00379 const ArrayOfGField3& vmr_field_raw,
00380 const Index& atmosphere_dim
00381 )
00382 {
00383 const ConstVectorView tfr_p_grid = t_field_raw.get_numeric_grid(GFIELD3_P_GRID);
00384 const ConstVectorView tfr_lat_grid = t_field_raw.get_numeric_grid(GFIELD3_LAT_GRID);
00385 const ConstVectorView tfr_lon_grid = t_field_raw.get_numeric_grid(GFIELD3_LON_GRID);
00386 const ConstVectorView zfr_p_grid = z_field_raw.get_numeric_grid(GFIELD3_P_GRID);
00387 const ConstVectorView zfr_lat_grid = z_field_raw.get_numeric_grid(GFIELD3_LAT_GRID);
00388 const ConstVectorView zfr_lon_grid = z_field_raw.get_numeric_grid(GFIELD3_LON_GRID);
00389
00390
00391
00392
00393 chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
00394 chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 if ( atmosphere_dim == 1)
00405 {
00406 if( !( tfr_lat_grid.nelem() == 1 &&
00407 tfr_lon_grid.nelem() == 1 ))
00408 throw runtime_error(
00409 "Temperature data (T_field) has wrong dimension "
00410 "(2D or 3D).\n"
00411 );
00412
00413 if( !( zfr_lat_grid.nelem() == 1 &&
00414 zfr_lon_grid.nelem() == 1 ))
00415 throw runtime_error(
00416 "Altitude data (z_field) has wrong dimension "
00417 "(2D or 3D).\n"
00418 );
00419
00420
00421 t_field.resize(p_grid.nelem(), 1, 1);
00422 z_field.resize(p_grid.nelem(), 1, 1);
00423 vmr_field.resize(vmr_field_raw.nelem(), p_grid.nelem(), 1, 1);
00424
00425
00426
00427 ArrayOfGridPos gp_p(p_grid.nelem());
00428
00429
00430
00431
00432 p2gridpos( gp_p, tfr_p_grid, p_grid );
00433
00434
00435 Matrix itw(p_grid.nelem(), 2);
00436
00437 interpweights( itw, gp_p);
00438
00439
00440 interp( t_field(joker, 0, 0), itw,
00441 t_field_raw(joker, 0, 0), gp_p);
00442
00443
00444
00445
00446
00447 p2gridpos( gp_p, zfr_p_grid, p_grid );
00448
00449
00450 interpweights( itw, gp_p );
00451
00452
00453 interp( z_field(joker, 0, 0), itw,
00454 z_field_raw(joker, 0, 0), gp_p);
00455
00456
00457
00458
00459 for (Index gas_i = 0; gas_i < vmr_field_raw.nelem(); gas_i++)
00460 {
00461 if( !( vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID).nelem() == 1 &&
00462 vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID).nelem() == 1 ))
00463 {
00464 ostringstream os;
00465 os << "VMR data of the " << gas_i << "th species has "
00466 << "wrong dimension (2D or 3D). \n";
00467 throw runtime_error( os.str() );
00468 }
00469
00470
00471 p2gridpos(gp_p, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID), p_grid);
00472
00473
00474 interpweights( itw, gp_p);
00475
00476
00477 interp( vmr_field(gas_i, joker, 0, 0),
00478 itw, vmr_field_raw[gas_i](joker, 0, 0), gp_p);
00479 }
00480
00481 }
00482
00483
00484 else if(atmosphere_dim == 2)
00485 {
00486 if( tfr_lat_grid.nelem() == 1 &&
00487 tfr_lon_grid.nelem() == 1 )
00488 throw runtime_error(
00489 "Raw data has wrong dimension (1D). "
00490 "You have to use \n"
00491 "AtmFieldsCalcExpand1D instead of AtmFieldsCalc."
00492 );
00493
00494
00495 t_field.resize(p_grid.nelem(), lat_grid.nelem(), 1);
00496 z_field.resize(p_grid.nelem(), lat_grid.nelem(), 1);
00497 vmr_field.resize(vmr_field_raw.nelem(), p_grid.nelem(), lat_grid.nelem(),
00498 1);
00499
00500
00501
00502 ArrayOfGridPos gp_p(p_grid.nelem());
00503 ArrayOfGridPos gp_lat(lat_grid.nelem());
00504
00505
00506
00507
00508 p2gridpos( gp_p, tfr_p_grid, p_grid );
00509 gridpos( gp_lat, tfr_lat_grid, lat_grid );
00510
00511
00512 Tensor3 itw(p_grid.nelem(), lat_grid.nelem(), 4);
00513
00514 interpweights( itw, gp_p, gp_lat);
00515
00516
00517 interp( t_field(joker, joker, 0 ), itw,
00518 t_field_raw(joker, joker, 0), gp_p, gp_lat);
00519
00520
00521
00522
00523 p2gridpos( gp_p, zfr_p_grid, p_grid );
00524 gridpos( gp_lat, zfr_lat_grid, lat_grid );
00525
00526
00527 interpweights( itw, gp_p, gp_lat);
00528
00529
00530 interp( z_field(joker, joker, 0), itw,
00531 z_field_raw(joker, joker, 0), gp_p, gp_lat);
00532
00533
00534
00535
00536 for (Index gas_i = 0; gas_i < vmr_field_raw.nelem(); gas_i++)
00537 {
00538
00539 p2gridpos(gp_p, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID), p_grid);
00540 gridpos(gp_lat, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID), lat_grid);
00541
00542
00543 interpweights( itw, gp_p, gp_lat);
00544
00545
00546 interp( vmr_field(gas_i, joker, joker, 0),
00547 itw, vmr_field_raw[gas_i](joker, joker, 0),
00548 gp_p, gp_lat);
00549 }
00550 }
00551
00552
00553
00554 else
00555 {
00556 if( tfr_lat_grid.nelem() == 1 &&
00557 tfr_lon_grid.nelem() == 1 )
00558 throw runtime_error(
00559 "Raw data has wrong dimension. You have to use \n"
00560 "AtmFieldsCalcExpand1D instead of AtmFieldsCalc."
00561 );
00562
00563
00564 t_field.resize(p_grid.nelem(), lat_grid.nelem(), lon_grid.nelem());
00565 z_field.resize(p_grid.nelem(), lat_grid.nelem(), lon_grid.nelem());
00566 vmr_field.resize(vmr_field_raw.nelem(), p_grid.nelem(), lat_grid.nelem(),
00567 lon_grid.nelem());
00568
00569
00570
00571 ArrayOfGridPos gp_p(p_grid.nelem());
00572 ArrayOfGridPos gp_lat(lat_grid.nelem());
00573 ArrayOfGridPos gp_lon(lon_grid.nelem());
00574
00575
00576
00577
00578
00579 p2gridpos( gp_p, tfr_p_grid, p_grid );
00580 gridpos( gp_lat, tfr_lat_grid, lat_grid );
00581 gridpos( gp_lon, tfr_lon_grid, lon_grid );
00582
00583
00584 Tensor4 itw(p_grid.nelem(), lat_grid.nelem(), lon_grid.nelem(), 8);
00585
00586 interpweights( itw, gp_p, gp_lat, gp_lon );
00587
00588
00589 interp( t_field, itw, t_field_raw, gp_p, gp_lat, gp_lon);
00590
00591
00592
00593
00594
00595 p2gridpos( gp_p, zfr_p_grid, p_grid );
00596 gridpos( gp_lat, zfr_lat_grid, lat_grid );
00597 gridpos( gp_lon, zfr_lon_grid, lon_grid );
00598
00599
00600 interpweights( itw, gp_p, gp_lat, gp_lon );
00601
00602
00603 interp( z_field, itw, z_field_raw, gp_p, gp_lat, gp_lon);
00604
00605
00606
00607
00608 for (Index gas_i = 0; gas_i < vmr_field_raw.nelem(); gas_i++)
00609 {
00610
00611 p2gridpos(gp_p, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID), p_grid);
00612 gridpos(gp_lat, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID), lat_grid);
00613 gridpos(gp_lon, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID), lon_grid);
00614
00615
00616 interpweights( itw, gp_p, gp_lat, gp_lon );
00617
00618
00619 interp( vmr_field(gas_i, joker, joker, joker),
00620 itw, vmr_field_raw[gas_i], gp_p, gp_lat, gp_lon);
00621 }
00622 }
00623 }
00624
00625
00626
00627 void AtmFieldsCalcExpand1D(
00628 Tensor3& t_field,
00629 Tensor3& z_field,
00630 Tensor4& vmr_field,
00631 const Vector& p_grid,
00632 const Vector& lat_grid,
00633 const Vector& lon_grid,
00634 const GField3& t_field_raw,
00635 const GField3& z_field_raw,
00636 const ArrayOfGField3& vmr_field_raw,
00637 const Index& atmosphere_dim )
00638 {
00639 chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
00640 chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
00641
00642 if( atmosphere_dim == 1 )
00643 { throw runtime_error(
00644 "This function is intended for 2D and 3D. For 1D, use *AtmFieldsCalc*.");}
00645
00646
00647 Vector vempty(0);
00648 Tensor3 t_temp, z_temp;
00649 Tensor4 vmr_temp;
00650 AtmFieldsCalc( t_temp, z_temp, vmr_temp, p_grid, vempty, vempty,
00651 t_field_raw, z_field_raw, vmr_field_raw, 1 );
00652
00653
00654 const Index np = p_grid.nelem();
00655 const Index nlat = lat_grid.nelem();
00656 Index nlon = lon_grid.nelem();
00657 if( atmosphere_dim == 2 )
00658 { nlon = 1; }
00659 const Index nspecies = vmr_temp.nbooks();
00660
00661 assert( t_temp.npages() == np );
00662
00663 t_field.resize( np, nlat, nlon );
00664 z_field.resize( np, nlat, nlon );
00665 vmr_field.resize( nspecies, np, nlat, nlon );
00666
00667 for( Index ilon=0; ilon<nlon; ilon++ )
00668 {
00669 for( Index ilat=0; ilat<nlat; ilat++ )
00670 {
00671 for( Index ip=0; ip<np; ip++ )
00672 {
00673 t_field(ip,ilat,ilon) = t_temp(ip,0,0);
00674 z_field(ip,ilat,ilon) = z_temp(ip,0,0);
00675 for( Index is=0; is<nspecies; is++ )
00676 { vmr_field(is,ip,ilat,ilon) = vmr_temp(is,ip,0,0); }
00677 }
00678 }
00679 }
00680 }
00681
00682
00683
00684
00685 void AtmFieldsRefinePgrid(
00686 Vector& p_grid,
00687 Tensor3& t_field,
00688 Tensor3& z_field,
00689 Tensor4& vmr_field,
00690
00691 const Vector& lat_grid,
00692 const Vector& lon_grid,
00693 const Index& atmosphere_dim,
00694
00695 const Numeric& p_step)
00696 {
00697
00698
00699
00700
00701
00702
00703
00704
00705 chk_atm_grids(atmosphere_dim, p_grid, lat_grid, lon_grid);
00706
00707
00708 chk_atm_field("t_field", t_field, atmosphere_dim,
00709 p_grid, lat_grid, lon_grid);
00710
00711
00712 chk_atm_field("z_field", z_field, atmosphere_dim,
00713 p_grid, lat_grid, lon_grid);
00714
00715
00716 chk_atm_field("vmr_field", vmr_field, atmosphere_dim,
00717 vmr_field.nbooks(), p_grid, lat_grid, lon_grid);
00718
00719
00720 if ( p_step <= 0 )
00721 {
00722 ostringstream os;
00723 os << "The keyword argument p_step must be >0.";
00724 throw runtime_error( os.str() );
00725 }
00726
00727
00728
00729
00730 Vector log_p_grid(p_grid.nelem());
00731 transform(log_p_grid, log, p_grid);
00732
00733
00734
00735
00736
00737
00738
00739 ArrayOfNumeric log_abs_p_a;
00740
00741
00742
00743
00744
00745
00746
00747 log_abs_p_a.push_back(log_p_grid[0]);
00748
00749 for (Index i=1; i<log_p_grid.nelem(); ++i)
00750 {
00751 const Numeric dp = log_p_grid[i-1] - log_p_grid[i];
00752
00753 const Numeric dp_by_p_step = dp/p_step;
00754
00755
00756
00757 const Index n = (Index) ceil(dp_by_p_step);
00758
00759
00760
00761
00762
00763 const Numeric ddp = dp/(Numeric)n;
00764
00765
00766 for (Index j=1; j<=n; ++j)
00767 log_abs_p_a.push_back(log_p_grid[i-1] - (Numeric)j*ddp);
00768 }
00769
00770
00771
00772 Vector log_abs_p(log_abs_p_a.nelem());
00773 for (Index i=0; i<log_abs_p_a.nelem(); ++i)
00774 log_abs_p[i] = log_abs_p_a[i];
00775
00776
00777 Vector abs_p(log_abs_p.nelem());
00778 transform(abs_p, exp, log_abs_p);
00779
00780
00781
00782
00783
00784
00785 ArrayOfGridPos gp(log_abs_p.nelem());
00786 gridpos(gp, log_p_grid, log_abs_p);
00787
00788
00789 Matrix itw(gp.nelem(),2);
00790 interpweights(itw,gp);
00791
00792
00793 Index nlat = lat_grid.nelem();
00794 Index nlon = lon_grid.nelem();
00795
00796
00797
00798 if (0 == nlat) nlat = 1;
00799 if (0 == nlon) nlon = 1;
00800
00801
00802 Tensor3 abs_t(log_abs_p.nelem(), nlat, nlon);
00803 Tensor3 abs_z(log_abs_p.nelem(), nlat, nlon);
00804 Tensor4 abs_vmr(vmr_field.nbooks(),
00805 log_abs_p.nelem(), nlat, nlon);
00806
00807 for (Index ilat=0; ilat<nlat; ++ilat)
00808 for (Index ilon=0; ilon<nlon; ++ilon)
00809 {
00810 interp(abs_t(joker, ilat, ilon),
00811 itw,
00812 t_field(joker, ilat, ilon),
00813 gp);
00814
00815 interp(abs_z(joker, ilat, ilon),
00816 itw,
00817 z_field(joker, ilat, ilon),
00818 gp);
00819
00820 for (Index ivmr=0; ivmr<vmr_field.nbooks(); ++ivmr)
00821 interp(abs_vmr(ivmr, joker, ilat, ilon),
00822 itw,
00823 vmr_field(ivmr, joker, ilat, ilon),
00824 gp);
00825 }
00826
00827
00828
00829 p_grid = abs_p;
00830 t_field = abs_t;
00831 z_field = abs_z;
00832 vmr_field = abs_vmr;
00833 }
00834
00835
00836
00837
00838 void AtmRawRead(
00839 GField3& t_field_raw,
00840 GField3& z_field_raw,
00841 ArrayOfGField3& vmr_field_raw,
00842
00843 const ArrayOfArrayOfSpeciesTag& abs_species,
00844
00845 const String& basename)
00846 {
00847
00848 String file_name = basename + ".t.xml";
00849 xml_read_from_file( file_name, t_field_raw);
00850
00851 out3 << "Temperature field read from file: " << file_name << "\n";
00852
00853
00854 file_name = basename + ".z.xml";
00855 xml_read_from_file( file_name, z_field_raw);
00856
00857 out3 << "Altitude field read from file: " << file_name << "\n";
00858
00859
00860
00861
00862 extern const Array<SpeciesRecord> species_data;
00863
00864
00865 for ( Index i=0; i<abs_species.nelem(); i ++)
00866 {
00867
00868 file_name =
00869 basename + "." +
00870 species_data[abs_species[i][0].Species()].Name() + ".xml";
00871
00872
00873 GField3 vmr_field_data;
00874 vmr_field_raw.push_back(vmr_field_data);
00875
00876
00877 xml_read_from_file( file_name, vmr_field_raw[vmr_field_raw.nelem()-1]);
00878
00879
00880 out3 << " " << species_data[abs_species[i][0].Species()].Name()
00881 << " profile read from file: " << file_name << "\n";
00882 }
00883 }
00884
00885
00886
00887
00888 void InterpAtmFieldToRteGps(
00889 Numeric& outvalue,
00890 const Index& atmosphere_dim,
00891 const Vector& p_grid,
00892 const Vector& lat_grid,
00893 const Vector& lon_grid,
00894 const GridPos& rte_gp_p,
00895 const GridPos& rte_gp_lat,
00896 const GridPos& rte_gp_lon,
00897 const Tensor3& field)
00898 {
00899
00900 outvalue = interp_atmfield_by_gp( atmosphere_dim, p_grid, lat_grid,
00901 lon_grid, field, rte_gp_p, rte_gp_lat, rte_gp_lon );
00902
00903 out3 << " Result = " << outvalue << "\n";
00904 }
00905
00906