16 static TransformMaker<Cal_RelativeHumidity>
28 oops::Log::trace() <<
" --> Retrieve Relative humidity"
30 oops::Log::trace() <<
" --> method: " <<
method() << std::endl;
31 oops::Log::trace() <<
" --> formulation: " <<
formulation() << std::endl;
32 oops::Log::trace() <<
" --> obsName: " <<
obsName() << std::endl;
69 const size_t nlocs_ =
obsdb_.nlocs();
75 float Q_sub_s_ice, Q_sub_s_w;
76 float pressure, temperature, dewPoint;
77 std::vector<float> airTemperature;
78 std::vector<float> dewPointTemperature;
79 std::vector<float> relativeHumidity;
80 std::vector<float> airPressure;
81 bool surfaceData =
true;
82 bool hasBeenUpdated =
false;
96 if (
obsdb_.has(
"ObsValue",
"pressure_surface") &&
97 obsdb_.has(
"ObsValue",
"air_temperature_surface") &&
98 obsdb_.has(
"ObsValue",
"dew_point_temperature_surface")) {
102 airTemperature,
true);
104 dewPointTemperature,
true);
111 airTemperature,
true);
113 dewPointTemperature,
true);
118 if (relativeHumidity.empty()) {
124 if (!oops::allVectorsSameNonZeroSize(airPressure, airTemperature, dewPointTemperature)) {
125 oops::Log::warning() <<
"Vector sizes: "
126 << oops::listOfVectorSizes(airPressure, airTemperature,
129 throw eckit::BadValue(
"At least one vector is the wrong size or empty out of "
130 "P, T and Td", Here());
137 auto evaluateSatSpecHumidity = [&](
float temp_1,
float temp_2){
138 float e_sub_s_w, e_sub_s_ice;
162 for (ioda::ObsSpace::RecIdxIter irec =
obsdb_.recidx_begin();
163 irec !=
obsdb_.recidx_end(); ++irec) {
164 const std::vector<std::size_t> &rSort =
obsdb_.recidx_vector(irec);
167 for (
size_t iloc : rSort) {
169 if (!apply[iloc])
continue;
172 pressure = airPressure[iloc];
173 temperature = airTemperature[iloc];
174 dewPoint = dewPointTemperature[iloc];
186 pressure <= 1.0)
continue;
189 if (dewPoint > 1.0) {
191 evaluateSatSpecHumidity(dewPoint, temperature);
195 if (Q_sub_s_w > 0 && Q_sub_s_ice > 0) {
196 relativeHumidity[iloc] = (Q_sub_s_w / Q_sub_s_ice) * 100.0;
198 relativeHumidity[iloc] = std::min(100.0f, relativeHumidity[iloc]);
199 hasBeenUpdated =
true;
206 evaluateSatSpecHumidity(temperature, temperature);
208 relativeHumidity[iloc] *= (Q_sub_s_w / Q_sub_s_ice);
210 relativeHumidity[iloc] = std::min(100.0f, relativeHumidity[iloc]);
212 hasBeenUpdated =
true;
218 if (hasBeenUpdated) {
232 float esat, qvs, qv, satVaporPres;
234 std::vector<float> specificHumidity;
235 std::vector<float> airTemperature;
236 std::vector<float> pressure;
237 std::vector<float> relativeHumidity(
nlocs);
240 specificHumidity,
true);
242 airTemperature,
true);
245 if (pressure.empty()) {
250 if (!oops::allVectorsSameNonZeroSize(specificHumidity, airTemperature, pressure)) {
251 oops::Log::warning() <<
"Vector sizes: "
252 << oops::listOfVectorSizes(specificHumidity, airTemperature,
255 throw eckit::BadValue(
"At least one vector is the wrong size or empty out of "
256 "specific_humidity, air_temperature and pressure", Here());
263 for (
size_t jobs = 0; jobs <
nlocs; ++jobs) {
265 if (!apply[jobs])
continue;
272 esat = std::min(pressure[jobs]*0.15f, satVaporPres);
275 qvs = 0.622 * esat/(pressure[jobs]-esat);
278 qv = std::max(1.0e-12f, specificHumidity[jobs]/(1.0f-specificHumidity[jobs]));
281 relativeHumidity[jobs] = std::max(1.0e-6f, qv/qvs);
303 oops::Log::trace() <<
" Retrieve Specific Humidity" << std::endl;
304 oops::Log::trace() <<
" --> method: " <<
method() << std::endl;
305 oops::Log::trace() <<
" --> formulation: " <<
formulation() << std::endl;
306 oops::Log::trace() <<
" --> obsName: " <<
obsName() << std::endl;
323 float esat, qvs, qv, satVaporPres;
324 std::vector<float> relativeHumidity;
325 std::vector<float> airTemperature;
326 std::vector<float> pressure;
327 std::vector<float> specificHumidity(
nlocs);
330 relativeHumidity,
true);
332 airTemperature,
true);
335 if (pressure.empty()) {
340 if (!oops::allVectorsSameNonZeroSize(relativeHumidity, airTemperature, pressure)) {
341 oops::Log::warning() <<
"Vector sizes: "
342 << oops::listOfVectorSizes(relativeHumidity, airTemperature,
345 throw eckit::BadValue(
"At least one vector is the wrong size or empty out of "
346 "relative_humidity, air_temperature and pressure", Here());
353 for (
size_t jobs = 0; jobs <
nlocs; ++jobs) {
359 esat = std::min(pressure[jobs]*0.15f, satVaporPres);
362 qvs = 0.622 * esat/(pressure[jobs]-esat);
365 qv = std::max(1.0e-12f, relativeHumidity[jobs]*qvs);
368 specificHumidity[jobs] = std::max(1.0e-12f, qv/(1.0f+qv));
void methodDEFAULT(const std::vector< bool > &apply)
Cal_RelativeHumidity(const VariableTransformsParameters &options, const ObsFilterData &data, const std::shared_ptr< ioda::ObsDataVector< int >> &flags)
void runTransform(const std::vector< bool > &apply) override
Run variable conversion.
void methodUKMO(const std::vector< bool > &apply)
Cal_SpecificHumidity(const VariableTransformsParameters &options, const ObsFilterData &data, const std::shared_ptr< ioda::ObsDataVector< int >> &flags)
void runTransform(const std::vector< bool > &apply) override
Run variable conversion.
void methodDEFAULT(const std::vector< bool > &apply)
ObsFilterData provides access to all data related to an ObsFilter.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
static TransformMaker< Cal_RelativeHumidity > makerCal_RelativeHumidity_("RelativeHumidity")
static TransformMaker< Cal_SpecificHumidity > makerCal_SpecificHumidity_("SpecificHumidity")
static constexpr double t0c