Skip to content
Snippets Groups Projects
Commit 185bb1a8 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Finish `gnuplot_1d_writer`

Also functional in parallel
parent b7227adc
Branches
Tags
1 merge request!80Feature/writers improvement
...@@ -67,16 +67,12 @@ GnuplotWriter1D::_is_node_value(const NodeValue<const DataType>&) const ...@@ -67,16 +67,12 @@ GnuplotWriter1D::_is_node_value(const NodeValue<const DataType>&) const
return true; return true;
} }
template <size_t Dimension>
void void
GnuplotWriter1D::_writePreamble(const OutputNamedItemValueSet& output_named_item_value_set, std::ostream& fout) const GnuplotWriter1D::_writePreamble(const OutputNamedItemValueSet& output_named_item_value_set, std::ostream& fout) const
{ {
fout << "# list of data\n"; fout << "# list of data\n";
fout << "# 1:x"; fout << "# 1:x";
if constexpr (Dimension > 1) { uint64_t i = 2;
fout << " 2:y";
}
uint64_t i = Dimension + 1;
for (const auto& i_named_item_value : output_named_item_value_set) { for (const auto& i_named_item_value : output_named_item_value_set) {
const std::string name = i_named_item_value.first; const std::string name = i_named_item_value.first;
const auto& item_value_variant = i_named_item_value.second; const auto& item_value_variant = i_named_item_value.second;
...@@ -105,139 +101,135 @@ GnuplotWriter1D::_writePreamble(const OutputNamedItemValueSet& output_named_item ...@@ -105,139 +101,135 @@ GnuplotWriter1D::_writePreamble(const OutputNamedItemValueSet& output_named_item
fout << "\n\n"; fout << "\n\n";
} }
template <typename DataType> template <typename DataType, ItemType item_type>
void size_t
GnuplotWriter1D::_writeCellValue(const NodeValue<DataType>&, CellId, std::ostream&) const GnuplotWriter1D::_itemValueNbRow(const ItemValue<DataType, item_type>&) const
{}
template <typename DataType>
void
GnuplotWriter1D::_writeCellValue(const CellValue<DataType>& cell_value, CellId cell_id, std::ostream& fout) const
{ {
const auto& value = cell_value[cell_id];
if constexpr (std::is_arithmetic_v<DataType>) { if constexpr (std::is_arithmetic_v<DataType>) {
fout << ' ' << value; return 1;
} else if constexpr (is_tiny_vector_v<std::decay_t<DataType>>) { } else if constexpr (is_tiny_vector_v<std::decay_t<DataType>>) {
for (size_t i = 0; i < value.dimension(); ++i) { return DataType::Dimension;
fout << ' ' << value[i];
}
} else if constexpr (is_tiny_matrix_v<std::decay_t<DataType>>) { } else if constexpr (is_tiny_matrix_v<std::decay_t<DataType>>) {
for (size_t i = 0; i < value.nbRows(); ++i) { return DataType{}.dimension();
for (size_t j = 0; j < value.nbColumns(); ++j) {
fout << ' ' << value(i, j);
}
}
} else { } else {
throw UnexpectedError("invalid data type for cell value output: " + demangle<DataType>()); throw UnexpectedError("invalid data type for cell value output: " + demangle<DataType>());
} }
} }
template <typename MeshType> template <typename MeshType, ItemType item_type>
void void
GnuplotWriter1D::_writeCellValues(const std::shared_ptr<const MeshType>& mesh, GnuplotWriter1D::_writeItemValues(const std::shared_ptr<const MeshType>& mesh,
const OutputNamedItemValueSet& output_named_item_value_set, const OutputNamedItemValueSet& output_named_item_value_set,
std::ostream& fout) const std::ostream& fout) const
{ {
if constexpr (MeshType::Dimension == 1) { using ItemId = ItemIdT<item_type>;
auto& mesh_data = MeshDataManager::instance().getMeshData(*mesh);
const auto& cell_center = mesh_data.xj(); const size_t& number_of_columns = [&] {
for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { size_t number_of_columns = 1;
fout << cell_center[cell_id][0];
for (auto [name, item_value] : output_named_item_value_set) { for (auto [name, item_value] : output_named_item_value_set) {
std::visit([&](auto&& cell_value) { _writeCellValue(cell_value, cell_id, fout); }, item_value); std::visit([&](auto&& value) { number_of_columns += _itemValueNbRow(value); }, item_value);
}
return number_of_columns;
}();
auto is_owned = mesh->connectivity().template isOwned<item_type>();
const size_t& number_of_owned_lines = [&]() {
if (parallel::size() > 1) {
size_t number_of_owned_items = 0;
for (ItemId item_id = 0; item_id < mesh->template numberOf<item_type>(); ++item_id) {
if (is_owned[item_id]) {
++number_of_owned_items;
} }
fout << '\n';
} }
} else if constexpr (MeshType::Dimension == 2) {
auto cell_to_node_matrix = mesh->connectivity().cellToNodeMatrix();
for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { return number_of_owned_items;
std::ostringstream os; } else {
os.precision(15); return mesh->template numberOf<item_type>();
os.setf(std::ios_base::scientific); }
}();
for (auto [name, item_value] : output_named_item_value_set) { Array<double> values{number_of_columns * number_of_owned_lines};
std::visit([&](auto&& cell_value) { _writeCellValue(cell_value, cell_id, os); }, item_value);
if constexpr (item_type == ItemType::cell) {
auto& mesh_data = MeshDataManager::instance().getMeshData(*mesh);
const auto& cell_center = mesh_data.xj();
size_t index = 0;
for (ItemId item_id = 0; item_id < mesh->template numberOf<item_type>(); ++item_id) {
if (is_owned[item_id]) {
values[number_of_columns * index++] = cell_center[item_id][0];
}
} }
} else if constexpr (item_type == ItemType::node) {
const auto& node_position = mesh->xr();
const auto& cell_nodes = cell_to_node_matrix[cell_id]; size_t index = 0;
for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) { for (ItemId item_id = 0; item_id < mesh->template numberOf<item_type>(); ++item_id) {
const NodeId& node_id = cell_nodes[i_node]; if (is_owned[item_id]) {
const TinyVector<2>& xr = mesh->xr()[node_id]; values[number_of_columns * index++] = node_position[item_id][0];
fout << xr[0] << ' ' << xr[1] << ' ' << os.str() << '\n';
} }
fout << '\n';
} }
} else { } else {
throw UnexpectedError("invalid mesh dimension"); throw UnexpectedError("invalid item type");
}
} }
template <typename ValueType> size_t column_number = 1;
void for (auto [name, output_item_value] : output_named_item_value_set) {
GnuplotWriter1D::_writeNodeValue(const NodeValue<ValueType>& node_value, NodeId node_id, std::ostream& fout) const std::visit(
{ [&](auto&& item_value) {
const auto& value = node_value[node_id]; using ItemValueT = std::decay_t<decltype(item_value)>;
if constexpr (std::is_arithmetic_v<ValueType>) { if constexpr (ItemValueT::item_t == item_type) {
fout << ' ' << value; using DataT = std::decay_t<typename ItemValueT::data_type>;
} else if constexpr (is_tiny_vector_v<std::decay_t<ValueType>>) { size_t index = 0;
for (size_t i = 0; i < value.dimension(); ++i) { for (ItemId item_id = 0; item_id < item_value.size(); ++item_id) {
fout << ' ' << value[i]; if (is_owned[item_id]) {
if constexpr (std::is_arithmetic_v<DataT>) {
values[number_of_columns * index + column_number] = item_value[item_id];
} else if constexpr (is_tiny_vector_v<DataT>) {
const size_t k = number_of_columns * index + column_number;
for (size_t j = 0; j < DataT::Dimension; ++j) {
values[k + j] = item_value[item_id][j];
} }
} else if constexpr (is_tiny_matrix_v<std::decay_t<ValueType>>) { } else if constexpr (is_tiny_matrix_v<DataT>) {
for (size_t i = 0; i < value.nbRows(); ++i) { size_t k = number_of_columns * index + column_number;
for (size_t j = 0; j < value.nbColumns(); ++j) { for (size_t i = 0; i < DataT{}.nbRows(); ++i) {
fout << ' ' << value(i, j); for (size_t j = 0; j < DataT{}.nbColumns(); ++j) {
values[k++] = item_value[item_id](i, j);
} }
} }
} else {
throw UnexpectedError("invalid data type for cell value output: " + demangle<ValueType>());
} }
++index;
} }
template <typename ValueType>
void
GnuplotWriter1D::_writeNodeValue(const CellValue<ValueType>&, NodeId, std::ostream&) const
{}
template <typename MeshType>
void
GnuplotWriter1D::_writeNodeValues(const std::shared_ptr<const MeshType>& mesh,
const OutputNamedItemValueSet& output_named_item_value_set,
std::ostream& fout) const
{
if constexpr (MeshType::Dimension == 1) {
const auto& xr = mesh->xr();
for (NodeId node_id = 0; node_id < mesh->numberOfNodes(); ++node_id) {
fout << xr[node_id][0];
for (auto [name, item_value] : output_named_item_value_set) {
std::visit([&](auto&& node_value) { _writeNodeValue(node_value, node_id, fout); }, item_value);
} }
fout << '\n';
} }
} else if constexpr (MeshType::Dimension == 2) { column_number += _itemValueNbRow(item_value);
auto cell_to_node_matrix = mesh->connectivity().cellToNodeMatrix(); },
output_item_value);
}
for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { if (parallel::size() > 1) {
std::ostringstream os; values = parallel::gatherVariable(values, 0);
os.precision(15);
os.setf(std::ios_base::scientific);
const auto& cell_nodes = cell_to_node_matrix[cell_id];
for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) {
const NodeId& node_id = cell_nodes[i_node];
const TinyVector<2>& xr = mesh->xr()[node_id];
fout << xr[0] << ' ' << xr[1] << ' ' << os.str();
for (auto [name, item_value] : output_named_item_value_set) {
std::visit([&](auto&& node_value) { _writeNodeValue(node_value, node_id, os); }, item_value);
} }
fout << '\n';
if (parallel::rank() == 0) {
Assert(values.size() % number_of_columns == 0);
std::vector<size_t> line_numbers(values.size() / number_of_columns);
for (size_t i = 0; i < line_numbers.size(); ++i) {
line_numbers[i] = i;
}
std::sort(line_numbers.begin(), line_numbers.end(),
[&](size_t i, size_t j) { return values[i * number_of_columns] < values[j * number_of_columns]; });
for (auto i_line : line_numbers) {
fout << values[i_line * number_of_columns];
for (size_t j = 1; j < number_of_columns; ++j) {
fout << ' ' << values[i_line * number_of_columns + j];
} }
fout << '\n'; fout << '\n';
} }
} else {
throw UnexpectedError("invalid mesh dimension");
} }
} }
...@@ -263,19 +255,23 @@ GnuplotWriter1D::_write(const std::shared_ptr<const MeshType>& mesh, ...@@ -263,19 +255,23 @@ GnuplotWriter1D::_write(const std::shared_ptr<const MeshType>& mesh,
throw NormalError("cannot store both node and cell values in a gnuplot file"); throw NormalError("cannot store both node and cell values in a gnuplot file");
} }
std::ofstream fout(_getFilename()); std::ofstream fout;
if (parallel::rank() == 0) {
fout.open(_getFilename());
fout.precision(15); fout.precision(15);
fout.setf(std::ios_base::scientific); fout.setf(std::ios_base::scientific);
fout << _getDateAndVersionComment(); fout << _getDateAndVersionComment();
fout << "\n# time = " << time << "\n\n"; fout << "# time = " << time << "\n\n";
_writePreamble<MeshType::Dimension>(output_named_item_value_set, fout); _writePreamble(output_named_item_value_set, fout);
}
if (has_cell_value) { if (has_cell_value) {
this->_writeCellValues(mesh, output_named_item_value_set, fout); this->_writeItemValues<MeshType, ItemType::cell>(mesh, output_named_item_value_set, fout);
} else { // has_node_value } else { // has_node_value
this->_writeNodeValues(mesh, output_named_item_value_set, fout); this->_writeItemValues<MeshType, ItemType::node>(mesh, output_named_item_value_set, fout);
} }
} }
......
...@@ -30,29 +30,14 @@ class GnuplotWriter1D : public WriterBase ...@@ -30,29 +30,14 @@ class GnuplotWriter1D : public WriterBase
template <typename DataType> template <typename DataType>
bool _is_node_value(const NodeValue<const DataType>&) const; bool _is_node_value(const NodeValue<const DataType>&) const;
template <typename DataType> template <typename DataType, ItemType item_type>
void _writeCellValue(const CellValue<DataType>& cell_value, CellId cell_id, std::ostream& fout) const; size_t _itemValueNbRow(const ItemValue<DataType, item_type>&) const;
template <typename DataType>
void _writeCellValue(const NodeValue<DataType>& node_value, CellId cell_id, std::ostream& fout) const;
template <typename MeshType>
void _writeCellValues(const std::shared_ptr<const MeshType>& mesh,
const OutputNamedItemValueSet& output_named_item_value_set,
std::ostream& fout) const;
template <typename DataType>
void _writeNodeValue(const CellValue<DataType>& cell_value, NodeId cell_id, std::ostream& fout) const;
template <typename DataType> template <typename MeshType, ItemType item_type>
void _writeNodeValue(const NodeValue<DataType>& node_value, NodeId cell_id, std::ostream& fout) const; void _writeItemValues(const std::shared_ptr<const MeshType>& mesh,
template <typename MeshType>
void _writeNodeValues(const std::shared_ptr<const MeshType>& mesh,
const OutputNamedItemValueSet& output_named_item_value_set, const OutputNamedItemValueSet& output_named_item_value_set,
std::ostream& fout) const; std::ostream& fout) const;
template <size_t Dimension>
void _writePreamble(const OutputNamedItemValueSet& output_named_item_value_set, std::ostream& fout) const; void _writePreamble(const OutputNamedItemValueSet& output_named_item_value_set, std::ostream& fout) const;
template <typename MeshType> template <typename MeshType>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment