14 #include "ioda/ObsSpace.h"
15 #include "ioda/ObsVector.h"
17 #include "oops/base/Variables.h"
18 #include "oops/util/IntSetParser.h"
19 #include "oops/util/Logger.h"
20 #include "oops/util/missingValues.h"
22 #include "ufo/GeoVaLs.h"
23 #include "ufo/ObsBias.h"
24 #include "ufo/ObsDiagnostics.h"
26 #include "rttov/wrapper/Profile.h"
27 #include "rttov/wrapper/RttovSafe.h"
62 rttov::RttovSafe & aRttov_,
const std::string CoefFileName,
63 const std::vector<int> channels_, std::size_t & nlevels,
64 std::vector<bool> & skip_profile) {
69 aRttov_.setFileCoef(CoefFileName);
70 aRttov_.options.setAddInterp(
true);
71 aRttov_.options.setVerboseWrapper(
true);
72 aRttov_.options.setCO2Data(
false);
73 aRttov_.options.setStoreRad(
true);
74 aRttov_.options.setDoCheckinput(
false);
75 aRttov_.options.setSwitchrad(
true);
78 aRttov_.options.setFastemVersion(6);
79 aRttov_.options.setSupplyFoamFraction(
false);
80 aRttov_.options.setApplyBandCorrection(
true);
85 aRttov_.loadInst(channels_);
87 catch (std::exception& e) {
88 oops::Log::error() <<
"Error loading instrument " << e.what() << std::endl;
91 oops::Log::info() <<
"ObsRadianceRTTOVCPP channels: " << channels_ << std::endl;
95 nlevels = geovals.
nlevs(
"air_temperature");
96 std::size_t nprofiles = odb_.nlocs();
97 std::size_t nchannels = aRttov_.getNchannels();
99 std::vector <rttov::Profile> profiles;
100 for (std::size_t p = 0; p < nprofiles; p++) {
102 profiles.push_back(aProfile);
106 std::vector<double> sunzen(nprofiles, 0.0);
111 std::vector<double> tmpvar1d(nlevels, 0.0);
112 std::vector<double> tmpvar2d(nprofiles, 0.0);
117 std::vector<std::vector<double>> tmpvar3d;
118 for (std::size_t i = 0; i < nlevels; ++i) {
119 geovals.
getAtLevel(tmpvar2d,
"air_pressure", i);
120 tmpvar3d.push_back(tmpvar2d);
122 for (std::size_t i = 0; i < nprofiles; ++i) {
123 for (std::size_t k = 0; k < nlevels; ++k) {
125 tmpvar1d[k] = tmpvar3d[k][i]*0.01;
127 profiles[i].setP(tmpvar1d);
130 std::vector<std::vector<double>>().swap(tmpvar3d);
133 std::vector<std::vector<double>> tmpvar3d_T;
134 for (std::size_t i = 0; i < nlevels; ++i) {
135 geovals.
getAtLevel(tmpvar2d,
"air_temperature", i);
136 tmpvar3d_T.push_back(tmpvar2d);
138 for (std::size_t i = 0; i < nprofiles; ++i) {
139 for (std::size_t k = 0; k < nlevels; ++k) {
140 tmpvar1d[k] = tmpvar3d_T[k][i];
142 profiles[i].setT(tmpvar1d);
144 std::vector<std::vector<double>>().swap(tmpvar3d_T);
147 std::vector<std::vector<double>> tmpvar3d_Q;
148 for (std::size_t i = 0; i < nlevels; ++i) {
149 geovals.
getAtLevel(tmpvar2d,
"specific_humidity", i);
150 tmpvar3d_Q.push_back(tmpvar2d);
152 for (std::size_t i = 0; i < nprofiles; ++i) {
153 profiles[i].setGasUnits(rttov::kg_per_kg);
154 for (std::size_t k = 0; k < nlevels; ++k) {
155 tmpvar1d[k] = tmpvar3d_Q[k][i];
157 profiles[i].setQ(tmpvar1d);
159 std::vector<std::vector<double>>().swap(tmpvar3d_Q);
163 std::vector<double> ps(nprofiles, 0.0);
164 std::vector<double> t2m(nprofiles, 0.0);
165 std::vector<double> q2m(nprofiles, 0.0);
166 std::vector<double> u10(nprofiles, 0.0);
167 std::vector<double> v10(nprofiles, 0.0);
168 std::vector<double> tskin(nprofiles, 0.0);
169 std::vector<int> landmask(nprofiles);
170 std::vector<double> seaice_frac(nprofiles, 0.0);
173 geovals.
get(ps,
"surface_pressure");
174 geovals.
get(t2m,
"surface_temperature");
175 geovals.
get(q2m,
"specific_humidity_at_two_meters_above_surface");
176 geovals.
get(u10,
"uwind_at_10m");
177 geovals.
get(v10,
"vwind_at_10m");
178 geovals.
get(tskin,
"skin_temperature");
179 geovals.
get(landmask,
"landmask");
180 geovals.
get(seaice_frac,
"seaice_fraction");
184 std::vector<double> satzen(nprofiles, 0.0);
185 std::vector<double> satazi(nprofiles, 0.0);
186 std::vector<double> sunazi(nprofiles, 0.0);
187 std::vector<double> lat(nprofiles, 0.0);
188 std::vector<double> lon(nprofiles, 0.0);
189 std::vector<double> elev(nprofiles, 0.0);
190 std::vector<util::DateTime> times(nprofiles);
192 odb_.get_db(
"MetaData",
"sensor_zenith_angle", satzen);
193 odb_.get_db(
"MetaData",
"sensor_azimuth_angle", satazi);
194 odb_.get_db(
"MetaData",
"solar_zenith_angle", sunzen);
195 odb_.get_db(
"MetaData",
"solar_azimuth_angle", sunazi);
196 odb_.get_db(
"MetaData",
"latitude", lat);
197 odb_.get_db(
"MetaData",
"longitude", lon);
198 odb_.get_db(
"MetaData",
"height_above_mean_sea_level", elev);
199 odb_.get_db(
"MetaData",
"datetime", times);
203 util::DateTime time1;
204 int year, month, day, hour, minute, second;
207 for (std::size_t i = 0; i < nprofiles; i++) {
208 profiles[i].setGasUnits(rttov::kg_per_kg);
212 if ( landmask[i] == 0 ) surftype=1;
213 if ( landmask[i] == 1 ) surftype=0;
214 if ( seaice_frac[i] >= 0.5 ) surftype=2;
215 profiles[i].setSurfGeom(lat[i], lon[i], 0.001*elev[i]);
218 time1.toYYYYMMDDhhmmss(year, month, day, hour, minute, second);
219 profiles[i].setDateTimes(year, month, day, hour, minute, second);
222 profiles[i].setSurfType(surftype, 0);
225 profiles[i].setS2m(ps[i]*0.01, t2m[i], q2m[i], u10[i], v10[i], 100000.);
229 profiles[i].setSkin(tskin[i], 35., 0., 0., 3.0, 5.0, 15.0, 0.1, 0.3, 0.);
231 profiles[i].setSkin(tskin[i], 35., 0., 0., 2.9, 3.4, 27.0, 0.0, 0.0, 0.);
233 profiles[i].setAngles(satzen[i], satazi[i], sunzen[i], sunazi[i]);
236 catch (std::exception& e) {
237 oops::Log::error() <<
"Error defining the profile data " << e.what() << std::endl;
243 aRttov_.setTheProfiles(profiles);
245 catch (exception& e) {
246 oops::Log::error() <<
"Error setting the profiles " << e.what() << std::endl;
252 double surfemisrefl[2][nprofiles][nchannels];
254 aRttov_.setSurfEmisRefl(
reinterpret_cast<double *
>(surfemisrefl));
259 for (
int i = 0; i < nprofiles; i++) {
260 for (
int j = 0; j < 2; j++) {
261 for (
int c = 0; c < nchannels; c++) surfemisrefl[j][i][c] = -1.;
271 catch (std::exception& e) {
272 oops::Log::error() <<
"Error running RTTOV K model " << e.what() << std::endl;
277 std::vector<double> var_k(nlevels, 0.0);
279 for (
size_t p = 0; p < nprofiles; p++) skip_profile.push_back(
false);
281 for (
size_t p = 0; p < nprofiles; p++) {
282 for (
size_t c = 0; c < nchannels; c++) {
283 var_k = aRttov_.getTK(p, c);
284 for (
size_t l = 0; l < nlevels; ++l)
if (std::isnan(var_k[l])) {skip_profile[p] =
true;}
286 var_k = aRttov_.getItemK(rttov::Q, p, c);
287 for (
size_t l = 0; l < nlevels; ++l)
if (std::isnan(var_k[l])) {skip_profile[p] =
true;}
291 oops::Log::trace() <<
"rttovcpp_interface done" << std::endl;
GeoVaLs: geophysical values at locations.
size_t nlevs(const std::string &var) const
Return number of levels for a specified variable.
void getAtLevel(std::vector< double > &, const std::string &, const int) const
Get GeoVaLs at a specified level.
void get(std::vector< double > &, const std::string &var) const
Get 2D GeoVaLs for variable var (fails for 3D GeoVaLs)
void rttovcpp_interface(const GeoVaLs &geovals, const ioda::ObsSpace &odb_, rttov::RttovSafe &aRttov_, const std::string CoefFileName, const std::vector< int > channels_, std::size_t &nlevels, std::vector< bool > &skip_profile)
Set one single RttovSafe object for a single sensor.