vtudata.txx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include <fstream>
  2. #include SCTL_INCLUDE(math_utils.hpp)
  3. namespace SCTL_NAMESPACE {
  4. inline void VTUData::WriteVTK(const std::string& fname, const Comm& comm = Comm::Self()) const {
  5. typedef typename VTUData::VTKReal VTKReal;
  6. Long value_dof = 0;
  7. { // Write vtu file.
  8. std::ofstream vtufile;
  9. { // Open file for writing.
  10. std::stringstream vtufname;
  11. vtufname << fname << std::setfill('0') << std::setw(6) << comm.Rank() << ".vtu";
  12. vtufile.open(vtufname.str().c_str());
  13. if (vtufile.fail()) return;
  14. }
  15. { // Write to file.
  16. Long pt_cnt = coord.Dim() / 3;
  17. Long cell_cnt = types.Dim();
  18. { // Set value_dof
  19. StaticArray<Long,2> pts_cnt{pt_cnt,0};
  20. StaticArray<Long,2> val_cnt{value.Dim(),0};
  21. comm.Allreduce(pts_cnt+0, pts_cnt+1, 1, Comm::CommOp::SUM);
  22. comm.Allreduce(val_cnt+0, val_cnt+1, 1, Comm::CommOp::SUM);
  23. value_dof = (pts_cnt[1] ? val_cnt[1] / pts_cnt[1] : 0);
  24. }
  25. Vector<int32_t> mpi_rank;
  26. { // Set mpi_rank
  27. Integer new_myrank = comm.Rank();
  28. mpi_rank.ReInit(pt_cnt);
  29. for (Long i = 0; i < mpi_rank.Dim(); i++) mpi_rank[i] = new_myrank;
  30. }
  31. bool isLittleEndian;
  32. { // Set isLittleEndian
  33. uint16_t number = 0x1;
  34. uint8_t *numPtr = (uint8_t *)&number;
  35. isLittleEndian = (numPtr[0] == 1);
  36. }
  37. Long data_size = 0;
  38. vtufile << "<?xml version=\"1.0\"?>\n";
  39. vtufile << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"" << (isLittleEndian ? "LittleEndian" : "BigEndian") << "\">\n";
  40. // ===========================================================================
  41. vtufile << " <UnstructuredGrid>\n";
  42. vtufile << " <Piece NumberOfPoints=\"" << pt_cnt << "\" NumberOfCells=\"" << cell_cnt << "\">\n";
  43. //---------------------------------------------------------------------------
  44. vtufile << " <Points>\n";
  45. vtufile << " <DataArray type=\"Float" << sizeof(VTKReal) * 8 << "\" NumberOfComponents=\"3\" Name=\"Position\" format=\"appended\" offset=\"" << data_size << "\" />\n";
  46. data_size += sizeof(uint32_t) + coord.Dim() * sizeof(VTKReal);
  47. vtufile << " </Points>\n";
  48. //---------------------------------------------------------------------------
  49. vtufile << " <PointData>\n";
  50. if (value_dof) { // value
  51. vtufile << " <DataArray type=\"Float" << sizeof(VTKReal) * 8 << "\" NumberOfComponents=\"" << value_dof << "\" Name=\"value\" format=\"appended\" offset=\"" << data_size << "\" />\n";
  52. data_size += sizeof(uint32_t) + value.Dim() * sizeof(VTKReal);
  53. }
  54. { // mpi_rank
  55. vtufile << " <DataArray type=\"Int32\" NumberOfComponents=\"1\" Name=\"mpi_rank\" format=\"appended\" offset=\"" << data_size << "\" />\n";
  56. data_size += sizeof(uint32_t) + pt_cnt * sizeof(int32_t);
  57. }
  58. vtufile << " </PointData>\n";
  59. //---------------------------------------------------------------------------
  60. //---------------------------------------------------------------------------
  61. vtufile << " <Cells>\n";
  62. vtufile << " <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << data_size << "\" />\n";
  63. data_size += sizeof(uint32_t) + connect.Dim() * sizeof(int32_t);
  64. vtufile << " <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << data_size << "\" />\n";
  65. data_size += sizeof(uint32_t) + offset.Dim() * sizeof(int32_t);
  66. vtufile << " <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << data_size << "\" />\n";
  67. //data_size += sizeof(uint32_t) + types.Dim() * sizeof(uint8_t);
  68. vtufile << " </Cells>\n";
  69. //---------------------------------------------------------------------------
  70. vtufile << " </Piece>\n";
  71. vtufile << " </UnstructuredGrid>\n";
  72. // ===========================================================================
  73. vtufile << " <AppendedData encoding=\"raw\">\n";
  74. vtufile << " _";
  75. int32_t block_size;
  76. { // coord
  77. block_size = coord.Dim() * sizeof(VTKReal);
  78. vtufile.write((char *)&block_size, sizeof(int32_t));
  79. if (coord.Dim()) vtufile.write((char *)&coord[0], coord.Dim() * sizeof(VTKReal));
  80. }
  81. if (value_dof) { // value
  82. block_size = value.Dim() * sizeof(VTKReal);
  83. vtufile.write((char *)&block_size, sizeof(int32_t));
  84. if (value.Dim()) vtufile.write((char *)&value[0], value.Dim() * sizeof(VTKReal));
  85. }
  86. { // mpi_rank
  87. block_size = mpi_rank.Dim() * sizeof(int32_t);
  88. vtufile.write((char *)&block_size, sizeof(int32_t));
  89. if (mpi_rank.Dim()) vtufile.write((char *)&mpi_rank[0], mpi_rank.Dim() * sizeof(int32_t));
  90. }
  91. { // block_size
  92. block_size = connect.Dim() * sizeof(int32_t);
  93. vtufile.write((char *)&block_size, sizeof(int32_t));
  94. if (connect.Dim()) vtufile.write((char *)&connect[0], connect.Dim() * sizeof(int32_t));
  95. }
  96. { // offset
  97. block_size = offset.Dim() * sizeof(int32_t);
  98. vtufile.write((char *)&block_size, sizeof(int32_t));
  99. if (offset.Dim()) vtufile.write((char *)&offset[0], offset.Dim() * sizeof(int32_t));
  100. }
  101. { // types
  102. block_size = types.Dim() * sizeof(uint8_t);
  103. vtufile.write((char *)&block_size, sizeof(int32_t));
  104. if (types.Dim()) vtufile.write((char *)&types[0], types.Dim() * sizeof(uint8_t));
  105. }
  106. vtufile << "\n";
  107. vtufile << " </AppendedData>\n";
  108. // ===========================================================================
  109. vtufile << "</VTKFile>\n";
  110. }
  111. vtufile.close(); // close file
  112. }
  113. if (!comm.Rank()) { // Write pvtu file
  114. std::ofstream pvtufile;
  115. { // Open file for writing
  116. std::stringstream pvtufname;
  117. pvtufname << fname << ".pvtu";
  118. pvtufile.open(pvtufname.str().c_str());
  119. if (pvtufile.fail()) return;
  120. }
  121. { // Write to file.
  122. pvtufile << "<?xml version=\"1.0\"?>\n";
  123. pvtufile << "<VTKFile type=\"PUnstructuredGrid\">\n";
  124. pvtufile << " <PUnstructuredGrid GhostLevel=\"0\">\n";
  125. pvtufile << " <PPoints>\n";
  126. pvtufile << " <PDataArray type=\"Float" << sizeof(VTKReal) * 8 << "\" NumberOfComponents=\"3\" Name=\"Position\"/>\n";
  127. pvtufile << " </PPoints>\n";
  128. pvtufile << " <PPointData>\n";
  129. if (value_dof) { // value
  130. pvtufile << " <PDataArray type=\"Float" << sizeof(VTKReal) * 8 << "\" NumberOfComponents=\"" << value_dof << "\" Name=\"value\"/>\n";
  131. }
  132. { // mpi_rank
  133. pvtufile << " <PDataArray type=\"Int32\" NumberOfComponents=\"1\" Name=\"mpi_rank\"/>\n";
  134. }
  135. pvtufile << " </PPointData>\n";
  136. {
  137. // Extract filename from path.
  138. std::stringstream vtupath;
  139. vtupath << '/' << fname;
  140. std::string pathname = vtupath.str();
  141. std::string fname_ = pathname.substr(pathname.find_last_of("/\\") + 1);
  142. // char *fname_ = (char*)strrchr(vtupath.str().c_str(), '/') + 1;
  143. // std::string fname_ =
  144. // boost::filesystem::path(fname).filename().string().
  145. for (Integer i = 0; i < comm.Size(); i++) pvtufile << " <Piece Source=\"" << fname_ << std::setfill('0') << std::setw(6) << i << ".vtu\"/>\n";
  146. }
  147. pvtufile << " </PUnstructuredGrid>\n";
  148. pvtufile << "</VTKFile>\n";
  149. }
  150. pvtufile.close(); // close file
  151. }
  152. };
  153. template <class ElemLst> inline void VTUData::AddElems(const ElemLst elem_lst, Integer order, const Comm& comm) {
  154. constexpr Integer COORD_DIM = ElemLst::CoordDim();
  155. constexpr Integer ElemDim = ElemLst::ElemDim();
  156. using CoordBasis = typename ElemLst::CoordBasis;
  157. using CoordType = typename ElemLst::CoordType;
  158. Long N0 = coord.Dim() / COORD_DIM;
  159. Long NElem = elem_lst.NElem();
  160. Matrix<CoordType> nodes = VTK_Nodes<CoordType, ElemDim>(order);
  161. Integer Nnodes = sctl::pow<ElemDim,Integer>(order);
  162. SCTL_ASSERT(nodes.Dim(0) == ElemDim);
  163. SCTL_ASSERT(nodes.Dim(1) == Nnodes);
  164. { // Set coord
  165. Matrix<CoordType> vtk_coord;
  166. auto M = CoordBasis::SetupEval(nodes);
  167. CoordBasis::Eval(vtk_coord, elem_lst.ElemVector(), M);
  168. for (Long k = 0; k < NElem; k++) {
  169. for (Integer i = 0; i < Nnodes; i++) {
  170. constexpr Integer dim = (COORD_DIM < 3 ? COORD_DIM : 3);
  171. for (Integer j = 0; j < dim; j++) {
  172. coord.PushBack((VTUData::VTKReal)vtk_coord[k*COORD_DIM+j][i]);
  173. }
  174. for (Integer j = dim; j < 3; j++) {
  175. coord.PushBack((VTUData::VTKReal)0);
  176. }
  177. }
  178. }
  179. }
  180. if (ElemLst::ElemDim() == 2) {
  181. for (Long k = 0; k < NElem; k++) {
  182. for (Integer i = 0; i < order-1; i++) {
  183. for (Integer j = 0; j < order-1; j++) {
  184. Long idx = k*Nnodes + i*order + j;
  185. connect.PushBack(N0+idx);
  186. connect.PushBack(N0+idx+1);
  187. connect.PushBack(N0+idx+order+1);
  188. connect.PushBack(N0+idx+order);
  189. offset.PushBack(connect.Dim());
  190. types.PushBack(9);
  191. }
  192. }
  193. }
  194. } else {
  195. // TODO
  196. SCTL_ASSERT(false);
  197. }
  198. }
  199. template <class ElemLst, class ValueBasis> inline void VTUData::AddElems(const ElemLst elem_lst, const Vector<ValueBasis>& elem_value, Integer order, const Comm& comm) {
  200. constexpr Integer ElemDim = ElemLst::ElemDim();
  201. using ValueType = typename ValueBasis::ValueType;
  202. Long NElem = elem_lst.NElem();
  203. Integer dof = (NElem==0 ? 0 : elem_value.Dim() / NElem);
  204. SCTL_ASSERT(elem_value.Dim() == NElem * dof);
  205. AddElems(elem_lst, order, comm);
  206. Matrix<ValueType> nodes = VTK_Nodes<ValueType, ElemDim>(order);
  207. Integer Nnodes = sctl::pow<ElemDim,Integer>(order);
  208. SCTL_ASSERT(nodes.Dim(0) == ElemDim);
  209. SCTL_ASSERT(nodes.Dim(1) == Nnodes);
  210. { // Set value
  211. Matrix<ValueType> vtk_value;
  212. auto M = ValueBasis::SetupEval(nodes);
  213. ValueBasis::Eval(vtk_value, elem_value, M);
  214. for (Long k = 0; k < NElem; k++) {
  215. for (Integer i = 0; i < Nnodes; i++) {
  216. for (Integer j = 0; j < dof; j++) {
  217. value.PushBack((VTUData::VTKReal)vtk_value[k*dof+j][i]);
  218. }
  219. }
  220. }
  221. }
  222. }
  223. template <class CoordType, Integer ELEM_DIM> inline Matrix<CoordType> VTUData::VTK_Nodes(Integer order) {
  224. Matrix<CoordType> nodes;
  225. if (ELEM_DIM == 2) {
  226. Integer Nnodes = order*order;
  227. nodes.ReInit(ELEM_DIM, Nnodes);
  228. for (Integer i = 0; i < order; i++) {
  229. for (Integer j = 0; j < order; j++) {
  230. //nodes[0][i*order+j] = i / (CoordType)(order-1);
  231. //nodes[1][i*order+j] = j / (CoordType)(order-1);
  232. nodes[0][i*order+j] = 0.5 - 0.5 * sctl::cos<CoordType>((2*i+1) * const_pi<CoordType>() / (2*order));
  233. nodes[1][i*order+j] = 0.5 - 0.5 * sctl::cos<CoordType>((2*j+1) * const_pi<CoordType>() / (2*order));
  234. }
  235. }
  236. } else {
  237. // TODO
  238. SCTL_ASSERT(false);
  239. }
  240. return nodes;
  241. }
  242. }