20 #include "pism/util/pism_utilities.hh"
29 #include <gsl/gsl_version.h>
35 #include "pism/pism_config.hh"
40 #define MPI_INCLUDED 1
44 #if (Pism_USE_PROJ==1)
45 #include "pism/util/Proj.hh"
48 #if (Pism_USE_JANSSON==1)
52 #include <petsctime.h>
56 #include "pism/util/error_handling.hh"
65 std::string tmp = input;
68 tmp.erase(0, tmp.find_first_not_of(
" \t"));
71 tmp.substr(tmp.find_last_not_of(
" \t"));
77 bool ends_with(
const std::string &str,
const std::string &suffix) {
78 if (suffix.size() > str.size()) {
82 return (str.rfind(suffix) + suffix.size() == str.size());
86 std::string
join_impl(
const T& input,
const std::string& separator) {
91 auto j = input.begin();
92 std::string result = *j;
94 while (j != input.end()) {
95 result += separator + *j;
102 std::string
join(
const std::vector<std::string> &strings,
const std::string &separator) {
106 std::string
set_join(
const std::set<std::string> &input,
const std::string& separator) {
117 for (
const char &c : input) {
118 result += c == from ? to : c;
125 std::vector<std::string>
split(
const std::string &input,
char separator) {
126 std::istringstream input_list(input);
128 std::vector<std::string> result;
130 while (getline(input_list, token, separator)) {
131 if (not token.empty()) {
132 result.emplace_back(token);
139 std::set<std::string>
set_split(
const std::string &input,
char separator) {
140 std::set<std::string> result;
141 for (
const auto &token :
split(input, separator)) {
142 result.insert(token);
149 int len = (int)a.size();
150 for (
int k = 0;
k < len-1;
k++) {
151 if (a[
k] >= a[
k+1]) {
158 bool member(
const std::string &
string,
const std::set<std::string> &set) {
159 return (set.find(
string) != set.end());
163 assert(local != result);
164 int err = MPI_Allreduce(local, result,
count, MPI_DOUBLE, op, comm);
169 assert(local != result);
170 int err = MPI_Allreduce(local, result,
count, MPI_INT, op, comm);
194 unsigned int GlobalSum(MPI_Comm comm,
unsigned int input) {
196 int err = MPI_Allreduce(&input, &result, 1, MPI_UNSIGNED, MPI_SUM, comm);
203 int err = MPI_Allreduce(&input, &result, 1, MPI_INT, MPI_SUM, comm);
233 result +=
pism::printf(
"CMake %s.\n", pism::cmake_version);
238 result +=
pism::printf(
"PETSc configure: %s\n", pism::petsc_configure_flags);
245 OMPI_RELEASE_VERSION);
249 MPI_Get_library_version(buffer, &string_length);
254 result +=
pism::printf(
"NetCDF %s.\n", nc_inq_libvers());
258 #if (Pism_USE_PROJ==1)
262 #if (Pism_USE_JANSSON==1)
263 result +=
pism::printf(
"Jansson %s.\n", JANSSON_VERSION);
266 #if (Pism_BUILD_PYTHON_BINDINGS==1)
267 result +=
pism::printf(
"SWIG %s.\n", pism::swig_version);
268 result +=
pism::printf(
"petsc4py %s.\n", pism::petsc4py_version);
277 const double seconds_per_hour = 3600.0;
285 MPI_Comm_rank(com, &rank);
292 localtime_r(&now, &tm_now);
295 strftime(date_str,
sizeof(date_str),
"%F %T %Z", &tm_now);
298 MPI_Bcast(date_str, 50, MPI_CHAR, 0, com);
300 return std::string(date_str);
308 ierr = PetscGetUserName(username,
sizeof(username));
314 ierr = PetscGetHostName(hostname,
sizeof(hostname));
321 std::string result =
pism::printf(
"%s@%s %s: ", username, hostname, time.c_str());
323 unsigned int length = result.size();
324 MPI_Bcast(&length, 1, MPI_UNSIGNED, 0, com);
326 result.resize(length);
327 MPI_Bcast(&result[0], length, MPI_CHAR, 0, com);
337 PetscErrorCode ierr = PetscGetArgs(&argc, &argv);
341 std::string argument;
342 for (
int j = 0; j < argc; j++) {
346 if (argument.find(
' ') != std::string::npos) {
347 argument =
"\"" + argument +
"\"";
350 cmdstr += std::string(
" ") + argument;
365 const std::string &suffix) {
366 std::string basename = filename;
370 std::string::size_type j = basename.rfind(separator);
371 if (j == std::string::npos) {
372 j = basename.rfind(
".nc");
376 if (j == std::string::npos) {
381 basename.resize(
static_cast<int>(j));
383 result = basename + separator + suffix;
396 MPI_Comm_rank(comm, &rank);
402 PetscErrorCode ierr = PetscTime(&tmp);
PISM_CHK(ierr,
"PetscTime");
410 MPI_Bcast(&result, 1, MPI_DOUBLE, 0, comm);
415 std::string
printf(
const char *format, ...) {
416 std::string result(1024,
' ');
420 va_start(arglist, format);
421 if((length = vsnprintf(&result[0], result.size(), format, arglist)) > result.size()) {
422 result.reserve(length);
423 vsnprintf(&result[0], result.size(), format, arglist);
426 return result.substr(0, length);
436 if (format.find(
"%s") == std::string::npos) {
441 if (format.find(
'%') != format.rfind(
'%')) {
448 double my_min = input[0];
449 for (
auto x : input) {
456 double my_max = input[0];
457 for (
auto x : input) {
474 static const size_t block_size = 92681;
478 while (length != 0) {
479 size_t block =
std::min(block_size, length);
481 for (
size_t i = 0; i < block; ++i) {
486 c0 = c0 % UINT32_MAX;
487 c1 =
c1 % UINT32_MAX;
489 length = length > block_size ? length - block_size : 0;
491 return (
c1 << 32 | c0);
498 const std::vector<double> &data,
501 MPI_Comm_rank(com, &rank);
503 uint64_t
sum =
fletcher64((uint32_t*)data.data(), data.size() * 2);
505 PetscPrintf(PETSC_COMM_SELF,
"[%d] %s: %016llx\n",
506 rank, label, (
unsigned long long int)
sum);
510 const std::vector<double> &data,
513 MPI_Comm_rank(com, &rank);
515 std::vector<std::string> tmp;
516 tmp.reserve(data.size());
517 for (
const auto &f : data) {
521 auto str =
join(tmp,
",");
523 PetscPrintf(PETSC_COMM_SELF,
"[%d] %s: %s\n",
524 rank, label, str.c_str());
528 const std::vector<int> &data,
531 MPI_Comm_rank(com, &rank);
533 std::vector<std::string> tmp;
534 tmp.reserve(data.size());
535 for (
const auto &f : data) {
539 auto str =
join(tmp,
",");
541 PetscPrintf(PETSC_COMM_SELF,
"[%d] %s: %s\n",
542 rank, label, str.c_str());
550 double floatation_level,
double rho_ice,
551 double rho_water,
double g) {
553 double ice_bottom =
std::max(bed, floatation_level -
rho_ice / rho_water * ice_thickness);
554 double water_column_height =
std::max(floatation_level - ice_bottom, 0.0);
556 if (ice_thickness > 0.0) {
557 return 0.5 * rho_water *
g * pow(water_column_height, 2.0) / ice_thickness;
564 double result = strtod(input.c_str(), &endptr);
565 if (*endptr !=
'\0') {
567 "Can't parse %s (expected a floating point number)",
575 long int result = strtol(input.c_str(), &endptr, 10);
576 if (*endptr !=
'\0') {
578 "Can't parse %s (expected an integer)",
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 max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double sum(const array::Scalar &input)
Sums up all the values in an array::Scalar object. Ignores ghosts.
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
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)
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.
static double start_time(const Config &config, const Logger &log, const File *file, const std::string &reference_date, const std::string &calendar, const units::Unit &time_units)
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.
void GlobalMax(MPI_Comm comm, double *local, double *result, int count)
std::string set_join(const std::set< std::string > &input, const std::string &separator)
std::string printf(const char *format,...)
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.
bool member(const std::string &string, const std::set< std::string > &set)
void GlobalMin(MPI_Comm comm, double *local, double *result, int count)
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).
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.