write_to_gmv.h
Go to the documentation of this file.
1 /*
2  This file is part of the Ristra tangram project.
3  Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/tangram/blob/master/LICENSE
5 */
6 
7 #ifndef PORTAGE_WRITE_TO_GMV_H_
8 #define PORTAGE_WRITE_TO_GMV_H_
9 
10 #include <fstream>
11 #include <vector>
12 #include <array>
13 #include <algorithm>
14 #include <string>
15 
17 
18 /* Do we need to write a variant of this which will work if we don't
19  * have TANGRAM and multi-material state? */
20 
21 #include "tangram/driver/CellMatPoly.h"
22 
23 namespace Portage {
24 
41 template<int D, class Mesh_Wrapper, class State_Wrapper,
42  class InterfaceReconstructor>
43 void write_to_gmv(Mesh_Wrapper const& mesh,
44  State_Wrapper const& state,
45  std::shared_ptr<InterfaceReconstructor> ir,
46  std::vector<std::string> &fieldnames,
47  std::string filename) {
48 
49  std::cerr << "Writing material and field data to GMV file\n";
50 
51  int nmats = state.num_materials();
52  int nc = mesh.num_entities(Entity_kind::CELL, Entity_type::PARALLEL_OWNED);
53  int nallc = mesh.num_entities(Entity_kind::CELL, Entity_type::ALL);
54 
55  std::vector<int> cell_num_mats(nc, 0);
56  std::vector<std::vector<int>> cell_mat_ids(nc);
57 
58  std::vector<int> icell_owned2all(nc, -1);
59  for (int ic = 0, iowned = 0; ic < nallc; ic++)
60  if (mesh.cell_get_type(ic) == Wonton::PARALLEL_OWNED) {
61  state.cell_get_mats(iowned, &(cell_mat_ids[iowned]));
62  cell_num_mats[iowned] = cell_mat_ids[iowned].size();
63  icell_owned2all[iowned] = ic;
64  iowned++;
65  }
66 
67  std::ofstream fout(filename);
68  fout << std::scientific;
69  fout.precision(17);
70 
71  fout << "gmvinput ascii" << std::endl;
72  fout << "codename Portage" << std::endl;
73  fout << "simdate 01/01/01" << std::endl;
74 
75  // Make a list of unique points in the mesh and cell mat poly
76  // structures combined
77 
78  int np = mesh.num_entities(Entity_kind::NODE, Entity_type::PARALLEL_OWNED);
79  int nallp = mesh.num_entities(Entity_kind::NODE, Entity_type::ALL);
80  int nmatpnts = np;
81 
82  std::vector<int> inode_owned2all(np, -1);
83  std::vector<int> inode_all2owned(nallp, -1);
84  for (int ip = 0, iowned = 0; ip < nallp; ip++)
85  if (mesh.node_get_type(ip) == Wonton::PARALLEL_OWNED) {
86  inode_owned2all[iowned] = ip;
87  inode_all2owned[ip] = iowned;
88  iowned++;
89  }
90 
91  for (int c = 0; c < nc; c++) {
92  if (cell_num_mats[c] > 1) { // Mixed cell
93  Tangram::CellMatPoly<D> const& cellmatpoly =
94  ir->cell_matpoly_data(icell_owned2all[c]);
95 
96  int ncp = cellmatpoly.num_matvertices();
97  for (int i = 0; i < ncp; i++)
98  if (cellmatpoly.matvertex_parent_kind(i) != Tangram::Entity_kind::NODE)
99  nmatpnts++; // point does not correspond to mesh node - add to list
100  }
101  }
102 
103  std::vector<Point<D>> points(nmatpnts);
104 
105  for (int i = 0; i < np; i++)
106  mesh.node_get_coordinates(inode_owned2all[i], &(points[i]));
107 
108  nmatpnts = np; // reset nmatpnts so it can be used as a counter
109  for (int c = 0; c < nc; c++) {
110  if (cell_num_mats[c] > 1) { // Mixed cell
111  Tangram::CellMatPoly<D> const& cellmatpoly =
112  ir->cell_matpoly_data(icell_owned2all[c]);
113 
114  int ncp = cellmatpoly.num_matvertices();
115  for (int i = 0; i < ncp; i++) {
116  if (cellmatpoly.matvertex_parent_kind(i) != Tangram::Entity_kind::NODE) {
117  points[nmatpnts] = Point<D>(cellmatpoly.matvertex_point(i));
118  nmatpnts++;
119  }
120  }
121  }
122  }
123 
124  fout << "nodev " << nmatpnts << std::endl;
125  for (int ip = 0; ip < nmatpnts; ip++) {
126  fout << points[ip];
127  if (D == 2) // GMV requires us to output 3 coordinates
128  fout << " " << 0.000000;
129  fout << std::endl;
130  }
131 
132  // Count the number of polygons we will write out - assume one
133  // polygon per material per cell
134 
135  int npoly = 0;
136  for (int c = 0; c < nc; c++)
137  npoly += cell_num_mats[c];
138  fout << "cells " << npoly << std::endl;
139 
140  // Now write out material polygons one material at a time (this
141  // makes it easier to also write out corresponding field data
142 
143  for (int m = 0; m < nmats; m++) {
144  std::vector<int> matcells;
145  state.mat_get_cells(m, &matcells);
146 
147  for (int c : matcells) {
148  if (cell_num_mats[c] > 1) { // multi-material cell
149 
150  Tangram::CellMatPoly<D> const& cellmatpoly =
151  ir->cell_matpoly_data(icell_owned2all[c]);
152 
153  // Write out the polyhedra corresponding to this material
154  int nmp = cellmatpoly.num_matpolys();
155  for (int i = 0; i < nmp; i++) {
156 
157  if (cellmatpoly.matpoly_matid(i) != m) continue;
158 
159  if (D == 1 || D == 2) {
160  std::vector<int> mverts = cellmatpoly.matpoly_vertices(i);
161  fout << "general 1 " << mverts.size() << " ";
162  for (auto n : mverts) {
163  if (cellmatpoly.matvertex_parent_kind(n) == Tangram::Entity_kind::NODE)
164  fout << inode_all2owned[cellmatpoly.matvertex_parent_id(n)] + 1 << " ";
165  else {
166  Point<D> pnt = cellmatpoly.matvertex_point(n);
167  for (int j = np; j < nmatpnts; j++) {
168  if (points[j] == pnt) {
169  fout << j+1 << " ";
170  break;
171  }
172  }
173  }
174  }
175  fout << std::endl;
176 
177  } else if (D == 3) {
178 
179  std::vector<int> const& mfaces = cellmatpoly.matpoly_faces(i);
180  fout << "general " << mfaces.size() << std::endl;
181  for (auto f : mfaces) {
182  std::vector<int> const& mfverts = cellmatpoly.matface_vertices(f);
183  fout << mfverts.size() << " ";
184  }
185  fout << std::endl;
186  for (auto f : mfaces) {
187  std::vector<int> const& mfverts = cellmatpoly.matface_vertices(f);
188  int nfv = mfverts.size();
189  int mp0, mp1;
190  cellmatpoly.matface_matpolys(f, &mp0, &mp1);
191  if (mp0 == i) { // Natural order of vertices
192  for (int j = 0; j < nfv; j++) {
193  int n = mfverts[j];
194  if (cellmatpoly.matvertex_parent_kind(n) == Tangram::Entity_kind::NODE)
195  fout << inode_all2owned[cellmatpoly.matvertex_parent_id(n)] + 1 << " ";
196  else {
197  Point<D> pnt = cellmatpoly.matvertex_point(n);
198  for (int j = np; j < nmatpnts; j++) {
199  if (points[j] == pnt) {
200  fout << j+1 << " ";
201  break;
202  }
203  }
204  }
205  }
206  fout << std::endl;
207  } else { // Reverse order of vertices
208  for (int j = 0; j < nfv; j++) {
209  int n = mfverts[nfv-j-1];
210  if (cellmatpoly.matvertex_parent_kind(n) == Tangram::Entity_kind::NODE)
211  fout << inode_all2owned[cellmatpoly.matvertex_parent_id(n)] + 1 << " ";
212  else {
213  Point<D> pnt = cellmatpoly.matvertex_point(n);
214  for (int j = np; j < nmatpnts; j++) {
215  if (points[j] == pnt) {
216  fout << j+1 << " ";
217  break;
218  }
219  }
220  }
221  }
222  fout << std::endl;
223  }
224  } // for (auto f : mfaces)
225  } // else if (D == 3)
226  } // for (i = 0; i < nmp; i++)
227 
228  } else { // single material cell
229 
230  if (cell_mat_ids[c][0] == m) {
231  if (D == 1 || D == 2) {
232  // Write out the cell
233  std::vector<int> cverts;
234  mesh.cell_get_nodes(icell_owned2all[c], &cverts);
235 
236  // write cell out as polygons (even if its a quad or tri)
237  fout << "general 1 " << cverts.size() << " ";
238  for (auto n : cverts)
239  fout << n+1 << " ";
240  fout << std::endl;
241  } else if (D == 3) {
242  std::vector<int> cfaces;
243  std::vector<int> cfdirs;
244  mesh.cell_get_faces_and_dirs(icell_owned2all[c], &cfaces, &cfdirs);
245  fout << "general " << cfaces.size() << std::endl;
246  for (auto f : cfaces) {
247  std::vector<int> fverts;
248  mesh.face_get_nodes(f, &fverts);
249  fout << fverts.size() << " ";
250  }
251  fout << std::endl;
252 
253  int j = 0;
254  for (auto f : cfaces) {
255  std::vector<int> fverts;
256  mesh.face_get_nodes(f, &fverts);
257  int nfverts = fverts.size();
258  if (cfdirs[j] == 1) {
259  for (int k = 0; k < nfverts; k++)
260  fout << fverts[k]+1 << " ";
261  fout << std::endl;
262  } else {
263  for (int k = 0; k < nfverts; k++)
264  fout << fverts[nfverts-k-1]+1 << " ";
265  fout << std::endl;
266  }
267  }
268  }
269  } // if (cell_mat_ids[c][0] == m)
270 
271  } // if (cell_num_mats[c] > 1) ... else ...
272  } // for (c : matcells)
273  } // for (m = 0; m < nmats; m++)
274 
275 
276  // Write out material ID of polygons
277 
278  fout << "material " << std::endl;
279  fout << nmats << " 0" << std::endl;
280  for (int m = 0; m < nmats; m++)
281  fout << "mat" << m+1 << std::endl;
282 
283  for (int m = 0; m < nmats; m++) {
284  std::vector<int> matcells;
285  state.mat_get_cells(m, &matcells);
286 
287  for (int c : matcells) {
288  for (int cm : cell_mat_ids[c]) {
289  if (cm == m) {
290  fout << m+1 << " ";
291  break;
292  }
293  }
294  }
295  }
296  fout << std::endl;
297 
298  // Write out any requested fields
299  if (fieldnames.size()) {
300  fout << "variable" << std::endl;
301  for (auto & fieldname : fieldnames) {
302  if (state.field_type(Portage::Entity_kind::CELL, fieldname) ==
303  Portage::Field_type::UNKNOWN_TYPE_FIELD)
304  continue;
305 
306  fout << fieldname << " 0 " << std::endl;
307  for (int m = 0; m < nmats; m++) {
308  std::vector<int> matcells;
309  state.mat_get_cells(m, &matcells);
310  int nmatcells = matcells.size();
311 
312  double const *matvec;
313  state.mat_get_celldata(fieldname, m, &matvec);
314 
315  for (int i = 0; i < nmatcells; i++)
316  fout << matvec[i] << std::endl;
317  }
318  }
319  fout << "endvars" << std::endl;
320  }
321 
322  fout << "endgmv" << std::endl;
323 }
324 
325 
326 } // namespace Portage
327 
328 #endif // PORTAGE_WRITE_TO_GMV_H_
void write_to_gmv(Mesh_Wrapper const &mesh, State_Wrapper const &state, std::shared_ptr< InterfaceReconstructor > ir, std::vector< std::string > &fieldnames, std::string filename)
Method to write out material polygons from an interface reconstruction and any associated material fi...
Definition: write_to_gmv.h:43
Definition: coredriver.h:42
constexpr std::vector< Point< oper::dimension(domain)> > points()
Definition: operator_references.h:29