27#include "pism/util/Config.hh"
28#include "pism/util/GridInfo.hh"
29#include "pism/util/Grid.hh"
30#include "pism/util/VariableMetadata.hh"
31#include "pism/util/error_handling.hh"
32#include "pism/util/io/File.hh"
33#include "pism/util/io/IO_Flags.hh"
34#include "pism/util/io/YacOutputWriter.hh"
35#include "pism/external/nlohmann/json.hpp"
48 for (
const auto &attribute : attributes.
strings) {
49 output[attribute.first] = attribute.second;
52 for (
const auto &attribute : attributes.
numbers) {
53 output[attribute.first] = attribute.second;
62 static const std::map<pism::io::Type, std::string> type_map = {
67 auto it = type_map.find(input);
68 return (it != type_map.end()) ? it->second :
"None";
76 unsigned int x_size,
unsigned int y_start,
77 unsigned int y_size) {
78 std::vector<int> indices;
79 indices.reserve((
size_t)x_size * y_size);
80 for (
unsigned int j = y_start; j < y_start + y_size; ++j) {
81 for (
unsigned int i = x_start; i < x_start + x_size; ++i) {
82 indices.push_back((
int)(j * x_global_size + i));
96 return dims[0].get_name() +
"-" + dims[1].get_name();
103 for (
auto *ptr : buffers) {
113 const std::string & proj_string, std::vector<double> &longitudes,
114 std::vector<double> &latitudes) {
115 int patch_size = (
int)(grid.xm * grid.ym);
117 longitudes.resize(patch_size);
118 latitudes.resize(patch_size);
120 if (proj_string.empty()) {
127 const auto &x = grid.x;
128 const auto &y = grid.y;
130 double x_min = x.front();
131 double y_min = y.front();
132 double x_span = x.back() - x_min;
133 double y_span = y.back() - y_min;
136 const int i = p.i(), j = p.j();
137 longitudes[it] = (x[i] - x_min) / x_span;
138 latitudes[it] = (y[j] - y_min) / y_span;
146 "output writer: non-trivial projections are not implemented yet");
163 MPI_Comm global_comm = MPI_COMM_NULL;
165 const int nbr_comps = 2;
166 const char *comp_names[nbr_comps] = {
"pism",
"pism_output" };
167 yac_cget_comps_comm(comp_names, nbr_comps, &global_comm);
171 MPI_Comm_size(global_comm, &global_size);
172 std::vector<int> component_leaders_ranks(global_size);
175 MPI_Group local_group = MPI_GROUP_NULL, global_group = MPI_GROUP_NULL;
176 MPI_Comm_group(
comm(), &local_group);
177 MPI_Comm_group(global_comm, &global_group);
184 const int local_leader_rank[] = {0};
185 int local_leader_global_rank[] = {-1};
186 MPI_Group_translate_ranks(local_group, 1, local_leader_rank,
187 global_group, local_leader_global_rank);
188 MPI_Allgather(local_leader_global_rank, 1, MPI_INT,
189 component_leaders_ranks.data(), 1, MPI_INT, global_comm);
190 int remote_leader = component_leaders_ranks.back();
193 MPI_Intercomm_create(
comm(), local_leader_rank[0], global_comm, remote_leader,
tag,
196 MPI_Group_free(&local_group);
197 MPI_Group_free(&global_group);
198 MPI_Comm_free(&global_comm);
214 variable_name.c_str());
229 const auto &grid = *variable.
grid_info();
240 int grid_size[2] = {(
int)grid.Mx, (
int)grid.My};
245 std::vector<double> latitudes;
246 std::vector<double> longitudes;
249 int local_patch_size = (
int)latitudes.size();
251 MPI_Gather(&local_patch_size, 1, MPI_INT, NULL, 1, MPI_INT, 0,
m_intercomm);
254 auto patch_global_indices =
258 MPI_Gatherv(patch_global_indices.data(), local_patch_size, MPI_INT, NULL, NULL, NULL, MPI_INT, 0,
260 MPI_Gatherv(latitudes.data(), local_patch_size, MPI_DOUBLE, NULL, NULL, NULL, MPI_DOUBLE, 0,
262 MPI_Gatherv(longitudes.data(), local_patch_size, MPI_DOUBLE, NULL, NULL, NULL, MPI_DOUBLE, 0,
266 int cyclic_dims[] = {0, 0};
267 int nbr_vertices[] = {(
int)grid.xm, (
int)grid.ym};
269 int point_set_id = -1;
270 yac_cdef_grid_curve2d(
grid_name.c_str(), nbr_vertices, cyclic_dims, longitudes.data(),
271 latitudes.data(), &grid_id);
272 yac_cdef_points_unstruct(grid_id, local_patch_size, YAC_LOCATION_CORNER, longitudes.data(),
273 latitudes.data(), &point_set_id);
281 const auto &variable_name = variable.
get_name();
288 int collection_size = std::max((
int)variable.
levels().size(), 1);
295 yac_cdef_field(variable_name.c_str(), 1, &point_set_id, 1, collection_size,
"PT1M",
296 YAC_TIME_UNIT_ISO_FORMAT, &field_id);
305 info[
"variable_name"] = variable_name;
306 info[
"timestep"] =
"PT1M";
307 info[
"collection_size"] = collection_size;
324 const nlohmann::json &metadata) {
330 nlohmann::json message{};
331 message[
"action"] = action_id;
332 message[
"info"] = metadata;
339 MPI_Isend((
void *)message_string.data(), (
int)message_string.length(), MPI_CHAR, 0, 0,
349 MPI_Comm_rank(
comm, &rank);
379 for (
const auto &variable : array_variables) {
380 if (variable.grid_info() ==
nullptr) {
386 const auto &grid = *variable.grid_info();
388 int collection_size = std::max((
int)variable.levels().size(), 1);
389 int array_size = (
int)(grid.xm * grid.ym * collection_size);
403 const std::string &variable_name,
404 const std::vector<std::string> &dims,
io::Type type,
413 nlohmann::json info, nc_attributes;
415 info[
"attributes"] = nc_attributes;
416 info[
"dimensions"] = dims;
418 info[
"file_name"] = file_name;
419 info[
"variable_name"] = variable_name;
438 info[
"file_name"] = file_name;
439 info[
"time"] = time_seconds;
446 info[
"file_name"] = file_name;
447 info[
"history"] = text;
454 info[
"file_name"] = file_name;
462 int time_length = -1;
463 MPI_Recv(&time_length, 1, MPI_INT, 0, 0,
m_intercomm, &status);
464 double last_time = -1;
465 MPI_Recv(&last_time, 1, MPI_DOUBLE, 0, 0,
m_intercomm, &status);
479 if (error_code != MPI_SUCCESS) {
498 info[
"file_name"] = file_name;
503 const std::string &name,
unsigned int length) {
518 info[
"file_name"] = file_name;
520 info[
"length"] = length;
528 const std::string &file_name,
const std::map<std::string, std::string> &strings,
529 const std::map<std::string, std::vector<double> > &numbers) {
532 nlohmann::json attributes_json;
533 for (
const auto &attribute : strings) {
534 attributes_json[attribute.first] = attribute.second;
537 for (
const auto &attribute : numbers) {
538 attributes_json[attribute.first] = attribute.second;
541 nlohmann::json file_attributes_json;
542 file_attributes_json[
"file_name"] = file_name;
543 file_attributes_json[
"attributes"] = attributes_json;
556 const std::string &variable_name,
557 const std::vector<unsigned int> &start,
558 const std::vector<unsigned int> &
count,
const double *data) {
563 info[
"file_name"] = file_name;
564 info[
"variable_name"] = variable_name;
565 info[
"start"] = start;
566 info[
"count"] =
count;
567 info[
"tag"] =
tag(variable_name);
573 for (
const auto &c :
count) {
579 double *buffer =
new double[data_size];
581 memcpy(buffer, data, data_size *
sizeof(
double));
583 MPI_Isend((
void *)(buffer), data_size, MPI_DOUBLE, 0,
tag(variable_name),
589 const std::string &variable_name,
590 const std::vector<unsigned int> &start,
591 const std::vector<unsigned int> &
count,
592 const std::string &input) {
597 info[
"file_name"] = file_name;
598 info[
"variable_name"] = variable_name;
599 info[
"start"] = start;
600 info[
"count"] =
count;
601 info[
"tag"] =
tag(variable_name);
608 for (
const auto &c :
count) {
616 MPI_Isend((
void *)(
m_text_buffers.back().data()), data_size, MPI_CHAR, 0,
622 const std::string &variable_name,
623 const double *data) {
628 const auto *grid = variable.grid_info();
634 info[
"file_name"] = file_name;
635 info[
"variable_name"] = variable_name;
636 info[
"ndims"] = variable.n_spatial_dimensions();
637 info[
"time_dependent"] = variable.get_time_dependent();
642 int x_size = (
int)grid->xm;
643 int y_size = (
int)grid->ym;
644 int collection_size = std::max((
int)variable.levels().size(), 1);
649 std::vector<double**> collection_data(collection_size,
nullptr);
650 std::vector<double*> point_set_data(collection_size,
nullptr);
651 for (
int j = 0; j < collection_size; ++j) {
653 collection_data[j] = &(point_set_data[j]);
661 int delta_x_p = collection_size;
662 int delta_y_p = collection_size * x_size;
665 int delta_y_y = x_size;
666 for (
int c = 0; c < collection_size; c++) {
667 for (
int x = 0; x < x_size; x++) {
668 for (
int y = 0; y < y_size; y++) {
669 int pism_index = y * delta_y_p + x * delta_x_p + c;
670 int yac_index = y * delta_y_y + x * delta_x_y;
672 collection_data[c][0][yac_index] = data[pism_index];
684 yac_cput(
m_field_ids[variable_name], collection_size, collection_data.data(), &info, &error);
A class for storing and accessing PISM configuration flags and parameters.
void set_is_async(bool flag)
const std::string & time_name() const
const VariableMetadata & variable_info(const std::string &variable_name) const
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
std::map< std::string, std::string > strings
string and boolean attributes
std::map< std::string, std::vector< double > > numbers
scalar and array attributes
std::vector< std::string > m_text_buffers
buffers used to send text (write_text_impl())
void initialize_impl(const std::set< VariableMetadata > &array_variables)
void define_yac_field(const VariableMetadata &variable)
void set_global_attributes_impl(const std::string &file_name, const std::map< std::string, std::string > &strings, const std::map< std::string, std::vector< double > > &numbers)
void end_yac_definitions()
void define_variable_impl(const std::string &file_name, const std::string &variable_name, const std::vector< std::string > &dims, io::Type type, const VariableAttributes &attributes)
std::map< std::string, int > m_field_ids
YAC field ID corresponding to a particular variable (by name)
std::map< std::string, int > m_variable_tags
std::vector< double * > m_buffers
buffers used to send arrays of double
void define_dimension_impl(const std::string &file_name, const std::string &name, unsigned int length)
void define_yac_grid(const VariableMetadata &variable)
void write_distributed_array_impl(const std::string &file_name, const std::string &variable_name, const double *data)
std::vector< MPI_Request > m_mpi_requests
void close_impl(const std::string &file_name)
void append_impl(const std::string &file_name)
TagTreatment
Tags for MPI messages sending non-gridded variable data.
void write_text_impl(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::string &input)
void write_array_impl(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const double *data)
double last_time_value_impl(const std::string &file_name)
unsigned int time_dimension_length_impl(const std::string &file_name)
void waitall()
Call MPI_Waitall() to ensure that all buffers can be freed.
std::map< std::string, int > m_time_length
Length of the time dimension in a file.
bool m_leader
True if the current MPI process is responsible for sending non-gridded data.
void append_history_impl(const std::string &file_name, const std::string &text)
YacOutputWriter(MPI_Comm comm, const Config &config)
void append_time_impl(const std::string &file_name, double time_seconds)
std::map< std::string, int > m_point_set_id
YAC point set ID corresponding to a grid name.
void sync_impl(const std::string &file_name)
std::map< std::string, std::map< std::string, bool > > m_defined_variable
void send_action(int action_id, const nlohmann::json &metadata)
std::map< std::string, std::map< std::string, bool > > m_defined_dimension
int tag(const std::string &variable_name, TagTreatment flag=GET_EXISTING_TAG)
std::map< std::string, double > m_last_time
last time value in an output file
#define PISM_ERROR_LOCATION
static std::string to_python_type(pism::io::Type input)
static void to_json(const VariableAttributes &attributes, nlohmann::json &output)
static void free_array_buffers(std::vector< double * > &buffers)
static std::string grid_name(const VariableMetadata &variable)
void compute_point_coordinates(const grid::DistributedGridInfo &grid, const std::string &proj_string, std::vector< double > &longitudes, std::vector< double > &latitudes)
static std::vector< int > patch_global_indices(unsigned int x_global_size, unsigned int x_start, unsigned int x_size, unsigned int y_start, unsigned int y_size)
@ FINISH_YAC_INITIALIZATION
std::string grid_name(const pism::File &file, const std::string &variable_name, pism::units::System::Ptr sys, bool piecewise_constant)