20#include "pism/util/pism_utilities.hh"
29#include <gsl/gsl_version.h>
31#include "pism/pism_config.hh"
40#include <netcdf_meta.h>
44#include "pism/util/Proj.hh"
51#include "pism/util/error_handling.hh"
60 std::string tmp = input;
63 tmp.erase(0, tmp.find_first_not_of(
" \t"));
66 tmp.erase(tmp.find_last_not_of(
" \t") + 1);
72bool ends_with(
const std::string &str,
const std::string &suffix) {
73 if (suffix.size() > str.size()) {
77 return (str.rfind(suffix) + suffix.size() == str.size());
81std::string
join_impl(
const T& input,
const std::string& separator) {
86 auto j = input.begin();
87 std::string result = *j;
89 while (j != input.end()) {
90 result += separator + *j;
97std::string
join(
const std::vector<std::string> &strings,
const std::string &separator) {
101std::string
set_join(
const std::set<std::string> &input,
const std::string& separator) {
112 for (
const char &c : input) {
113 result += c == from ? to : c;
120std::vector<std::string>
split(
const std::string &input,
char separator) {
121 std::istringstream input_list(input);
123 std::vector<std::string> result;
125 while (getline(input_list, token, separator)) {
126 if (not token.empty()) {
127 result.emplace_back(token);
134std::set<std::string>
set_split(
const std::string &input,
char separator) {
135 std::set<std::string> result;
136 for (
const auto &token :
split(input, separator)) {
137 result.insert(token);
144 int len = (
int)a.size();
145 for (
int k = 0;
k < len-1;
k++) {
146 if (a[
k] >= a[
k+1]) {
153template<
typename T,
typename A>
154bool member(
const T& x,
const A& iterable) {
155 return std::any_of(iterable.begin(), iterable.end(),
156 [&x](
const std::string &y) { return x == y; });
159bool set_member(
const std::string &
string,
const std::set<std::string> &set) {
160 return member(
string, set);
163bool vector_member(
const std::string &
string,
const std::vector<std::string> &vector) {
164 return member(
string, vector);
168 assert(local != result);
169 int err = MPI_Allreduce(local, result,
count, MPI_DOUBLE, op, comm);
174 assert(local != result);
175 int err = MPI_Allreduce(local, result,
count, MPI_INT, op, comm);
199unsigned int GlobalSum(MPI_Comm comm,
unsigned int input) {
201 int err = MPI_Allreduce(&input, &result, 1, MPI_UNSIGNED, MPI_SUM, comm);
208 int err = MPI_Allreduce(&input, &result, 1, MPI_INT, MPI_SUM, comm);
244 result +=
pism::printf(
"CMake %s.\n", pism::cmake_version);
249 result +=
pism::printf(
"PETSc configure: %s\n", pism::petsc_configure_flags);
256 OMPI_RELEASE_VERSION);
260 MPI_Get_library_version(buffer, &string_length);
264 result +=
pism::printf(
"NetCDF %s.\n", nc_inq_libvers());
268#if (Pism_USE_PROJ==1)
272#if (Pism_BUILD_PYTHON_BINDINGS==1)
273 result +=
pism::printf(
"SWIG %s.\n", pism::swig_version);
274 result +=
pism::printf(
"petsc4py %s.\n", pism::petsc4py_version);
282 return 100 * NC_VERSION_MAJOR + 10 * NC_VERSION_MINOR + NC_VERSION_PATCH;
291 const double seconds_per_hour = 3600.0;
299 MPI_Comm_rank(com, &rank);
306 localtime_r(&now, &tm_now);
309 strftime(date_str,
sizeof(date_str),
"%F %T %Z", &tm_now);
312 MPI_Bcast(date_str, 50, MPI_CHAR, 0, com);
314 return std::string(date_str);
322 ierr = PetscGetUserName(username,
sizeof(username));
328 ierr = PetscGetHostName(hostname,
sizeof(hostname));
335 std::string result =
pism::printf(
"%s@%s %s: ", username, hostname, time.c_str());
337 unsigned int length = result.size();
338 MPI_Bcast(&length, 1, MPI_UNSIGNED, 0, com);
340 result.resize(length);
341 MPI_Bcast(&result[0], length, MPI_CHAR, 0, com);
351 PetscErrorCode ierr = PetscGetArgs(&argc, &argv);
355 std::string argument;
356 for (
int j = 0; j < argc; j++) {
360 if (argument.find(
' ') != std::string::npos) {
361 argument =
"\"" + argument +
"\"";
364 cmdstr += std::string(
" ") + argument;
379 const std::string &suffix) {
380 std::string basename = filename;
384 std::string::size_type j = basename.rfind(separator);
385 if (j == std::string::npos) {
386 j = basename.rfind(
".nc");
390 if (j == std::string::npos) {
395 basename.resize(
static_cast<int>(j));
397 result = basename + separator + suffix;
410 MPI_Comm_rank(comm, &rank);
416 PetscErrorCode ierr = PetscTime(&tmp);
PISM_CHK(ierr,
"PetscTime");
424 MPI_Bcast(&result, 1, MPI_DOUBLE, 0, comm);
429std::string
printf(
const char* format, ...) {
430 std::string result(1024,
'\0');
432 va_start(ap, format);
435 va_list ap1; va_copy(ap1, ap);
436 int n = std::vsnprintf(&result[0], result.size(), format, ap1);
438 if (
n < 0) { va_end(ap);
return {}; }
440 if (
static_cast<size_t>(
n) >= result.size()) {
442 result.resize(
static_cast<size_t>(
n) + 1);
443 va_list ap2; va_copy(ap2, ap);
444 std::vsnprintf(&result[0], result.size(), format, ap2);
449 result.resize(
static_cast<size_t>(
n));
460 if (format.find(
"%s") == std::string::npos) {
465 if (format.find(
'%') != format.rfind(
'%')) {
472 double my_min = input[0];
473 for (
auto x : input) {
474 my_min = std::min(x, my_min);
480 double my_max = input[0];
481 for (
auto x : input) {
482 my_max = std::max(x, my_max);
498 static const size_t block_size = 92681;
502 while (length != 0) {
503 size_t block = std::min(block_size, length);
505 for (
size_t i = 0; i < block; ++i) {
510 c0 = c0 % UINT32_MAX;
511 c1 =
c1 % UINT32_MAX;
513 length = length > block_size ? length - block_size : 0;
515 return (
c1 << 32 | c0);
522 const std::vector<double> &data,
525 MPI_Comm_rank(com, &rank);
527 uint64_t sum =
fletcher64((uint32_t*)data.data(), data.size() * 2);
529 PetscPrintf(PETSC_COMM_SELF,
"[%d] %s: %016llx\n",
530 rank, label, (
unsigned long long int)sum);
534 const std::vector<double> &data,
537 MPI_Comm_rank(com, &rank);
539 std::vector<std::string> tmp;
540 tmp.reserve(data.size());
541 for (
const auto &f : data) {
545 auto str =
join(tmp,
",");
547 PetscPrintf(PETSC_COMM_SELF,
"[%d] %s: %s\n",
548 rank, label, str.c_str());
552 const std::vector<int> &data,
555 MPI_Comm_rank(com, &rank);
557 std::vector<std::string> tmp;
558 tmp.reserve(data.size());
559 for (
const auto &f : data) {
563 auto str =
join(tmp,
",");
565 PetscPrintf(PETSC_COMM_SELF,
"[%d] %s: %s\n",
566 rank, label, str.c_str());
574 double floatation_level,
double rho_ice,
575 double rho_water,
double g) {
577 double ice_bottom = std::max(bed, floatation_level -
rho_ice / rho_water * ice_thickness);
578 double water_column_height = std::max(floatation_level - ice_bottom, 0.0);
580 if (ice_thickness > 0.0) {
581 return 0.5 * rho_water *
g * pow(water_column_height, 2.0) / ice_thickness;
588 double result = strtod(input.c_str(), &endptr);
589 if (*endptr !=
'\0') {
591 "Can't parse %s (expected a floating point number)",
598 std::vector<double> result;
600 for (
const auto &p :
split(input,
',')) {
608 long int result = strtol(input.c_str(), &endptr, 10);
609 if (*endptr !=
'\0') {
611 "Can't parse %s (expected an integer)",
618 std::vector<long> result;
620 for (
const auto &p :
split(input,
',')) {
void failed()
Indicates a failure of a parallel section.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
#define PISM_CHK(errcode, name)
#define PISM_ERROR_LOCATION
#define PISM_C_CHK(errcode, success, name)
double get_time(MPI_Comm comm)
bool is_increasing(const std::vector< double > &a)
Checks if a vector of doubles is strictly increasing.
double parse_number(const std::string &input)
bool member(const T &x, const A &iterable)
double average_water_column_pressure(double ice_thickness, double bed, double floatation_level, double rho_ice, double rho_water, double g)
double wall_clock_hours(MPI_Comm com, double start_time)
Return time since the beginning of the run, in hours.
std::vector< long > parse_integer_list(const std::string &input)
void print_checksum(MPI_Comm com, const std::vector< double > &data, const char *label)
bool ends_with(const std::string &str, const std::string &suffix)
Returns true if str ends with suffix and false otherwise.
std::vector< double > parse_number_list(const std::string &input)
void GlobalMax(MPI_Comm comm, double *local, double *result, int count)
bool vector_member(const std::string &string, const std::vector< std::string > &vector)
std::string set_join(const std::set< std::string > &input, const std::string &separator)
std::string printf(const char *format,...)
int netcdf_version()
return NetCDF version as an integer
void print_vector(MPI_Comm com, const std::vector< double > &data, const char *label)
uint64_t fletcher64(const uint32_t *data, size_t length)
void validate_format_string(const std::string &format)
std::set< std::string > set_split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a set of strings.
double vector_min(const std::vector< double > &input)
std::string string_strip(const std::string &input)
std::string filename_add_suffix(const std::string &filename, const std::string &separator, const std::string &suffix)
Adds a suffix to a filename.
std::string timestamp(MPI_Comm com)
Creates a time-stamp used for the history NetCDF attribute.
void GlobalMin(MPI_Comm comm, double *local, double *result, int count)
static double start_time(const Config &config, const File *file, const std::string &reference_date, const std::string &calendar, const units::Unit &time_units)
std::string args_string()
Uses argc and argv to create the string with current PISM command-line arguments.
long int parse_integer(const std::string &input)
static const int TEMPORARY_STRING_LENGTH
std::string join(const std::vector< std::string > &strings, const std::string &separator)
Concatenate strings, inserting separator between elements.
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)
std::string username_prefix(MPI_Comm com)
Creates a string with the user name, hostname and the time-stamp (for history strings).
bool set_member(const std::string &string, const std::set< std::string > &set)
std::string join_impl(const T &input, const std::string &separator)
void GlobalReduce(MPI_Comm comm, double *local, double *result, int count, MPI_Op op)
std::string replace_character(const std::string &input, char from, char to)
double vector_max(const std::vector< double > &input)
std::vector< std::string > split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a vector of strings.