20#include "pism/util/ScalarForcing.hh"
26#include <gsl/gsl_spline.h>
28#include "pism/util/ConfigInterface.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());
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 std::vector<double> times{};
98 std::vector<double> bounds{};
100 size_t N = times.size();
105 double v0 = data.front();
106 double v1 = data.back();
108 double b0 = bounds.front();
109 double b1 = bounds.back();
113 double dt1 = times.front() -
b0;
114 double dt2 = b1 - times.back();
117 double alpha = dt1 + dt2 > 0 ? dt2 / (dt1 + dt2) : 0.0;
119 v0 = (1.0 - alpha) * data.back() + alpha * data.front();
135 if (bounds.front() < times.front()) {
139 for (
size_t k = 0;
k < N; ++
k) {
143 if (bounds.back() > times.back()) {
150 forcing_t0 = bounds.front();
151 forcing_t1 = bounds.back();
157 "m_impl->times have to be strictly increasing (this is a bug)");
163 variable[
"units"] = units;
164 variable[
"output_units"] = output_units;
165 variable[
"long_name"] = long_name;
177 bool extrapolate = ctx.
config()->get_flag(
"input.forcing.time_extrapolation");
179 if (not (extrapolate or periodic)) {
185 long_name.c_str(), variable_name.c_str(), filename.c_str());
191 const std::string &variable_name,
const std::string &units,
192 const std::string &output_units,
const std::string &long_name)
200 auto config = ctx.
config();
202 auto filename = config->get_string(prefix +
".file");
203 bool periodic = config->get_flag(prefix +
".periodic");
205 if (filename.empty()) {
207 "%s.file is required", prefix.c_str());
210 initialize(ctx, filename, variable_name, units, output_units,
211 long_name, periodic);
215 const std::string &filename,
216 const std::string &variable_name,
217 const std::string &units,
218 const std::string &output_units,
219 const std::string &long_name,
228 initialize(ctx, filename, variable_name, units, output_units,
229 long_name, periodic);
261 if (T < m_impl->times.front()) {
296 return integral(a, t1) + v1 * (b - t1);
311 return 0.5 * (v_a + v_b) * dt;
319 for (
size_t k = ai + 1;
k < bi; ++
k) {
349 double N = std::floor((a - t0) / P);
350 double M = std::floor((b - t0) / P);
351 double delta = a - t0 - P * N;
352 double gamma = b - t0 - P * M;
354 double N_periods = M - (N + 1);
356 if (N_periods >= 0.0) {
357 return (
integral(t0 + delta, t0 + P) +
362 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
void read_time_info(std::shared_ptr< units::System > unit_system, const File &file, const std::string &time_name, const std::string &time_units, std::vector< double > ×, std::vector< double > &bounds)
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)
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