Chaste  Release::2017.1
TrianglesMeshWriter.cpp
1 /*
2 
3 Copyright (c) 2005-2017, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "TrianglesMeshWriter.hpp"
37 
38 #include "AbstractTetrahedralMesh.hpp"
39 #include "Version.hpp"
40 
41 #include <cassert>
42 
44 // Implementation
46 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
48  const std::string& rDirectory,
49  const std::string& rBaseName,
50  const bool clearOutputDir)
51  : AbstractTetrahedralMeshWriter<ELEMENT_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir)
52 {
53 }
54 
55 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
57 {
58 }
59 
60 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
62 {
63  this->mFilesAreBinary=true;
64 }
65 
66 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
68 {
69  std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
70 // PetscTools::Barrier("DodgyBarrierBeforeNODE");
71  MeshEventHandler::BeginEvent(MeshEventHandler::NODE);
72  // Write node file
73  std::string node_file_name = this->mBaseName + ".node";
74  out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name, std::ios::binary | std::ios::trunc);
75 
76  // Write the node header
77  unsigned num_attr = 0;
78 
79  if (this->mpMesh && !this->mFilesAreBinary)
80  {
81  // Assumes that all nodes have the same number of attributes as the first node in the mesh.
82  num_attr = this->mpMesh->GetNumNodeAttributes();
83  }
85  unsigned max_bdy_marker = 0;
86  unsigned num_nodes = this->GetNumNodes();
87 
88  *p_node_file << num_nodes << "\t";
89  *p_node_file << SPACE_DIM << "\t";
90  *p_node_file << num_attr << "\t";
91  *p_node_file << max_bdy_marker;
92  if (this->mFilesAreBinary)
93  {
94  *p_node_file << "\tBIN\n";
95  }
96  else
97  {
98  *p_node_file << "\n";
99  }
100 
101  *p_node_file << std::setprecision(20);
102 
103  // Write each node's data
104  for (unsigned item_num=0; item_num<num_nodes; item_num++)
105  {
106  if (this->mpMesh && !this->mFilesAreBinary && num_attr!=0)
107  {
108 
110  WriteItem(p_node_file, item_num, this->GetNextNode(), this->mpMesh->GetNode(item_num)->rGetNodeAttributes());
111  }
112  else
113  {
114  WriteItem(p_node_file, item_num, this->GetNextNode());
115  }
116  }
117  *p_node_file << comment << "\n";
118  p_node_file->close();
119 // PetscTools::Barrier("DodgyBarrierAfterNODE");
120  MeshEventHandler::EndEvent(MeshEventHandler::NODE);
121  MeshEventHandler::BeginEvent(MeshEventHandler::ELE);
122  if (ELEMENT_DIM < SPACE_DIM)
123  {
126  return;
127  }
128 
129  // Write element file
130  std::string element_file_name = this->mBaseName + ".ele";
131  out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name, std::ios::binary | std::ios::trunc);
132 
133  // Write the element header
134  unsigned num_elements = this->GetNumElements();
135  num_attr = 1u; // We have a single region code
136 
137  // The condition below allows the writer to cope with a NodesOnlyMesh
138  if (num_elements == 0)
139  {
140  *p_element_file << 0 << "\t";
141  *p_element_file << 0 << "\t";
142  *p_element_file << 0;
143  if (this->mFilesAreBinary)
144  {
145  *p_element_file << "\tBIN\n";
146  }
147  else
148  {
149  *p_element_file << "\n";
150  }
151  p_element_file->close();
152  }
153  else
154  {
155  ElementData element_data = this->GetNextElement();
156 
157  unsigned nodes_per_element = element_data.NodeIndices.size();
158  if (nodes_per_element != ELEMENT_DIM+1)
159  {
160  // Check that this is a quadratic mesh
161  assert(ELEMENT_DIM == SPACE_DIM);
162  assert(nodes_per_element == (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2);
163  }
164 
165  *p_element_file << num_elements << "\t";
166  *p_element_file << nodes_per_element << "\t";
167  *p_element_file << num_attr;
168  if (this->mFilesAreBinary)
169  {
170  *p_element_file << "\tBIN\n";
171  }
172  else
173  {
174  *p_element_file << "\n";
175  }
176 
177  // Write each element's data
178  std::vector<double> attribute_values(1);
179  for (unsigned item_num=0; item_num<num_elements; item_num++)
180  {
181  /*
182  * If item_num==0 we will already have got the element above (in order to
183  * get the number of nodes per element).
184  */
185  if (item_num > 0)
186  {
187  element_data = this->GetNextElement();
188  }
189  attribute_values[0] = element_data.AttributeValue;
190  WriteItem(p_element_file, item_num, element_data.NodeIndices, attribute_values);
191  }
192  *p_element_file << comment << "\n";
193  p_element_file->close();
194  }
195 // PetscTools::Barrier("DodgyBarrierAfterELE");
196  MeshEventHandler::EndEvent(MeshEventHandler::ELE);
197  MeshEventHandler::BeginEvent(MeshEventHandler::FACE);
198  // Write boundary face file
199  std::string face_file_name = this->mBaseName;
200 
201  if (ELEMENT_DIM == 1)
202  {
203  // In 1-D there is no boundary file: it's trivial to calculate
204  return;
205  }
206  else if (ELEMENT_DIM == 2)
207  {
208  face_file_name = face_file_name + ".edge";
209  }
210  else
211  {
212  face_file_name = face_file_name + ".face";
213  }
214  out_stream p_face_file = this->mpOutputFileHandler->OpenOutputFile(face_file_name, std::ios::binary | std::ios::trunc);
215 
216  // Write the boundary face header
217  if (num_elements != 0)
218  {
219  unsigned num_faces = this->GetNumBoundaryFaces();
220 
221  *p_face_file << num_faces << "\t";
223  *p_face_file << max_bdy_marker;
224  if (this->mFilesAreBinary)
225  {
226  *p_face_file << "\tBIN\n";
227  }
228  else
229  {
230  *p_face_file << "\n";
231  }
232 
233  // Write each face's data
234  std::vector<double> default_marker(0);
235  for (unsigned item_num=0; item_num<num_faces; item_num++)
236  {
237  ElementData face_data = this->GetNextBoundaryElement();
238  WriteItem(p_face_file, item_num, face_data.NodeIndices, default_marker);
239  }
240  *p_face_file << comment << "\n";
241  p_face_file->close();
242 
243  if (this->GetNumCableElements() > 0)
244  {
245  // Write cable element file
246  std::string cable_element_file_name = this->mBaseName + ".cable";
247  out_stream p_cable_element_file = this->mpOutputFileHandler->OpenOutputFile(cable_element_file_name, std::ios::binary | std::ios::trunc);
248 
249  // Write the cable element header
250  unsigned num_cable_elements = this->GetNumCableElements();
252  num_attr = 1u; // We have a single region code - which is actually a radius
253 
254  *p_cable_element_file << num_cable_elements << "\t";
255  *p_cable_element_file << 2 << "\t";
256  *p_cable_element_file << num_attr;
257  if (this->mFilesAreBinary)
258  {
259  *p_cable_element_file << "\tBIN\n";
260  }
261  else
262  {
263  *p_cable_element_file << "\n";
264  }
265 
266  // Write each element's data
267  std::vector<double> attribute_values(1);
268  for (unsigned item_num=0; item_num<num_cable_elements; item_num++)
269  {
270  ElementData cable_element_data = this->GetNextCableElement();
271  attribute_values[0] = cable_element_data.AttributeValue;
272  WriteItem(p_cable_element_file, item_num, cable_element_data.NodeIndices, attribute_values);
273  }
274  *p_cable_element_file << comment;
275  p_cable_element_file->close();
276  }
277  }
278 // PetscTools::Barrier("DodgyBarrierAfterFACE");
279  MeshEventHandler::EndEvent(MeshEventHandler::FACE);
280 }
281 
282 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
284 {
285  std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
286 
287  std::string element_file_name = this->mBaseName;
288  if (ELEMENT_DIM == 1 && (SPACE_DIM == 2 || SPACE_DIM == 3))
289  {
290  element_file_name = element_file_name + ".edge";
291  }
292  else if (ELEMENT_DIM == 2 && SPACE_DIM == 3)
293  {
294  element_file_name = element_file_name + ".face";
295  }
296 
297  out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name, std::ios::binary | std::ios::trunc);
298 
299  // Write the element header
300  unsigned num_elements = this->GetNumElements();
301  assert(SPACE_DIM != ELEMENT_DIM); // LCOV_EXCL_LINE
302  unsigned num_attr = 1;
303 
304  *p_element_file << num_elements << "\t";
305  //*p_element_file << nodes_per_element << "\t";
306  *p_element_file << num_attr;
307  if (this->mFilesAreBinary)
308  {
309  *p_element_file << "\tBIN\n";
310  }
311  else
312  {
313  *p_element_file << "\n";
314  }
315 
316  // Write each element's data
317  std::vector<double> attribute_values(1);
318  for (unsigned item_num=0; item_num<num_elements; item_num++)
319  {
320  ElementData element_data = this->GetNextElement();
321  attribute_values[0] = element_data.AttributeValue;
322  WriteItem(p_element_file, item_num, element_data.NodeIndices, attribute_values);
323  }
324 
325  *p_element_file << comment << "\n";
326  p_element_file->close();
327 }
328 
329 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
331 {
332  std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
333 
334  if (ELEMENT_DIM == 1 && (SPACE_DIM == 2 || SPACE_DIM == 3))
335  {
336  return;
337  }
338 
339  assert(SPACE_DIM == 3 && ELEMENT_DIM == 2); // LCOV_EXCL_LINE
340 
341  std::string face_file_name = this->mBaseName;
342  face_file_name = face_file_name + ".edge";
343 
344  out_stream p_face_file = this->mpOutputFileHandler->OpenOutputFile(face_file_name, std::ios::binary | std::ios::trunc);
345 
346  // Write the boundary face header
347  unsigned num_faces = this->GetNumBoundaryFaces();
348 
349  unsigned max_bdy_marker = 0;
350  std::vector<double> default_marker(0);
351 
352  *p_face_file << num_faces << "\t";
353  *p_face_file << max_bdy_marker;
354  if (this->mFilesAreBinary)
355  {
356  *p_face_file << "\tBIN\n";
357  }
358  else
359  {
360  *p_face_file << "\n";
361  }
362 
363  // Write each face's data
364  for (unsigned item_num=0; item_num<num_faces; item_num++)
365  {
366  ElementData face_data = this->GetNextBoundaryElement();
367  WriteItem(p_face_file, item_num, face_data.NodeIndices, default_marker);
368  }
369  *p_face_file << comment << "\n";
370  p_face_file->close();
371 }
372 
373 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
374 template<class T_DATA>
375 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteItem(out_stream &pFile, unsigned itemNumber,
376  const std::vector<T_DATA> &dataPacket)
377 {
378  //Writing with no attribute
379  //Instantiates the attribute variety with the attributes empty
380  WriteItem(pFile, itemNumber, dataPacket, std::vector<double>());
381 }
382 
383 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
384 template<class T_DATA>
385 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteItem(out_stream &pFile, unsigned itemNumber,
386  const std::vector<T_DATA> &dataPacket,
387  const std::vector<double> &rAttributes)
388 {
389  if (this->mFilesAreBinary)
390  {
391  // No item numbers
392  // Write raw data out of std::vector into the file
393  pFile->write((char*)&dataPacket[0], dataPacket.size()*sizeof(T_DATA));
394 
395  // Write raw attribute(s)
396  // MSVC 10 will trip an assertion on accessing the 0th element if the vector is empty.
397  // Note that C++11 gives vectors a .data() method which would be a better way of doing this!
398  if (!rAttributes.empty())
399  {
400  pFile->write((char*)&rAttributes[0], rAttributes.size()*sizeof(double));
401  }
402  }
403  else
404  {
405  *pFile << itemNumber;
406  for (unsigned i=0; i<dataPacket.size(); i++)
407  {
408  *pFile << "\t" << dataPacket[i];
409  }
410  for (unsigned i=0; i<rAttributes.size(); i++)
411  {
412  *pFile << "\t" << rAttributes[i];
413  }
414  *pFile << "\n";
415  }
416 }
417 
418 // Explicit instantiation
419 template class TrianglesMeshWriter<1,1>;
420 template class TrianglesMeshWriter<1,2>;
421 template class TrianglesMeshWriter<1,3>;
422 template class TrianglesMeshWriter<2,2>;
423 template class TrianglesMeshWriter<2,3>;
424 template class TrianglesMeshWriter<3,3>;
425 
430 template void TrianglesMeshWriter<1, 1>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
431 template void TrianglesMeshWriter<1, 1>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
432 template void TrianglesMeshWriter<1, 2>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
433 template void TrianglesMeshWriter<1, 2>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
434 template void TrianglesMeshWriter<1, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
435 template void TrianglesMeshWriter<1, 3>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
436 template void TrianglesMeshWriter<2, 2>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
437 template void TrianglesMeshWriter<2, 2>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
438 template void TrianglesMeshWriter<2, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
439 template void TrianglesMeshWriter<2, 3>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
440 template void TrianglesMeshWriter<3, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
441 template void TrianglesMeshWriter<3, 3>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpMesh
void WriteItem(out_stream &pFile, unsigned itemNumber, const std::vector< T_DATA > &dataPacket, const std::vector< double > &rAttributes)
virtual unsigned GetNumNodes()
TrianglesMeshWriter(const std::string &rDirectory, const std::string &rBaseName, const bool clearOutputDir=true)
OutputFileHandler * mpOutputFileHandler
std::vector< unsigned > NodeIndices
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static std::string GetProvenanceString()