Chaste  Release::3.4
TrianglesMeshWriter.cpp
1 /*
2 
3 Copyright (c) 2005-2016, 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 
47 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
49  const std::string& rDirectory,
50  const std::string& rBaseName,
51  const bool clearOutputDir)
52  : AbstractTetrahedralMeshWriter<ELEMENT_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir)
53 {
54 }
55 
56 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
58 {
59 }
60 
61 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
63 {
64  this->mFilesAreBinary=true;
65 }
66 
67 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
69 {
70  std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
71 // PetscTools::Barrier("DodgyBarrierBeforeNODE");
72  MeshEventHandler::BeginEvent(MeshEventHandler::NODE);
73  // Write node file
74  std::string node_file_name = this->mBaseName + ".node";
75  out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name, std::ios::binary | std::ios::trunc);
76 
77  // Write the node header
78  unsigned num_attr = 0;
79 
80  if (this->mpMesh && !this->mFilesAreBinary)
81  {
82  // Assumes that all nodes have the same number of attributes as the first node in the mesh.
83  num_attr = this->mpMesh->GetNumNodeAttributes();
84  }
86  unsigned max_bdy_marker = 0;
87  unsigned num_nodes = this->GetNumNodes();
88 
89  *p_node_file << num_nodes << "\t";
90  *p_node_file << SPACE_DIM << "\t";
91  *p_node_file << num_attr << "\t";
92  *p_node_file << max_bdy_marker;
93  if (this->mFilesAreBinary)
94  {
95  *p_node_file << "\tBIN\n";
96  }
97  else
98  {
99  *p_node_file << "\n";
100  }
101 
102  *p_node_file << std::setprecision(20);
103 
104  // Write each node's data
105  for (unsigned item_num=0; item_num<num_nodes; item_num++)
106  {
107  if (this->mpMesh && !this->mFilesAreBinary && num_attr!=0)
108  {
109 
111  WriteItem(p_node_file, item_num, this->GetNextNode(), this->mpMesh->GetNode(item_num)->rGetNodeAttributes());
112  }
113  else
114  {
115  WriteItem(p_node_file, item_num, this->GetNextNode());
116  }
117  }
118  *p_node_file << comment << "\n";
119  p_node_file->close();
120 // PetscTools::Barrier("DodgyBarrierAfterNODE");
121  MeshEventHandler::EndEvent(MeshEventHandler::NODE);
122  MeshEventHandler::BeginEvent(MeshEventHandler::ELE);
123  if (ELEMENT_DIM < SPACE_DIM)
124  {
125  WriteElementsAsFaces();
126  WriteFacesAsEdges();
127  return;
128  }
129 
130  // Write element file
131  std::string element_file_name = this->mBaseName + ".ele";
132  out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name, std::ios::binary | std::ios::trunc);
133 
134  // Write the element header
135  unsigned num_elements = this->GetNumElements();
136  num_attr = 1u; // We have a single region code
137 
138  // The condition below allows the writer to cope with a NodesOnlyMesh
139  if (num_elements == 0)
140  {
141  *p_element_file << 0 << "\t";
142  *p_element_file << 0 << "\t";
143  *p_element_file << 0;
144  if (this->mFilesAreBinary)
145  {
146  *p_element_file << "\tBIN\n";
147  }
148  else
149  {
150  *p_element_file << "\n";
151  }
152  p_element_file->close();
153  }
154  else
155  {
156  ElementData element_data = this->GetNextElement();
157 
158  unsigned nodes_per_element = element_data.NodeIndices.size();
159  if (nodes_per_element != ELEMENT_DIM+1)
160  {
161  // Check that this is a quadratic mesh
162  assert(ELEMENT_DIM == SPACE_DIM);
163  assert(nodes_per_element == (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2);
164  }
165 
166  *p_element_file << num_elements << "\t";
167  *p_element_file << nodes_per_element << "\t";
168  *p_element_file << num_attr;
169  if (this->mFilesAreBinary)
170  {
171  *p_element_file << "\tBIN\n";
172  }
173  else
174  {
175  *p_element_file << "\n";
176  }
177 
178  // Write each element's data
179  std::vector<double> attribute_values(1);
180  for (unsigned item_num=0; item_num<num_elements; item_num++)
181  {
182  /*
183  * If item_num==0 we will already have got the element above (in order to
184  * get the number of nodes per element).
185  */
186  if (item_num > 0)
187  {
188  element_data = this->GetNextElement();
189  }
190  attribute_values[0] = element_data.AttributeValue;
191  WriteItem(p_element_file, item_num, element_data.NodeIndices, attribute_values);
192  }
193  *p_element_file << comment << "\n";
194  p_element_file->close();
195  }
196 // PetscTools::Barrier("DodgyBarrierAfterELE");
197  MeshEventHandler::EndEvent(MeshEventHandler::ELE);
198  MeshEventHandler::BeginEvent(MeshEventHandler::FACE);
199  // Write boundary face file
200  std::string face_file_name = this->mBaseName;
201 
202  if (ELEMENT_DIM == 1)
203  {
204  // In 1-D there is no boundary file: it's trivial to calculate
205  return;
206  }
207  else if (ELEMENT_DIM == 2)
208  {
209  face_file_name = face_file_name + ".edge";
210  }
211  else
212  {
213  face_file_name = face_file_name + ".face";
214  }
215  out_stream p_face_file = this->mpOutputFileHandler->OpenOutputFile(face_file_name, std::ios::binary | std::ios::trunc);
216 
217  // Write the boundary face header
218  if (num_elements != 0)
219  {
220  unsigned num_faces = this->GetNumBoundaryFaces();
221 
222  *p_face_file << num_faces << "\t";
224  *p_face_file << max_bdy_marker;
225  if (this->mFilesAreBinary)
226  {
227  *p_face_file << "\tBIN\n";
228  }
229  else
230  {
231  *p_face_file << "\n";
232  }
233 
234  // Write each face's data
235  std::vector<double> default_marker(0);
236  for (unsigned item_num=0; item_num<num_faces; item_num++)
237  {
238  ElementData face_data = this->GetNextBoundaryElement();
239  WriteItem(p_face_file, item_num, face_data.NodeIndices, default_marker);
240  }
241  *p_face_file << comment << "\n";
242  p_face_file->close();
243 
244  if (this->GetNumCableElements() > 0)
245  {
246  // Write cable element file
247  std::string cable_element_file_name = this->mBaseName + ".cable";
248  out_stream p_cable_element_file = this->mpOutputFileHandler->OpenOutputFile(cable_element_file_name, std::ios::binary | std::ios::trunc);
249 
250  // Write the cable element header
251  unsigned num_cable_elements = this->GetNumCableElements();
253  num_attr = 1u; // We have a single region code - which is actually a radius
254 
255  *p_cable_element_file << num_cable_elements << "\t";
256  *p_cable_element_file << 2 << "\t";
257  *p_cable_element_file << num_attr;
258  if (this->mFilesAreBinary)
259  {
260  *p_cable_element_file << "\tBIN\n";
261  }
262  else
263  {
264  *p_cable_element_file << "\n";
265  }
266 
267  // Write each element's data
268  std::vector<double> attribute_values(1);
269  for (unsigned item_num=0; item_num<num_cable_elements; item_num++)
270  {
271  ElementData cable_element_data = this->GetNextCableElement();
272  attribute_values[0] = cable_element_data.AttributeValue;
273  WriteItem(p_cable_element_file, item_num, cable_element_data.NodeIndices, attribute_values);
274  }
275  *p_cable_element_file << comment;
276  p_cable_element_file->close();
277  }
278  }
279 // PetscTools::Barrier("DodgyBarrierAfterFACE");
280  MeshEventHandler::EndEvent(MeshEventHandler::FACE);
281 
282 }
283 
284 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
286 {
287  std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
288 
289  std::string element_file_name = this->mBaseName;
290  if (ELEMENT_DIM == 1 && (SPACE_DIM == 2 || SPACE_DIM == 3))
291  {
292  element_file_name = element_file_name + ".edge";
293  }
294  else if (ELEMENT_DIM == 2 && SPACE_DIM == 3)
295  {
296  element_file_name = element_file_name + ".face";
297  }
298 
299  out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name, std::ios::binary | std::ios::trunc);
300 
301  // Write the element header
302  unsigned num_elements = this->GetNumElements();
303  assert(SPACE_DIM != ELEMENT_DIM);
304  unsigned num_attr = 1;
305 
306  *p_element_file << num_elements << "\t";
307  //*p_element_file << nodes_per_element << "\t";
308  *p_element_file << num_attr;
309  if (this->mFilesAreBinary)
310  {
311  *p_element_file << "\tBIN\n";
312  }
313  else
314  {
315  *p_element_file << "\n";
316  }
317 
318  // Write each element's data
319  std::vector<double> attribute_values(1);
320  for (unsigned item_num=0; item_num<num_elements; item_num++)
321  {
322  ElementData element_data = this->GetNextElement();
323  attribute_values[0] = element_data.AttributeValue;
324  WriteItem(p_element_file, item_num, element_data.NodeIndices, attribute_values);
325  }
326 
327  *p_element_file << comment << "\n";
328  p_element_file->close();
329 
330 }
331 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
333 {
334  std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
335 
336  if (ELEMENT_DIM == 1 && (SPACE_DIM == 2 || SPACE_DIM == 3))
337  {
338  return;
339  }
340 
341  assert(SPACE_DIM == 3 && ELEMENT_DIM == 2);
342 
343  std::string face_file_name = this->mBaseName;
344  face_file_name = face_file_name + ".edge";
345 
346  out_stream p_face_file = this->mpOutputFileHandler->OpenOutputFile(face_file_name, std::ios::binary | std::ios::trunc);
347 
348  // Write the boundary face header
349  unsigned num_faces = this->GetNumBoundaryFaces();
350 
351  unsigned max_bdy_marker = 0;
352  std::vector<double> default_marker(0);
353 
354  *p_face_file << num_faces << "\t";
355  *p_face_file << max_bdy_marker;
356  if (this->mFilesAreBinary)
357  {
358  *p_face_file << "\tBIN\n";
359  }
360  else
361  {
362  *p_face_file << "\n";
363  }
364 
365  // Write each face's data
366  for (unsigned item_num=0; item_num<num_faces; item_num++)
367  {
368  ElementData face_data = this->GetNextBoundaryElement();
369  WriteItem(p_face_file, item_num, face_data.NodeIndices, default_marker);
370  }
371  *p_face_file << comment << "\n";
372  p_face_file->close();
373 }
374 
375 
376 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
377 template<class T_DATA>
378 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteItem(out_stream &pFile, unsigned itemNumber,
379  const std::vector<T_DATA> &dataPacket)
380 {
381  //Writing with no attribute
382  //Instantiates the attribute variety with the attributes empty
383  WriteItem(pFile, itemNumber, dataPacket, std::vector<double>());
384 }
385 
386 
387 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
388 template<class T_DATA>
389 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteItem(out_stream &pFile, unsigned itemNumber,
390  const std::vector<T_DATA> &dataPacket,
391  const std::vector<double> &rAttributes)
392 {
393  if (this->mFilesAreBinary)
394  {
395  // No item numbers
396  // Write raw data out of std::vector into the file
397  pFile->write((char*)&dataPacket[0], dataPacket.size()*sizeof(T_DATA));
398 
399  // Write raw attribute(s)
400  // MSVC 10 will trip an assertion on accessing the 0th element if the vector is empty.
401  // Note that C++11 gives vectors a .data() method which would be a better way of doing this!
402  if (!rAttributes.empty())
403  {
404  pFile->write((char*)&rAttributes[0], rAttributes.size()*sizeof(double));
405  }
406  }
407  else
408  {
409  *pFile << itemNumber;
410  for (unsigned i=0; i<dataPacket.size(); i++)
411  {
412  *pFile << "\t" << dataPacket[i];
413  }
414  for (unsigned i=0; i<rAttributes.size(); i++)
415  {
416  *pFile << "\t" << rAttributes[i];
417  }
418  *pFile << "\n";
419  }
420 }
421 
423 // Explicit instantiation
425 
426 template class TrianglesMeshWriter<1,1>;
427 template class TrianglesMeshWriter<1,2>;
428 template class TrianglesMeshWriter<1,3>;
429 template class TrianglesMeshWriter<2,2>;
430 template class TrianglesMeshWriter<2,3>;
431 template class TrianglesMeshWriter<3,3>;
432 
437 template void TrianglesMeshWriter<1, 1>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
438 template void TrianglesMeshWriter<1, 1>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
439 template void TrianglesMeshWriter<1, 2>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
440 template void TrianglesMeshWriter<1, 2>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
441 template void TrianglesMeshWriter<1, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
442 template void TrianglesMeshWriter<1, 3>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
443 template void TrianglesMeshWriter<2, 2>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
444 template void TrianglesMeshWriter<2, 2>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
445 template void TrianglesMeshWriter<2, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
446 template void TrianglesMeshWriter<2, 3>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
447 template void TrianglesMeshWriter<3, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double> & );
448 template void TrianglesMeshWriter<3, 3>::WriteItem(out_stream &, unsigned, const std::vector<double> &, const std::vector<double> & );
void WriteItem(out_stream &pFile, unsigned itemNumber, const std::vector< T_DATA > &dataPacket, const std::vector< double > &rAttributes)
TrianglesMeshWriter(const std::string &rDirectory, const std::string &rBaseName, const bool clearOutputDir=true)
std::vector< unsigned > NodeIndices
static std::string GetProvenanceString()