Skip to content

Commit

Permalink
#128: stats: add derived stats for ranks and objects
Browse files Browse the repository at this point in the history
  • Loading branch information
lifflander committed Dec 6, 2024
1 parent 0030760 commit c0264cf
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 4 deletions.
34 changes: 34 additions & 0 deletions src/vt-tv/api/info.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,40 @@ struct Info {
return static_cast<int>(rank.getRankID());
}

/**
* \brief Get user-defined QOIs on a rank
*
* \param[in] rank the rank
* \param[in] phase the phase
* \param[in] key the key
*
* \return the value for a given user-defined key/value pair
*/
QOIVariantTypes getRankUserDefined(
Rank rank, PhaseType phase, std::string const& key
) const {
return rank.getPhaseWork().at(phase).getUserDefined().at(key);
}

/**
* \brief Get all the user-defined keys for a given rank on a phase
*
* \param[in] rank the rank
* \param[in] phase the phase
*
* \return vector of keys
*/
std::vector<std::string> getRankUserDefinedKeys(
Rank rank, PhaseType phase
) const {
std::vector<std::string> keys;
auto const& user_defined = rank.getPhaseWork().at(phase).getUserDefined();
for (auto const& [key, _] : user_defined) {
keys.push_back(key);
}
return keys;
}

/**
* \brief Get load of a given rank
*
Expand Down
19 changes: 17 additions & 2 deletions src/vt-tv/api/phase_work.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,17 @@ struct PhaseWork {
*
* \param[in] in_phase the phase
* \param[in] in_objects objects' work for the phase
* \param[in] in_user_defined the user-defined fields in json
*/
PhaseWork(
PhaseType in_phase,
std::unordered_map<ElementIDType, ObjectWork> in_objects)
std::unordered_map<ElementIDType, ObjectWork> in_objects,
std::unordered_map<std::string, QOIVariantTypes> in_user_defined = {}
)
: phase_(in_phase),
objects_(std::move(in_objects)) { }
objects_(std::move(in_objects)),
user_defined_(std::move(in_user_defined))
{ }

/**
* \brief Get the phase ID
Expand Down Expand Up @@ -141,6 +146,13 @@ struct PhaseWork {
return ov_max;
}

/**
* \brief Get user-defined fields
*
* \return user-defined fields
*/
auto const& getUserDefined() const { return user_defined_; }

/**
* \brief Serializer for data
*
Expand All @@ -150,13 +162,16 @@ struct PhaseWork {
void serialize(SerializerT& s) {
s | phase_;
s | objects_;
s | user_defined_;
}

private:
/// Phase identifier
PhaseType phase_ = 0;
/// Object work for this phase
std::unordered_map<ElementIDType, ObjectWork> objects_;
// User-defined field---used to populate the rank-level info
std::unordered_map<std::string, QOIVariantTypes> user_defined_;
};

} /* end namespace vt::tv */
Expand Down
94 changes: 93 additions & 1 deletion src/vt-tv/render/render.cc
Original file line number Diff line number Diff line change
Expand Up @@ -307,14 +307,32 @@ Render::createObjectMapping_(PhaseType phase) {
return object_mapping;
}

template <typename T, typename U>
void Render::addRankArray(
vtkNew<vtkPolyData>& pd_mesh, PhaseType phase, std::string const& key
) {
vtkNew<U> array;
std::string array_name = key;
array->SetName(array_name.c_str());
array->SetNumberOfTuples(this->n_ranks_);

for (uint64_t rank_id = 0; rank_id < this->n_ranks_; rank_id++) {
auto const& cur_rank_info = info_.getRanks().at(rank_id);
auto const& value = info_.getRankUserDefined(cur_rank_info, phase, key);
//fmt::print("phase={}, key={}, rank_id={}\n", phase, key, rank_id);
array->SetTuple1(rank_id, std::get<T>(value));
}
pd_mesh->GetPointData()->AddArray(array);
}

vtkNew<vtkPolyData> Render::createRankMesh_(PhaseType phase) {
fmt::print("\n\n");
fmt::print("----- Creating rank mesh for phase {} -----\n", phase);
vtkNew<vtkPoints> rank_points_;
rank_points_->SetNumberOfPoints(this->n_ranks_);

vtkNew<vtkDoubleArray> rank_arr;
std::string rank_array_name = "Rank " + this->rank_qoi_;
std::string rank_array_name = this->rank_qoi_;
rank_arr->SetName(rank_array_name.c_str());
rank_arr->SetNumberOfTuples(this->n_ranks_);

Expand All @@ -338,10 +356,27 @@ vtkNew<vtkPolyData> Render::createRankMesh_(PhaseType phase) {
vtkNew<vtkPolyData> pd_mesh;
pd_mesh->SetPoints(rank_points_);
pd_mesh->GetPointData()->SetScalars(rank_arr);

auto const& rank_info = info_.getRanks().at(0);
auto const& keys = info_.getRankUserDefinedKeys(rank_info, phase);
for (auto const& key : keys) {
auto const& test_value = info_.getRankUserDefined(rank_info, phase, key);
if (std::holds_alternative<double>(test_value)) {
addRankArray<double, vtkDoubleArray>(pd_mesh, phase, key);
} else if (std::holds_alternative<int>(test_value)) {
addRankArray<int, vtkIntArray>(pd_mesh, phase, key);
}
}

fmt::print("----- Finished creating rank mesh for phase {} -----\n", phase);
return pd_mesh;
}

enum struct VtkTypeEnum : int {
TYPE_DOUBLE,
TYPE_INT
};

bool compareObjects(
const std::pair<ObjectWork, uint64_t>& p1,
const std::pair<ObjectWork, uint64_t>& p2) {
Expand Down Expand Up @@ -394,6 +429,8 @@ vtkNew<vtkPolyData> Render::createObjectMesh_(PhaseType phase) {

auto object_mapping = this->createObjectMapping_(phase);

std::map<std::string, VtkTypeEnum> qoi_map;

// Iterate through object mapping
for (auto const& [rankID, objects] : object_mapping) {
std::array<uint64_t, 3> ijk =
Expand Down Expand Up @@ -436,6 +473,14 @@ vtkNew<vtkPolyData> Render::createObjectMesh_(PhaseType phase) {
for (auto const& [objectID, objectWork] : objects) {
bool migratable = this->info_.getObjectInfo().at(objectID).isMigratable();
ordered_objects.push_back(std::make_pair(objectWork, migratable));
for (auto const& [key, _] : objectWork.getUserDefined()) {
auto const& value = objectWork.getUserDefined().at(key);
VtkTypeEnum t = VtkTypeEnum::TYPE_DOUBLE;
if (std::holds_alternative<int>(value)) {
t = VtkTypeEnum::TYPE_INT;
}
qoi_map[key] = t;
}
}

// Sort objects
Expand Down Expand Up @@ -532,11 +577,58 @@ vtkNew<vtkPolyData> Render::createObjectMesh_(PhaseType phase) {
}
pd_mesh->GetCellData()->SetScalars(lineValuesArray);

for (auto const& [key, vtk_type] : qoi_map) {
if (vtk_type == VtkTypeEnum::TYPE_DOUBLE) {
addObjectArray<double, vtkDoubleArray>(pd_mesh, phase, key);
} else if (vtk_type == VtkTypeEnum::TYPE_INT) {
addObjectArray<int, vtkIntArray>(pd_mesh, phase, key);
}
}

fmt::print("----- Finished creating object mesh -----\n");

return pd_mesh;
}

template <typename T, typename U>
void Render::addObjectArray(
vtkNew<vtkPolyData>& pd_mesh, PhaseType phase, std::string const& key
) {
auto const num_objects = info_.getPhaseObjects(phase).size();

vtkNew<U> array;
array->SetName(key.c_str());
array->SetNumberOfTuples(num_objects);

int point_index = 0;
auto object_mapping = createObjectMapping_(phase);
for (auto const& [rankID, objects] : object_mapping) {
std::vector<std::pair<ObjectWork, uint64_t>> ordered_objects;
for (auto const& [objectID, objectWork] : objects) {
bool migratable = info_.getObjectInfo().at(objectID).isMigratable();
ordered_objects.push_back(std::make_pair(objectWork, migratable));
}
std::sort(ordered_objects.begin(), ordered_objects.end(), compareObjects);

// Add rank objects to point set
for (auto const& [objectWork, migratable] : ordered_objects) {
if (
auto it = objectWork.getUserDefined().find(key);
it != objectWork.getUserDefined().end()
) {
//fmt::print("phase={}, key={}, id={}\n", phase, key, objectWork.getID());
auto const& value = it->second;
array->SetTuple1(point_index, std::get<T>(value));
} else {
array->SetTuple1(point_index, T{});
}
point_index++;
}
}

pd_mesh->GetPointData()->AddArray(array);
}

void Render::getRgbFromTab20Colormap_(
int index, double& r, double& g, double& b) {
const std::vector<std::tuple<double, double, double>> tab20_cmap = {
Expand Down
27 changes: 27 additions & 0 deletions src/vt-tv/render/render.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,34 @@ struct Render {
*/
vtkNew<vtkPolyData> createRankMesh_(PhaseType iteration);

private:
/**
* \brief Add rank array
*
* \param[in] pd_mesh the mesh
* \param[in] phase the phase
* \param[in] key the QOI key to add
*/
template <typename T, typename U>
void addRankArray(
vtkNew<vtkPolyData>& pd_mesh, PhaseType phase, std::string const& key
);

/**
* \brief Add object array
*
* \param[in] pd_mesh the mesh
* \param[in] phase the phase
* \param[in] key the QOI key to add
*/
template <typename T, typename U>
void addObjectArray(
vtkNew<vtkPolyData>& pd_mesh, PhaseType phase, std::string const& key
);


public:
/**
* \brief Map objects to polygonal mesh.
*
* \param[in] phase phase
Expand Down
15 changes: 14 additions & 1 deletion src/vt-tv/utility/json_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,16 @@ std::unique_ptr<Info> JSONReader::parse() {
auto phases = j["phases"];
if (phases.is_array()) {
for (auto const& phase : phases) {
std::unordered_map<std::string, QOIVariantTypes> read_phase_user_defined;
auto id = phase["id"];
if (phase.find("user_defined") != phase.end()) {
auto phase_user_defined = phase["user_defined"];
if (phase_user_defined.is_object()) {
for (auto& [key, value] : phase_user_defined.items()) {
read_phase_user_defined[key] = value;
}
}
}
auto tasks = phase.value("tasks", j.array());

std::unordered_map<ElementIDType, ObjectWork> objects;
Expand All @@ -138,6 +147,7 @@ std::unique_ptr<Info> JSONReader::parse() {
auto object = task["entity"].value("id", task["entity"]["seq_id"]);
auto home = task["entity"]["home"];
bool migratable = task["entity"]["migratable"];

assert(object.is_number() && "task id or seq_id must be provided and be a number");
assert(home.is_number() && "task home must be a number");

Expand Down Expand Up @@ -258,7 +268,10 @@ std::unique_ptr<Info> JSONReader::parse() {
}
}
}
phase_info.try_emplace(id, PhaseWork{id, std::move(objects)});
phase_info.try_emplace(
id,
PhaseWork{id, std::move(objects), std::move(read_phase_user_defined)}
);
}
}

Expand Down

0 comments on commit c0264cf

Please sign in to comment.