gctl/lib/io/gmsh_io.h
2025-01-10 16:34:55 +08:00

3733 lines
109 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see <http://www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#ifndef _GCTL_GMSH_IO_H
#define _GCTL_GMSH_IO_H
// library's head files
#include "../core.h"
#include "../geometry.h"
#include "../utility.h"
#ifdef GCTL_EIGEN
#include "Eigen/Dense"
#endif // GCTL_EIGEN
namespace gctl
{
struct gmsh_physical_group
{
size_t dim_tag, phys_tag;
std::string name;
};
/**
* @brief Gmsh文件的IO类主要为调用下面定义的全局函数
*/
class gmshio
{
public:
gmshio();
gmshio(std::string filename, file_direction_e f_direct);
virtual ~gmshio();
void init_file(std::string filename, file_direction_e f_direct);
void reset_file(std::string filename, file_direction_e f_direct);
void set_packed(index_packed_e is_packed, file_direction_e f_direct);
bool initialized(file_direction_e f_direct);
void read_physical_groups(array<gmsh_physical_group> &phy_groups);
void save_physical_groups(const array<gmsh_physical_group> &phy_groups);
int physical_name2tag(const array<gmsh_physical_group> &phy_groups, std::string name);
template <typename A> void read_node(array<vertex<point2dc, A>> &out_nodes);
template <typename A> void read_node(array<vertex<point3dc, A>> &out_nodes);
template <typename E, typename A> void read_element(array<type_triangle2d<E>> &out_elements, const array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_triangle2d2o<E>> &out_elements, const array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_rectangle2d<E>> &out_elements, const array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_node<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_edge<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_triangle<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_tetrahedron<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_block<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_tricone<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_element(array<type_prism<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_triangle2d<E>> &out_elements, array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_triangle2d2o<E>> &out_elements, array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_rectangle2d<E>> &out_elements, array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_node<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_edge<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_triangle<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_tetrahedron<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_block<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_tricone<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename E, typename A> void read_mesh(array<type_prism<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag = nullptr);
template <typename T> void read_data(array<T> &out_data, std::string data_name = "");
template <typename T> void read_data(array<T> &out_data, array<size_t> &out_index, std::string data_name = "");
template <typename T> void read_data(std::vector<std::vector<T> > &out_data, std::vector<std::string> &out_name,
mesh_data_type_e d_type, std::vector<std::vector<size_t> > *out_index = nullptr);
template <typename E, typename A> void save_mesh(const array<type_triangle2d<E>> &element, const array<vertex<point2dc, A>> &node);
template <typename E, typename A> void save_mesh(const array<type_triangle2d2o<E>> &element, const array<vertex<point2dc, A>> &node);
template <typename E, typename A> void save_mesh(const array<type_rectangle2d<E>> &element, const array<vertex<point2dc, A>> &node);
template <typename E, typename A> void save_mesh(const array<type_triangle<E>> &element, const array<vertex<point3dc, A>> &node, array<bool> *out_ele_tag = nullptr, array<bool> *out_node_tag = nullptr);
template <typename E, typename A> void save_mesh(const array<type_tetrahedron<E>> &element, const array<vertex<point3dc, A>> &node, array<bool> *output_tag = nullptr);
template <typename E, typename A> void save_mesh(const array<type_block<E>> &element, const array<vertex<point3dc, A>> &node);
template <typename E, typename A> void save_mesh(const array<type_tricone<E>> &element, const array<vertex<point3dc, A>> &node);
template <typename E, typename A> void save_mesh(const array<type_prism<E>> &element, const array<vertex<point3dc, A>> &node);
template <typename E> void save_mesh(const array<type_tetrahedron<E>> &element);
template <typename T> void save_data(std::string dataname, const T *in_data, size_t in_size, mesh_data_type_e datatype, const size_t *in_index = nullptr);
template <typename T> void save_data(std::string dataname, const array<T> &in_data, mesh_data_type_e datatype, const array<size_t> *in_index = nullptr);
template <typename T> void save_data(std::string dataname, const std::vector<T> &in_data, mesh_data_type_e datatype, const std::vector<size_t> *in_index = nullptr);
template <typename T> void save_data(std::string dataname, const array<point3c<T>> &in_data, mesh_data_type_e datatype, const array<size_t> *in_index = nullptr);
template <typename T> void save_data(std::string dataname, const std::vector<point3c<T>> &in_data, mesh_data_type_e datatype, const std::vector<size_t> *in_index = nullptr);
#ifdef GCTL_EIGEN
template <typename T> void save_data(std::string dataname, const Eigen::Matrix<T, Eigen::Dynamic, 1> &in_data, mesh_data_type_e datatype, const Eigen::Matrix<T, Eigen::Dynamic, 1> *in_index = nullptr);
#endif // GCTL_EIGEN
template <typename E> void element_register(const array<type_triangle2d<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_triangle2d2o<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_rectangle2d<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_node<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_triangle<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_tetrahedron<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_block<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_tricone<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename E> void element_register(const array<type_prism<E>> &element, const _2i_matrix *tag_ptr = nullptr, array<size_t> *rgst_index = nullptr);
template <typename A> void save_registered_mesh(const array<vertex<point2dc, A>> &node, array<gmsh_physical_group> *phys_ptr = nullptr);
template <typename A> void save_registered_mesh(const array<vertex<point3dc, A>> &node, array<gmsh_physical_group> *phys_ptr = nullptr);
protected:
std::ifstream gmsh_in; // Input stream
std::ofstream gmsh_out; // Output stream
index_packed_e in_packed, out_packed; // Whether the input/output node indexes are starting from zero
std::vector<std::vector<int> > rgst_elem; // registered elements
};
template <typename A>
void gmshio::read_node(array<vertex<point2dc, A>> &out_nodes)
{
initialized(Input);
read_gmsh_node(gmsh_in, out_nodes, in_packed);
return;
}
template <typename A>
void gmshio::read_node(array<vertex<point3dc, A>> &out_nodes)
{
initialized(Input);
read_gmsh_node(gmsh_in, out_nodes, in_packed);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_triangle2d<E>> &out_elements, const array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_triangle2d2o<E>> &out_elements, const array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_rectangle2d<E>> &out_elements, const array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_node<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_edge<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_triangle<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_tetrahedron<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_block<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_tricone<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_element(array<type_prism<E>> &out_elements, const array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
initialized(Input);
read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_triangle2d<E>> &out_elements, array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_triangle2d2o<E>> &out_elements, array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_rectangle2d<E>> &out_elements, array<vertex<point2dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_node<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_edge<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_triangle<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_tetrahedron<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_block<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_tricone<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename E, typename A>
void gmshio::read_mesh(array<type_prism<E>> &out_elements, array<vertex<point3dc, A>> &nodes, _2i_vector *ele_tag)
{
read_node(nodes);
read_element(out_elements, nodes, ele_tag);
return;
}
template <typename T>
void gmshio::read_data(array<T> &out_data, std::string data_name)
{
initialized(Input);
read_gmsh_data(gmsh_in, out_data, data_name);
return;
}
template <typename T>
void gmshio::read_data(array<T> &out_data, array<size_t> &out_index, std::string data_name)
{
initialized(Input);
read_gmsh_data(gmsh_in, out_data, out_index, data_name, in_packed);
return;
}
template <typename T>
void gmshio::read_data(std::vector<std::vector<T> > &out_data, std::vector<std::string> &out_name,
mesh_data_type_e d_type, std::vector<std::vector<size_t> > *out_index)
{
initialized(Input);
read_gmsh_data(gmsh_in, out_data, out_name, d_type, out_index, in_packed);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_triangle2d<E>> &element, const array<vertex<point2dc, A>> &node)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_triangle2d2o<E>> &element, const array<vertex<point2dc, A>> &node)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_rectangle2d<E>> &element, const array<vertex<point2dc, A>> &node)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_triangle<E>> &element, const array<vertex<point3dc, A>> &node,
array<bool> *out_ele_tag, array<bool> *out_node_tag)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed, out_ele_tag, out_node_tag);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_tetrahedron<E>> &element, const array<vertex<point3dc, A>> &node, array<bool> *output_tag)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed, output_tag);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_block<E>> &element, const array<vertex<point3dc, A>> &node)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_tricone<E>> &element, const array<vertex<point3dc, A>> &node)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed);
return;
}
template <typename E, typename A>
void gmshio::save_mesh(const array<type_prism<E>> &element, const array<vertex<point3dc, A>> &node)
{
initialized(Output);
save2gmsh(gmsh_out, element, node, out_packed);
return;
}
template <typename E>
void gmshio::save_mesh(const array<type_tetrahedron<E>> &element)
{
initialized(Output);
save2gmsh(gmsh_out, element, out_packed);
return;
}
template <typename T>
void gmshio::save_data(std::string dataname, const T *in_data, size_t in_size, mesh_data_type_e datatype, const size_t *in_index)
{
initialized(Output);
save_gmsh_data(gmsh_out, dataname, in_data, in_size, datatype, out_packed, in_index);
return;
}
template <typename T>
void gmshio::save_data(std::string dataname, const array<T> &in_data, mesh_data_type_e datatype, const array<size_t> *in_index)
{
initialized(Output);
save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index);
return;
}
template <typename T>
void gmshio::save_data(std::string dataname, const std::vector<T> &in_data, mesh_data_type_e datatype, const std::vector<size_t> *in_index)
{
initialized(Output);
save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index);
return;
}
template <typename T>
void gmshio::save_data(std::string dataname, const array<point3c<T>> &in_data, mesh_data_type_e datatype, const array<size_t> *in_index)
{
initialized(Output);
save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index);
return;
}
template <typename T>
void gmshio::save_data(std::string dataname, const std::vector<point3c<T>> &in_data, mesh_data_type_e datatype, const std::vector<size_t> *in_index)
{
initialized(Output);
save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index);
return;
}
#ifdef GCTL_EIGEN
template <typename T>
void gmshio::save_data(std::string dataname, const Eigen::Matrix<T, Eigen::Dynamic, 1> &in_data, mesh_data_type_e datatype, const Eigen::Matrix<T, Eigen::Dynamic, 1> *in_index)
{
initialized(Output);
save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index);
return;
}
#endif // GCTL_EIGEN
template <typename E>
void gmshio::element_register(const array<type_triangle2d<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(5 + c_size);
tmp_elem[0] = 2; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 3; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(5);
tmp_elem[0] = 2; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 3; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_triangle2d2o<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(8 + c_size);
tmp_elem[0] = 9; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 6; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(8);
tmp_elem[0] = 9; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 6; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_rectangle2d<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(6 + c_size);
tmp_elem[0] = 3; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 4; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(6);
tmp_elem[0] = 3; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 4; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_node<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(3 + c_size);
tmp_elem[0] = 15; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
tmp_elem[2+c_size] = element[i].vert[0]->id;
if (out_packed == NotPacked) tmp_elem[2+c_size] += 1;
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(3);
tmp_elem[0] = 15; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
tmp_elem[2] = element[i].vert[0]->id;
if (out_packed == NotPacked) tmp_elem[2] += 1;
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_triangle<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(5 + c_size);
tmp_elem[0] = 2; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 3; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(5);
tmp_elem[0] = 2; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 3; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_tetrahedron<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(6 + c_size);
tmp_elem[0] = 4; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 4; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(6);
tmp_elem[0] = 4; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 4; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_block<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(10 + c_size);
tmp_elem[0] = 5; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 8; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(10);
tmp_elem[0] = 5; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 8; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_tricone<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(6 + c_size);
tmp_elem[0] = 4; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 4; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(6);
tmp_elem[0] = 4; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 4; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename E>
void gmshio::element_register(const array<type_prism<E>> &element, const _2i_matrix *tag_ptr, array<size_t> *rgst_index)
{
if (tag_ptr != nullptr && tag_ptr->row_size() != element.size())
{
throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)");
}
if (rgst_index != nullptr) rgst_index->resize(element.size());
rgst_elem.reserve(rgst_elem.size() + element.size());
std::vector<int> tmp_elem;
if (tag_ptr != nullptr)
{
size_t c_size = tag_ptr->col_size();
tmp_elem.resize(8 + c_size);
tmp_elem[0] = 6; tmp_elem[1] = c_size;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < c_size; j++)
{
tmp_elem[j+2] = tag_ptr->at(i, j);
}
for (size_t j = 0; j < 6; j++)
{
tmp_elem[j+2+c_size] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
else
{
tmp_elem.resize(8);
tmp_elem[0] = 6; tmp_elem[1] = 0;
for (size_t i = 0; i < element.size(); i++)
{
for (size_t j = 0; j < 6; j++)
{
tmp_elem[j+2] = element[i].vert[j]->id;
if (out_packed == NotPacked) tmp_elem[j+2] += 1;
}
if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size();
rgst_elem.push_back(tmp_elem);
}
}
return;
}
template <typename A>
void gmshio::save_registered_mesh(const array<vertex<point2dc, A>> &node, array<gmsh_physical_group> *phys_ptr)
{
initialized(Output);
if (rgst_elem.empty())
{
throw runtime_error("No registered elemets found. From gmshio::save_registered_mesh(...)");
}
// save head info
// 将文件指针重置到文件头 保险一点
gmsh_out.clear(std::ios::goodbit);
gmsh_out.seekp(0, std::ios::beg);
gmsh_out << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
if (phys_ptr != nullptr)
{
gmsh_out << "$PhysicalNames\n";
gmsh_out << phys_ptr->size() << "\n";
for (size_t i = 0; i < phys_ptr->size(); i++)
{
gmsh_out << phys_ptr->at(i).dim_tag << " " << phys_ptr->at(i).phys_tag << " \"" << phys_ptr->at(i).name << "\"\n";
}
gmsh_out << "$EndPhysicalNames\n";
}
// save node
save2gmsh_node(gmsh_out, node.get(), node.size(), out_packed);
// save elements
gmsh_out << "$Elements" << std::endl << rgst_elem.size() <<std::endl;
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
for (int i = 0; i < rgst_elem.size(); i++)
{
if (out_packed == Packed) gmsh_out << i;
else gmsh_out << i+1;
for (size_t j = 0; j < rgst_elem[i].size(); j++)
{
gmsh_out << " " << rgst_elem[i][j];
}
gmsh_out << std::endl;
}
gmsh_out << "$EndElements"<< std::endl;
return;
}
template <typename A>
void gmshio::save_registered_mesh(const array<vertex<point3dc, A>> &node, array<gmsh_physical_group> *phys_ptr)
{
initialized(Output);
if (rgst_elem.empty())
{
throw runtime_error("No registered elemets found. From gmshio::save_registered_mesh(...)");
}
// save head info
// 将文件指针重置到文件头 保险一点
gmsh_out.clear(std::ios::goodbit);
gmsh_out.seekp(0, std::ios::beg);
gmsh_out << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
if (phys_ptr != nullptr)
{
gmsh_out << "$PhysicalNames\n";
gmsh_out << phys_ptr->size() << "\n";
for (size_t i = 0; i < phys_ptr->size(); i++)
{
gmsh_out << phys_ptr->at(i).dim_tag << " " << phys_ptr->at(i).phys_tag << " \"" << phys_ptr->at(i).name << "\"\n";
}
gmsh_out << "$EndPhysicalNames\n";
}
// save node
save2gmsh_node(gmsh_out, node.get(), node.size(), out_packed);
// save elements
gmsh_out << "$Elements" << std::endl << rgst_elem.size() <<std::endl;
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
for (int i = 0; i < rgst_elem.size(); i++)
{
if (out_packed == Packed) gmsh_out << i;
else gmsh_out << i+1;
for (size_t j = 0; j < rgst_elem[i].size(); j++)
{
gmsh_out << " " << rgst_elem[i][j];
}
gmsh_out << std::endl;
}
gmsh_out << "$EndElements"<< std::endl;
return;
}
/**
* @brief Read nodes from a Gmsh file.
*
* @param[in] infile The input file stream
* @param node The output node array
* @param[in] packed Indicates whether the index in the node file starts from zero. The
* index is deemed to be started with one if this option is false. The default value of this
* variable is true.
*
*/
template <typename A>
void read_gmsh_node(std::ifstream &infile, array<vertex<point2dc, A>> &node, index_packed_e packed = Packed)
{
// 重置数据
if (!node.empty()) node.clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int n_size = 0;
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Nodes") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile, tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> n_size; //第一个数为顶点的个数
node.resize(n_size);
for (int i = 0; i < n_size; i++)
{
getline(infile, tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> node[i].id >> node[i].x >> node[i].y;
if (packed == NotPacked)
node[i].id -= 1;
}
break;
}
}
return;
}
/**
* @brief Read nodes from a Gmsh file.
*
* @param[in] infile The input file stream
* @param node an array<vertex3dc> object
* @param[in] packed Indicates whether the index in the node file starts from zero. The
* index is deemed to be started with one if this option is false. The default value of this
* variable is true.
*
*/
template <typename A>
void read_gmsh_node(std::ifstream &infile, array<vertex<point3dc, A>> &node, index_packed_e packed = Packed)
{
// 重置数据
if (!node.empty()) node.clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int n_size = 0;
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Nodes") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> n_size; //第一个数为顶点的个数
node.resize(n_size);
for (int i = 0; i < n_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> node[i].id >> node[i].x >> node[i].y >> node[i].z;
if (packed == NotPacked)
node[i].id -= 1;
}
break;
}
}
return;
}
/**
* @brief Read element index from a Gmsh file.
*
* @param[in] infile The input file stream
* @param element The output element object array
* @param node The node array
* @param[in] packed Indicates whether the index in the node file starts from zero. The
* index is deemed to be started with one if this option is false. The default value of this
* variable is true.
* @param[in] ele_tag Return elements' tags by a 2D integer vector.
*
*/
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_triangle2d<E>> &element,
const array<vertex<point2dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[3];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
triangle2d tmp_tri;
std::vector<triangle2d> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 2)
{
tmp_tri.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2];
if (packed == NotPacked)
{
for (int j = 0; j < 3; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]-1);
}
else
{
for (int j = 0; j < 3; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]);
}
element_vec.push_back(tmp_tri);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 3; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
/**
* @brief Read element index from a Gmsh file.
*
* @param[in] infile The input file stream
* @param element The output element object array
* @param node The node array
* @param[in] packed Indicates whether the index in the node file starts from zero. The
* index is deemed to be started with one if this option is false. The default value of this
* variable is true.
* @param[in] ele_tag Return elements' tags by a 2D integer vector.
*
*/
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_triangle2d2o<E>> &element,
const array<vertex<point2dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[6];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
triangle2d2o tmp_tri;
std::vector<triangle2d2o> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 9)
{
tmp_tri.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2]
>> tmp_index[3] >> tmp_index[4] >> tmp_index[5];
if (packed == NotPacked)
{
for (int j = 0; j < 3; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]-1);
tmp_tri.vert[5] = node.get(tmp_index[3]-1);
tmp_tri.vert[3] = node.get(tmp_index[4]-1);
tmp_tri.vert[4] = node.get(tmp_index[5]-1);
}
else
{
for (int j = 0; j < 3; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]);
tmp_tri.vert[5] = node.get(tmp_index[3]);
tmp_tri.vert[3] = node.get(tmp_index[4]);
tmp_tri.vert[4] = node.get(tmp_index[5]);
}
element_vec.push_back(tmp_tri);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 6; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_rectangle2d<E>> &element,
const array<vertex<point2dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[4];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
rectangle2d tmp_rect;
std::vector<rectangle2d> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 3)
{
tmp_rect.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2] >> tmp_index[3];
if (packed == NotPacked)
{
tmp_rect.dl = node.get(tmp_index[0]-1);
tmp_rect.ur = node.get(tmp_index[2]-1);
for (int j = 0; j < 4; j++)
{
tmp_rect.vert[j] = node.get(tmp_index[j]-1);
}
}
else
{
tmp_rect.dl = node.get(tmp_index[0]);
tmp_rect.ur = node.get(tmp_index[2]);
for (int j = 0; j < 4; j++)
tmp_rect.vert[j] = node.get(tmp_index[j]);
}
element_vec.push_back(tmp_rect);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
element[i].dl = element_vec[i].dl;
element[i].ur = element_vec[i].ur;
for (int j = 0; j < 4; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_node<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index;
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
enode tmp_node;
std::vector<enode> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 15)
{
tmp_node.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index;
if (packed == NotPacked) tmp_node.vert[0] = node.get(tmp_index-1);
else tmp_node.vert[0] = node.get(tmp_index);
element_vec.push_back(tmp_node);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
element[i].vert[0] = element_vec[i].vert[0];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_edge<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[2];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
edge tmp_tri;
std::vector<edge> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 1)
{
tmp_tri.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1];
if (packed == NotPacked)
{
for (int j = 0; j < 2; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]-1);
}
else
{
for (int j = 0; j < 2; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]);
}
element_vec.push_back(tmp_tri);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 2; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_triangle<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[3];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
triangle tmp_tri;
std::vector<triangle> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 2)
{
tmp_tri.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2];
if (packed == NotPacked)
{
for (int j = 0; j < 3; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]-1);
}
else
{
for (int j = 0; j < 3; j++)
tmp_tri.vert[j] = node.get(tmp_index[j]);
}
element_vec.push_back(tmp_tri);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 3; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_tetrahedron<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[4];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
tetrahedron tmp_tet;
std::vector<tetrahedron> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 4)
{
tmp_tet.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2] >> tmp_index[3];
if (packed == NotPacked)
{
for (int j = 0; j < 4; j++)
tmp_tet.vert[j] = node.get(tmp_index[j]-1);
}
else
{
for (int j = 0; j < 4; j++)
tmp_tet.vert[j] = node.get(tmp_index[j]);
}
element_vec.push_back(tmp_tet);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 4; j++)
{
element[i].vert[j] = element_vec[i].vert[j];
}
element[i].deter_vert_order();
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_block<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[8];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile,tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
block tmp_block;
std::vector<block> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 5)
{
tmp_block.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
for (int a = 0; a < 8; a++)
tmp_ss >> tmp_index[a];
if (packed == NotPacked)
{
tmp_block.dl = node.get(tmp_index[0]-1);
tmp_block.ur = node.get(tmp_index[6]-1);
for (int j = 0; j < 8; j++)
{
tmp_block.vert[j] = node.get(tmp_index[j]-1);
}
}
else
{
tmp_block.dl = node.get(tmp_index[0]);
tmp_block.ur = node.get(tmp_index[6]);
for (int j = 0; j < 8; j++)
{
tmp_block.vert[j] = node.get(tmp_index[j]);
}
}
element_vec.push_back(tmp_block);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
element[i].dl = element_vec[i].dl;
element[i].ur = element_vec[i].ur;
for (int j = 0; j < 8; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_tricone<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[3];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile, tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
tri_cone tmp_cone;
std::vector<tri_cone> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 2)
{
tmp_cone.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2];
if (packed == NotPacked)
{
for (int j = 0; j < 3; j++)
{
tmp_cone.vert[j] = node.get(tmp_index[j]-1);
}
}
else
{
for (int j = 0; j < 3; j++)
{
tmp_cone.vert[j] = node.get(tmp_index[j]);
}
}
element_vec.push_back(tmp_cone);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 3; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
template <typename E, typename A>
void read_gmsh_element(std::ifstream &infile, array<type_prism<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
_2i_vector *ele_tag = nullptr)
{
if (node.empty())
throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)");
// 重置数据
if (!element.empty()) element.clear();
// 重置标签
if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear();
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
int i_size = 0, ele_count = 0;
int tmp_int, ele_type, attri_num;
int tmp_index[6];
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile, tmp_str))
{
if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> i_size; //第一个数为顶点的个数
// 我们先用一个临时的向量来储存元素
prism tmp_prism;
std::vector<prism> element_vec;
std::vector<int> tmp_tag;
for (int i = 0; i < i_size; i++)
{
getline(infile,tmp_str);
str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> ele_type >> attri_num;
if (ele_type == 6)
{
tmp_prism.id = ele_count;
tmp_tag.clear();
for (int a = 0; a < attri_num; a++)
{
tmp_ss >> tmp_int;
tmp_tag.push_back(tmp_int);
}
if (ele_tag != nullptr)
ele_tag->push_back(tmp_tag);
tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2]
>> tmp_index[3] >> tmp_index[4] >> tmp_index[5];
if (packed == NotPacked)
{
for (int j = 0; j < 6; j++)
{
tmp_prism.vert[j] = node.get(tmp_index[j]-1);
}
}
else
{
for (int j = 0; j < 6; j++)
{
tmp_prism.vert[j] = node.get(tmp_index[j]);
}
}
element_vec.push_back(tmp_prism);
ele_count++;
}
}
//将元素转移到向量上来
element.resize(element_vec.size());
for (int i = 0; i < element.size(); i++)
{
element[i].id = element_vec[i].id;
for (int j = 0; j < 6; j++)
element[i].vert[j] = element_vec[i].vert[j];
}
destroy_vector(element_vec);
break;
}
}
return;
}
/**
* @brief Read data block from a Gmsh .msh file.
*
* @param infile The input file stream
* @param out_data Output data name
* @param[in] data_name Name of the data block that will be output. The first data block will
* be output if this no data name is given.
*/
template <typename T>
void read_gmsh_data(std::ifstream &infile, array<T> &out_data, std::string data_name = "")
{
std::string requst_name = "";
if (data_name != "")
requst_name = "\"" + data_name + "\"";
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
bool data_found = false;
int tmp_int, data_size;
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile, tmp_str))
{
if (tmp_str == "$NodeData" || tmp_str == "$ElementData")
{
//先读入元素块的名称 添加到数组
for (int i = 0; i < 2; i++)
getline(infile, tmp_str);
if (requst_name == "" || requst_name == tmp_str)
{
data_found = true;
//跳过元素属性前面的值 最后一次为当前元素块的个数
for (int i = 0; i < 6; i++)
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> data_size;
out_data.resize(data_size);
for (int i = 0; i < data_size; i++)
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> out_data[i];
}
break;
}
}
}
if (!data_found)
{
throw runtime_error("data not found for: " + data_name + ". From void gctl::read_gmsh_data(..)");
}
return;
}
/**
* @brief Read data block from a Gmsh .msh file.
*
* @param infile The input file stream
* @param out_data Output data name
* @param out_index Output data index
* @param[in] data_name Name of the data block that will be output. The first data block will
* be output if this no data name is given.
* @param[in] packed Indicates whether the index in the node file starts from zero. The
* index is deemed to be started with one if this option is false. The default value of this
* variable is true.
*/
template <typename T>
void read_gmsh_data(std::ifstream &infile, array<T> &out_data, array<size_t> &out_index,
std::string data_name = "", index_packed_e packed = Packed)
{
std::string requst_name = "";
if (data_name != "")
requst_name = "\"" + data_name + "\"";
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
bool data_found = false;
int tmp_int, data_size;
std::string tmp_str;
std::stringstream tmp_ss;
while(getline(infile, tmp_str))
{
if (tmp_str == "$NodeData" || tmp_str == "$ElementData")
{
//先读入元素块的名称 添加到数组
for (int i = 0; i < 2; i++)
getline(infile, tmp_str);
if (requst_name == "" || requst_name == tmp_str)
{
data_found = true;
//跳过元素属性前面的值 最后一次为当前元素块的个数
for (int i = 0; i < 6; i++)
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> data_size;
out_data.resize(data_size);
out_index.resize(data_size, -1);
for (int i = 0; i < data_size; i++)
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> out_index[i] >> out_data[i];
}
if (packed == NotPacked)
{
for (int i = 0; i < data_size; i++)
out_index[i] -= 1;
}
break;
}
}
}
if (!data_found)
{
throw runtime_error("data not found for: " + data_name + ". From void gctl::read_gmsh_data(..)");
}
return;
}
template <typename T>
void read_gmsh_data(std::ifstream &infile, std::vector<std::vector<T> > &out_data,
std::vector<std::string> &out_name, mesh_data_type_e d_type,
std::vector<std::vector<size_t> > *out_index = nullptr, index_packed_e packed = NotPacked)
{
// 将文件指针重置到文件头
infile.clear(std::ios::goodbit);
infile.seekg(std::ios::beg);
std::string tar_str;
if (d_type == NodeData) tar_str = "$NodeData";
else if (d_type == ElemData) tar_str = "$ElementData";
else throw std::runtime_error("Invalid mesh data type. From gctl::read_gmsh_data(...)");
int tmp_int, data_size;
std::string tmp_str;
std::stringstream tmp_ss;
std::vector<T> tmp_data;
std::vector<size_t> tmp_index;
while(getline(infile, tmp_str))
{
if (tmp_str == tar_str)
{
//先读入元素块的名称 添加到数组
for (int i = 0; i < 2; i++)
getline(infile, tmp_str);
tmp_str.erase(0, 1); // 删除第一个引号
tmp_str.erase(tmp_str.end() - 1); // 删除末尾的引号
out_name.push_back(tmp_str);
//跳过元素属性前面的值 最后一次为当前元素块的个数
for (int i = 0; i < 6; i++)
getline(infile, tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> data_size;
tmp_data.clear();
tmp_data.resize(data_size, 0.0);
if(out_index != nullptr)
{
tmp_index.clear();
tmp_index.resize(data_size);
for (int i = 0; i < data_size; i++)
{
getline(infile, tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_index[i] >> tmp_data[i];
}
if (packed == NotPacked)
{
for (size_t i = 0; i < data_size; i++)
{
tmp_index[i] -= 1;
}
}
out_data.push_back(tmp_data);
out_index->push_back(tmp_index);
}
else
{
for (int i = 0; i < data_size; i++)
{
getline(infile,tmp_str);
gctl::str2ss(tmp_str, tmp_ss);
tmp_ss >> tmp_int >> tmp_data[i];
}
out_data.push_back(tmp_data);
}
}
}
return;
}
/**
* @brief Save Gmsh node block.
*
* @warning This function is designed for internal usage. Don't call this function directly.
*
* @tparam A Attribute type of the vertex
* @param outfile Output file stream
* @param node_x Pointer of the node array
* @param node_size Size of the node array
* @param packed Whether the nodes' indexes start from zero (Packed) or one (NotPacked)
* @param output_tag Whether to output indexed vertex. A vertex will not be output if the tag is false.
* Note that passing a output_tag array will reset index of associated vertexes. Use this will caution.
*/
template <typename A>
void save2gmsh_node(std::ofstream &outfile, vertex<point2dc, A> *node_x, int node_size,
index_packed_e packed = Packed, bool *output_tag = nullptr)
{
// 将文件指针重置到文件尾
outfile.clear(std::ios::goodbit);
outfile.seekp(0, std::ios::end);
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
if (packed == Packed)
{
if (output_tag != nullptr)
{
int valid_count = 0;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i]) valid_count++;
}
int valid_id = 0;
outfile << "$Nodes" << std::endl << valid_count << std::endl;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i])
{
node_x[i].id = valid_id; valid_id++;
outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl;
}
}
}
else
{
outfile << "$Nodes" << std::endl << node_size << std::endl;
for (int i = 0; i < node_size; i++)
{
outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl;
}
}
}
else
{
if (output_tag != nullptr)
{
int valid_count = 0;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i]) valid_count++;
}
int valid_id = 0;
outfile << "$Nodes" << std::endl << valid_count << std::endl;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i])
{
node_x[i].id = valid_id; valid_id++;
outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl;
}
}
}
else
{
outfile << "$Nodes" << std::endl << node_size << std::endl;
for (int i = 0; i < node_size; i++)
{
outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl;
}
}
}
outfile<<"$EndNodes"<<std::endl;
return;
}
/**
* @brief Save Gmsh node block.
*
* @warning This function is designed for internal usage. Don't call this function directly.
*
* @tparam A Attribute type of the vertex
* @param outfile Output file stream
* @param node_x Pointer of the node array
* @param node_size Size of the node array
* @param packed Whether the nodes' indexes start from zero (Packed) or one (NotPacked)
* @param output_tag Whether to output indexed vertex. A vertex will not be output if the tag is false.
* Note that passing a output_tag array will reset index of associated vertexes. Use this will caution.
*/
template <typename A>
void save2gmsh_node(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
index_packed_e packed = Packed, bool *output_tag = nullptr)
{
// 将文件指针重置到文件尾
outfile.clear(std::ios::goodbit);
outfile.seekp(0, std::ios::end);
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
if (packed == Packed)
{
if (output_tag != nullptr)
{
int valid_count = 0;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i]) valid_count++;
}
int valid_id = 0;
outfile << "$Nodes" << std::endl << valid_count << std::endl;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i])
{
node_x[i].id = valid_id; valid_id++;
outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl;
}
}
}
else
{
outfile << "$Nodes" << std::endl << node_size << std::endl;
for (int i = 0; i < node_size; i++)
{
outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl;
}
}
}
else
{
if (output_tag != nullptr)
{
int valid_count = 0;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i]) valid_count++;
}
int valid_id = 0;
outfile << "$Nodes" << std::endl << valid_count << std::endl;
for (int i = 0; i < node_size; i++)
{
if (output_tag[i])
{
node_x[i].id = valid_id; valid_id++;
outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl;
}
}
}
else
{
outfile << "$Nodes" << std::endl << node_size << std::endl;
for (int i = 0; i < node_size; i++)
{
outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl;
}
}
}
outfile << "$EndNodes" << std::endl;
return;
}
/**
* @brief Save 2D/3D meshes to a Gmsh's mesh file.
*
* @param[in] outfile Output file stream.
* @param[in] node_x The vertex2dc array of nodes' coordinates.
* @param[in] node_size The number of node.
* @param[in] ele_index The triangle2d array of element's index.
* @param[in] ele_size The number of element.
* @param[in] pack Indicates whether to set the starting index of nodes to zero. The
* node's ordering will start with one if this option is false. The default value of this
* variable is true.
*
* @return status of the function.
*/
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point2dc, A> *node_x, int node_size,
const type_triangle2d<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size <<std::endl;
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
/**
* @brief Save 2D/3D meshes to a Gmsh's mesh file.
*
* @param[in] outfile Output file stream.
* @param[in] node_x The vertex2dc array of nodes' coordinates.
* @param[in] node_size The number of node.
* @param[in] ele_index The triangle2d2o array of element's index.
* @param[in] ele_size The number of element.
* @param[in] pack Indicates whether to set the starting index of nodes to zero. The
* node's ordering will start with one if this option is false. The default value of this
* variable is true.
*
* @return status of the function.
*/
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point2dc, A> *node_x, int node_size,
const type_triangle2d2o<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size <<std::endl;
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 9 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << " " << ele_index[i].vert[5]->id;
outfile << " " << ele_index[i].vert[3]->id;
outfile << " " << ele_index[i].vert[4]->id;
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 9 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << " " << ele_index[i].vert[5]->id + 1;
outfile << " " << ele_index[i].vert[3]->id + 1;
outfile << " " << ele_index[i].vert[4]->id + 1;
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point2dc, A> *node_x, int node_size,
const type_rectangle2d<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 3 0";
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 3 0";
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
const type_triangle<E> *ele_index, int ele_size, index_packed_e packed = Packed,
bool *out_ele_tag = nullptr, bool *out_node_tag = nullptr)
{
// Set the file stream to the head
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
// Output head info
outfile << "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n";
// Count for valid output elements if out_ele_tag is not nullptr
if (out_ele_tag != nullptr && out_node_tag != nullptr)
{
array<int> index_backup(node_size); // Backup nodes' indexes
for (int i = 0; i < node_size; i++)
{
index_backup[i] = node_x[i].id;
}
array<bool> valid_tag(node_size, false);
for (size_t i = 0; i < node_size; i++)
{
valid_tag[i] = out_node_tag[i];
}
for (int i = 0; i < ele_size; i++)
{
if (!valid_tag[i])
{
for (int j = 0; j < 3; j++)
{
valid_tag[ele_index[i].vert[j]->id] = false;
}
}
}
// Save nodes
save2gmsh_node(outfile, node_x, node_size, packed, valid_tag.get());
// Save elements
int valid_ele_count = 0;
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
valid_ele_count++;
}
}
int valid_id = 0;
outfile << "$Elements" << std::endl << valid_ele_count << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
outfile << valid_id << " 2 0"; valid_id++;
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
outfile << valid_id + 1 << " 2 0"; valid_id++;
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
}
outfile << "$EndElements" << std::endl;
// Restore nodes' indexes
for (int i = 0; i < node_size; i++)
{
node_x[i].id = index_backup[i];
}
}
else if (out_ele_tag != nullptr)
{
array<int> index_backup(node_size); // Backup nodes' indexes
for (int i = 0; i < node_size; i++)
{
index_backup[i] = node_x[i].id;
}
array<bool> valid_tag(node_size, false);
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
for (int j = 0; j < 3; j++)
{
valid_tag[ele_index[i].vert[j]->id] = true;
}
}
}
// Save nodes
save2gmsh_node(outfile, node_x, node_size, packed, valid_tag.get());
// Save elements
int valid_ele_count = 0;
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
valid_ele_count++;
}
}
int valid_id = 0;
outfile << "$Elements" << std::endl << valid_ele_count << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
outfile << valid_id << " 2 0"; valid_id++;
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
if (out_ele_tag[i])
{
outfile << valid_id + 1 << " 2 0"; valid_id++;
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
}
outfile << "$EndElements" << std::endl;
// Restore nodes' indexes
for (int i = 0; i < node_size; i++)
{
node_x[i].id = index_backup[i];
}
}
else if (out_node_tag != nullptr)
{
array<int> index_backup(node_size); // Backup nodes' indexes
for (int i = 0; i < node_size; i++)
{
index_backup[i] = node_x[i].id;
}
// Save nodes
save2gmsh_node(outfile, node_x, node_size, packed, out_node_tag);
// Save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements" << std::endl;
// Restore nodes' indexes
for (int i = 0; i < node_size; i++)
{
node_x[i].id = index_backup[i];
}
}
else
{
// Save nodes
save2gmsh_node(outfile, node_x, node_size, packed);
// Save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements" << std::endl;
}
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
const type_tetrahedron<E> *ele_index, int ele_size, index_packed_e packed = Packed,
bool *output_tag = nullptr)
{
// Set the file stream to the head
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
// Output head info
outfile << "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n";
// Count for valid output elements if output_tag is not nullptr
if (output_tag != nullptr)
{
array<int> index_backup(node_size); // Backup nodes' indexes
for (int i = 0; i < node_size; i++)
{
index_backup[i] = node_x[i].id;
}
array<bool> valid_tag(node_size, false);
for (int i = 0; i < ele_size; i++)
{
if (output_tag[i])
{
for (int j = 0; j < 3; j++)
{
valid_tag[ele_index[i].vert[j]->id] = true;
}
}
}
// Save nodes
save2gmsh_node(outfile, node_x, node_size, packed, valid_tag.get());
// Save elements
int valid_ele_count = 0;
for (int i = 0; i < ele_size; i++)
{
if (output_tag[i])
{
valid_ele_count++;
}
}
int valid_id = 0;
outfile << "$Elements" << std::endl << valid_ele_count << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
if (output_tag[i])
{
outfile << valid_id << " 4 0"; valid_id++;
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
if (output_tag[i])
{
outfile << valid_id + 1 << " 4 0"; valid_id++;
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
}
outfile << "$EndElements"<< std::endl;
// Restore nodes' indexes
for (int i = 0; i < node_size; i++)
{
node_x[i].id = index_backup[i];
}
}
else
{
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 4 0";
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 4 0";
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
}
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
const type_block<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 5 0";
for (int j = 0; j < 8; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 5 0";
for (int j = 0; j < 8; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
const type_tricone<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 2 0";
for (int j = 0; j < 3; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
const type_prism<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 6 0";
for (int j = 0; j < 6; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 6 0";
for (int j = 0; j < 6; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, vertex<point3dc, A> *node_x, int node_size,
const type_tesseroid<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// save node
save2gmsh_node(outfile, node_x, node_size, packed);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 5 0";
for (int j = 0; j < 8; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 5 0";
for (int j = 0; j < 8; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
template <typename E>
void save2gmsh(std::ofstream &outfile, const type_tetrahedron<E> *ele_index, int ele_size, index_packed_e packed = Packed)
{
// save head info
// 将文件指针重置到文件头 保险一点
outfile.clear(std::ios::goodbit);
outfile.seekp(std::ios::beg);
outfile << "$MeshFormat" << std::endl
<< "2.2 0 8" << std::endl
<< "$EndMeshFormat "<<std::endl;
// sort node
std::vector<vertex3dc*> node_index;
node_index.reserve(4*ele_size);
for (int i = 0; i < ele_size; ++i)
{
for (int j = 0; j < 4; ++j)
{
node_index.push_back(ele_index[i].vert[j]);
}
}
std::vector<vertex3dc*>::iterator pos;
std::sort(node_index.begin(), node_index.end()); //对顶点序列由小到大排序
pos = std::unique(node_index.begin(), node_index.end()); //获取重复序列开始的位置
node_index.erase(pos, node_index.end()); //删除重复点
outfile << "$Nodes" << std::endl << node_index.size() << std::endl;
// it is better to set the first vertex index to 1 to avoid a display bug in Gmsh
if (packed == Packed)
{
for (int i = 0; i < node_index.size(); i++)
{
outfile << node_index[i]->id << " " << std::setprecision(16)
<< node_index[i]->x << " " << node_index[i]->y << " " << node_index[i]->z << std::endl;
}
}
else
{
for (int i = 0; i < node_index.size(); i++)
{
outfile << node_index[i]->id + 1 << " " << std::setprecision(16)
<< node_index[i]->x << " " << node_index[i]->y << " " << node_index[i]->z << std::endl;
}
}
outfile<<"$EndNodes"<<std::endl;
destroy_vector(node_index);
// save elements
outfile << "$Elements" << std::endl << ele_size << std::endl;
if (packed == Packed)
{
for (int i = 0; i < ele_size; i++)
{
outfile << i << " 4 0";
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id;
}
outfile << std::endl;
}
}
else
{
for (int i = 0; i < ele_size; i++)
{
outfile << i + 1 << " 4 0";
for (int j = 0; j < 4; j++)
{
outfile << " " << ele_index[i].vert[j]->id + 1;
}
outfile << std::endl;
}
}
outfile << "$EndElements"<< std::endl;
return;
}
/**
* @brief Save 2D/3D meshes to Gmsh .msh files.
*
* @param outfile Output file stream.
* @param[in] element Output element array
* @param[in] node Output vertice array
* @param[in] packed Indicates whether to set the starting index to zero. The
* node and element's ordering will start with one if this option is false.
* The default value of this variable is true.
*/
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_triangle2d<E>> &element,
const array<vertex<point2dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_triangle2d2o<E>> &element,
const array<vertex<point2dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_rectangle2d<E>> &element,
const array<vertex<point2dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_triangle<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
array<bool> *out_ele_tag = nullptr, array<bool> *out_node_tag = nullptr)
{
if (out_ele_tag != nullptr && out_node_tag != nullptr)
{
if (element.size() != out_ele_tag->size() || node.size() != out_node_tag->size())
{
throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)");
return;
}
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, out_ele_tag->get(), out_node_tag->get());
}
else if (out_ele_tag != nullptr)
{
if (element.size() != out_ele_tag->size())
{
throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)");
return;
}
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, out_ele_tag->get());
}
else if (out_node_tag != nullptr)
{
if (node.size() != out_node_tag->size())
{
throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)");
return;
}
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, nullptr, out_node_tag->get());
}
else
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
}
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_tetrahedron<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed,
array<bool> *output_tag = nullptr)
{
if (output_tag != nullptr)
{
if (element.size() != output_tag->size())
{
throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)");
return;
}
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, output_tag->get());
}
else
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
}
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_block<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_tricone<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_prism<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E, typename A>
void save2gmsh(std::ofstream &outfile, const array<type_tesseroid<E>> &element,
const array<vertex<point3dc, A>> &node, index_packed_e packed = Packed)
{
save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed);
return;
}
template <typename E>
void save2gmsh(std::ofstream &outfile, const array<type_tetrahedron<E>> &element,
index_packed_e packed = Packed)
{
save2gmsh(outfile, element.get(), element.size(), packed);
return;
}
/**
* @brief Save a Gmsh data block to a given file.
*
* @param[in] filename The filename of the file that in_data is going to be added into.
* @param[in] dataname Name of the data that is going to be saved.
* @param[in] in_data Pointer of the double array of the input data.
* @param[in] d_size Number of the input data.
* @param[in] in_index Pointer of the int array of the input data's index. The size of in_index
* must be equal to in_data.
* @param[in] data_type The data type to be save. This enum could be equals to NODE_DATA
* or ELEMENT_DATA.
* @param[in] pack Indicates whether to set the starting index of data to zero.
* The data ordering will start with one if this option is false. The default value of
* this variable is true.
*
* @return status of the function
*/
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const T *in_data,
int d_size, mesh_data_type_e datatype, index_packed_e packed = Packed, const size_t *in_index = nullptr)
{
if (in_data == nullptr)
{
throw runtime_error("Null data pointer. From void gctl::save_gmsh_data(...)");
}
if (d_size <= 0)
{
throw runtime_error("Invalid array size. From void gctl::save_gmsh_data(...)");
}
// 将文件指针重置到文件尾
outfile.clear(std::ios::goodbit);
outfile.seekp(0, std::ios::end);
if (datatype == NodeData)
outfile<<"$NodeData"<<std::endl;
else if (datatype == ElemData || datatype == ElemData2D || datatype == ElemData3D)
outfile<<"$ElementData"<<std::endl;
int valid_size = 0;
for (int i = 0; i < d_size; i++)
{
if (!std::isnan(in_data[i])) valid_size++;
}
outfile<<1<<std::endl
<<"\"" << dataname << "\"" <<std::endl
<<1<<std::endl<<0.0<<std::endl
<<3<<std::endl<<0<<std::endl
<<1<<std::endl<<valid_size<<std::endl;
if (packed == Packed && in_index != nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << in_index[j] << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
else if (packed == NotPacked && in_index != nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << in_index[j]+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
else if (packed == Packed && in_index == nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << j << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
else
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << j+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
if (datatype == NodeData)
outfile << "$EndNodeData" << std::endl;
else
outfile << "$EndElementData"<< std::endl;
return;
}
/**
* @brief 保存Gmsh模型数据单元
*
* @param outfile 输出文件流
* @param[in] dataname 模型数据名称
* @param[in] in_data 模型数据数组
* @param[in] datatype 模型数据类型
* @param[in] in_index 模型数据索引数组的指针,为空时则依序储存模型数据数组
* @param[in] pack 输出模型数组索引是否从0开始为假时索引值从1开始
*/
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const array<T> &in_data,
mesh_data_type_e datatype, index_packed_e packed = Packed, const array<size_t> *in_index = nullptr)
{
if (in_index != nullptr)
{
save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed, in_index->get());
}
else save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed);
return;
}
/**
* @brief 保存Gmsh模型数据单元
*
* @param outfile 输出文件流
* @param[in] dataname 模型数据名称
* @param[in] in_data 模型数据数组
* @param[in] datatype 模型数据类型
* @param[in] in_index 模型数据索引数组的指针,为空时则依序储存模型数据数组
* @param[in] pack 输出模型数组索引是否从0开始为假时索引值从1开始
*/
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const std::vector<T> &in_data,
mesh_data_type_e datatype, index_packed_e packed = Packed, const std::vector<size_t> *in_index = nullptr)
{
if (in_index != nullptr)
{
save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed, in_index->data());
}
else save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed);
return;
}
/**
* @brief Save a Gmsh data block to a given file.
*
* @param[in] filename The filename of the file that in_data is going to be added into.
* @param[in] dataname Name of the data that is going to be saved.
* @param[in] in_data Pointer of the point3dc array of the input data.
* @param[in] d_size Number of the input data.
* @param[in] in_index Pointer of the int array of the input data's index. The size of in_index
* must be equal to in_data.
* @param[in] data_type The data type to be save. This enum could be equals to NODE_DATA
* or ELEMENT_DATA.
* @param[in] pack Indicates whether to set the starting index of data to zero.
* The data ordering will start with one if this option is false. The default value of
* this variable is true.
*
* @return status of the function
*/
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const point3c<T> *in_data,
int d_size, mesh_data_type_e datatype, index_packed_e packed = Packed, const size_t *in_index = nullptr)
{
if (in_data == nullptr)
{
throw runtime_error("Null data pointer. From void gctl::save_gmsh_data(...)");
}
if (d_size <= 0)
{
throw runtime_error("Invalid array size. From void gctl::save_gmsh_data(...)");
}
// 将文件指针重置到文件尾
outfile.clear(std::ios::goodbit);
outfile.seekp(0, std::ios::end);
if (datatype == NodeData)
outfile<<"$NodeData"<<std::endl;
else if (datatype == ElemData || datatype == ElemData2D || datatype == ElemData3D)
outfile<<"$ElementData"<<std::endl;
int valid_size = 0;
for (int i = 0; i < d_size; i++)
{
if (in_data[i].valid()) valid_size++;
}
outfile<<1<<std::endl
<<"\"" << dataname << "\"" <<std::endl
<<1<<std::endl<<0.0<<std::endl
<<3<<std::endl<<0<<std::endl
<<3<<std::endl<<valid_size<<std::endl;
if (packed == Packed && in_index != nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (in_data[j].valid())
{
outfile << in_index[j] << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< in_data[j].x << " " << in_data[j].y << " " << in_data[j].z << std::endl;
}
}
}
else if (packed == NotPacked && in_index != nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (in_data[j].valid())
{
outfile << in_index[j]+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< in_data[j].x << " " << in_data[j].y << " " << in_data[j].z << std::endl;
}
}
}
else if (packed == Packed && in_index == nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (in_data[j].valid())
{
outfile << j << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< in_data[j].x << " " << in_data[j].y << " " << in_data[j].z << std::endl;
}
}
}
else
{
for (int j = 0; j < d_size; j++)
{
if (in_data[j].valid())
{
outfile << j+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14)
<< in_data[j].x << " " << in_data[j].y << " " << in_data[j].z << std::endl;
}
}
}
if (datatype == NodeData)
outfile << "$EndNodeData" << std::endl;
else
outfile << "$EndElementData"<< std::endl;
return;
}
/**
* @brief 保存Gmsh模型数据单元
*
* @param outfile 输出文件流
* @param[in] dataname 模型数据名称
* @param[in] in_data 模型数据数组
* @param[in] datatype 模型数据类型
* @param[in] in_index 模型数据索引数组的指针,为空时则依序储存模型数据数组
* @param[in] pack 输出模型数组索引是否从0开始为假时索引值从1开始
*/
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const array<point3c<T>> &in_data,
mesh_data_type_e datatype, index_packed_e packed = Packed, const array<size_t> *in_index = nullptr)
{
if (in_index != nullptr)
{
save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed, in_index->get());
}
else save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed);
return;
}
/**
* @brief 保存Gmsh模型数据单元
*
* @param outfile 输出文件流
* @param[in] dataname 模型数据名称
* @param[in] in_data 模型数据数组
* @param[in] datatype 模型数据类型
* @param[in] in_index 模型数据索引数组的指针,为空时则依序储存模型数据数组
* @param[in] pack 输出模型数组索引是否从0开始为假时索引值从1开始
*/
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const std::vector<point3c<T>> &in_data,
mesh_data_type_e datatype, index_packed_e packed = Packed, const std::vector<size_t> *in_index = nullptr)
{
if (in_index != nullptr)
{
save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed, in_index->data());
}
else save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed);
return;
}
#ifdef GCTL_EIGEN
template <typename T>
void save_gmsh_data(std::ofstream &outfile, std::string dataname, const Eigen::Matrix<T, Eigen::Dynamic, 1> &in_data,
mesh_data_type_e datatype, index_packed_e packed = Packed, const Eigen::Matrix<T, Eigen::Dynamic, 1> *in_index = nullptr)
{
size_t d_size = in_data.size();
if (d_size <= 0)
{
throw runtime_error("Invalid array size. From void gctl::save_gmsh_data(...)");
}
// 将文件指针重置到文件尾
outfile.clear(std::ios::goodbit);
outfile.seekp(0, std::ios::end);
if (datatype == NodeData)
outfile<<"$NodeData"<<std::endl;
else if (datatype == ElemData || datatype == ElemData2D || datatype == ElemData3D)
outfile<<"$ElementData"<<std::endl;
int valid_size = 0;
for (int i = 0; i < d_size; i++)
{
if (!std::isnan(in_data[i])) valid_size++;
}
outfile<<1<<std::endl
<<"\"" << dataname << "\"" <<std::endl
<<1<<std::endl<<0.0<<std::endl
<<3<<std::endl<<0<<std::endl
<<1<<std::endl<<valid_size<<std::endl;
if (packed == Packed && in_index != nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << in_index->coeff(j) << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
else if (packed == NotPacked && in_index != nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << in_index->coeff(j)+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
else if (packed == Packed && in_index == nullptr)
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << j << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
else
{
for (int j = 0; j < d_size; j++)
{
if (!std::isnan(in_data[j]))
outfile << j+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl;
}
}
if (datatype == NodeData)
outfile << "$EndNodeData" << std::endl;
else
outfile << "$EndElementData"<< std::endl;
return;
}
#endif // GCTL_EIGEN
}
#endif //_GCTL_GMSH_IO_H