20#include "pism/util/ScalarForcing.hh"
26#include <gsl/gsl_spline.h>
28#include "pism/util/Config.hh"
29#include "pism/util/Context.hh"
30#include "pism/util/Time.hh"
31#include "pism/util/error_handling.hh"
32#include "pism/util/Logger.hh"
33#include "pism/util/io/File.hh"
34#include "pism/util/io/io_helpers.hh"
35#include "pism/util/VariableMetadata.hh"
36#include "pism/util/io/IO_Flags.hh"
46 double min = *std::min_element(data.begin(), data.end());
47 double max = *std::max_element(data.begin(), data.end());
49 metadata.report_range(log, min, max);
65 gsl_interp_accel*
acc;
70 const std::string &filename,
71 const std::string &variable_name,
72 const std::string &units,
73 const std::string &output_units,
74 const std::string &long_name,
85 " reading %s (%s) from file '%s'...\n",
86 long_name.c_str(), variable_name.c_str(), filename.c_str());
95 std::string time_name = file.
dimensions(variable_name)[0];
97 auto time = ctx.
time();
99 const auto × = info.times;
100 const auto &bounds = info.bounds;
102 size_t N = times.size();
107 double v0 = data.front();
108 double v1 = data.back();
110 double b0 = bounds.front();
111 double b1 = bounds.back();
115 double dt1 = times.front() -
b0;
116 double dt2 = b1 - times.back();
119 double alpha = dt1 + dt2 > 0 ? dt2 / (dt1 + dt2) : 0.0;
121 v0 = (1.0 - alpha) * data.back() + alpha * data.front();
137 if (bounds.front() < times.front()) {
141 for (
size_t k = 0;
k < N; ++
k) {
145 if (bounds.back() > times.back()) {
152 forcing_t0 = bounds.front();
153 forcing_t1 = bounds.back();
159 "m_impl->times have to be strictly increasing (this is a bug)");
165 variable[
"units"] = units;
166 variable[
"output_units"] = output_units;
167 variable[
"long_name"] = long_name;
179 bool extrapolate = ctx.
config()->get_flag(
"input.forcing.time_extrapolation");
181 if (not (extrapolate or periodic)) {
187 long_name.c_str(), variable_name.c_str(), filename.c_str());
193 const std::string &variable_name,
const std::string &units,
194 const std::string &output_units,
const std::string &long_name)
202 auto config = ctx.
config();
204 auto filename = config->get_string(prefix +
".file");
205 bool periodic = config->get_flag(prefix +
".periodic");
207 if (filename.empty()) {
209 "%s.file is required", prefix.c_str());
212 initialize(ctx, filename, variable_name, units, output_units,
213 long_name, periodic);
217 const std::string &filename,
218 const std::string &variable_name,
219 const std::string &units,
220 const std::string &output_units,
221 const std::string &long_name,
230 initialize(ctx, filename, variable_name, units, output_units,
231 long_name, periodic);
263 if (T < m_impl->times.front()) {
298 return integral(a, t1) + v1 * (b - t1);
313 return 0.5 * (v_a + v_b) * dt;
321 for (
size_t k = ai + 1;
k < bi; ++
k) {
351 double N = std::floor((a - t0) / P);
352 double M = std::floor((b - t0) / P);
353 double delta = a - t0 - P * N;
354 double gamma = b - t0 - P * M;
356 double N_periods = M - (N + 1);
358 if (N_periods >= 0.0) {
359 return (
integral(t0 + delta, t0 + P) +
364 return integral(t0 + delta, t0 + gamma) / dt;
std::shared_ptr< const Config > config() const
std::shared_ptr< const Logger > log() const
std::shared_ptr< units::System > unit_system() const
std::shared_ptr< const Time > time() const
std::vector< std::string > dimensions(const std::string &variable_name) const
High-level PISM I/O class.
void add_context(const std::string &message)
Add a message providing some context. This way we can (sort of) get a stack trace even though C++ exc...
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
double average(double t, double dt) const
double value(double t) const
void initialize(const Context &ctx, const std::string &filename, const std::string &variable_name, const std::string &units, const std::string &output_units, const std::string &long_name, bool periodic)
ScalarForcing(const Context &ctx, const std::string &option_prefix, const std::string &variable_name, const std::string &units, const std::string &output_units, const std::string &long_name)
double integral(double a, double b) const
#define PISM_ERROR_LOCATION
@ PISM_READONLY
open an existing file for reading only
std::vector< double > read_1d_variable(const File &file, const std::string &variable_name, const std::string &units, std::shared_ptr< units::System > unit_system)
TimeInfo read_time_info(const units::Unit &time_units, const std::string &calendar, const File &file, const std::string &time_name)
bool is_increasing(const std::vector< double > &a)
Checks if a vector of doubles is strictly increasing.
static void report_range(const std::vector< double > &data, const VariableMetadata &metadata, const Logger &log)
Report the range of a time-series stored in data.
void check_forcing_duration(const Time &time, double forcing_start, double forcing_end)
std::vector< double > times
std::vector< double > values