Chaste  Release::2017.1
Hdf5ToCmguiConverter.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 "Hdf5ToCmguiConverter.hpp"
37 #include "CmguiMeshWriter.hpp"
38 #include "UblasCustomFunctions.hpp"
39 #include "HeartConfig.hpp"
40 #include "PetscTools.hpp"
41 #include "Exception.hpp"
42 #include "ReplicatableVector.hpp"
43 #include "DistributedVector.hpp"
44 #include "DistributedVectorFactory.hpp"
45 #include "Version.hpp"
46 #include "GenericMeshReader.hpp"
47 
48 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
50 {
51  out_stream p_file = out_stream(NULL);
52 
53  unsigned num_nodes = this->mpReader->GetNumberOfRows();
54  unsigned num_timesteps = this->mpReader->GetUnlimitedDimensionValues().size();
55 
56  DistributedVectorFactory factory(num_nodes);
57 
58  Vec data = factory.CreateVec();//for V
59  Vec data_phie = factory.CreateVec();//for phi_e
60  Vec data_second_cell = factory.CreateVec();//for the V of the second cell, used in extended bidomain problems.
61 
62  for (unsigned time_step=0; time_step<num_timesteps; time_step++)
63  {
64  // Create the file for this time step
65  std::stringstream time_step_string;
66 
67  // unsigned to string
68  time_step_string << time_step;
70  {
71  p_file = this->mpOutputFileHandler->OpenOutputFile(this->mFileBaseName + "_" + time_step_string.str() + ".exnode");
72 
73  // Check how many digits are to be output in the solution (0 goes to default value of digits)
74  if (this->mPrecision != 0)
75  {
76  p_file->precision(this->mPrecision);
77  }
78  }
79 
80  std::vector<ReplicatableVector*> all_data;
81  unsigned num_vars = this->mpReader->GetVariableNames().size();
82  for (unsigned var=0; var<num_vars; var++)
83  {
84  // Read the data for this time step
85  this->mpReader->GetVariableOverNodes(data, this->mpReader->GetVariableNames()[var], time_step);
86  ReplicatableVector* p_repl_data = new ReplicatableVector(data);
87  assert(p_repl_data->GetSize()==num_nodes);
88  all_data.push_back(p_repl_data);
89  }
90 
92  {
93  // Write provenance info
94  std::string comment = "! " + ChasteBuildInfo::GetProvenanceString();
95  *p_file << comment;
96  // The header first
97  *p_file << "Group name: " << this->mFileBaseName << "\n";
98  *p_file << "#Fields=" << num_vars << "\n";
99  for (unsigned var=0; var<num_vars; var++)
100  {
101  *p_file << " " << var+1 << ") " <<this->mpReader->GetVariableNames()[var]<< " , field, rectangular cartesian, #Components=1" << "\n" << "x. Value index=1, #Derivatives=0, #Versions=1"<<"\n";
102  if (var != num_vars-1)
103  {
104  *p_file << "\n";
105  }
106  }
107 
108  // Write the data
109  for (unsigned i=0; i<num_nodes; i++)
110  {
111  // cmgui counts nodes from 1
112  *p_file << "Node: "<< i+1 << "\n";
113  for (unsigned var=0; var<num_vars; var++)
114  {
115  *p_file << (*(all_data[var]))[i] << "\n";
116  }
117  }
118  }
119 
120  for (unsigned var=0; var<num_vars; var++)
121  {
122  delete all_data[var];
123  }
124  }
125  PetscTools::Destroy(data);
126  PetscTools::Destroy(data_phie);
127  PetscTools::Destroy(data_second_cell);
128 
129  if (PetscTools::AmMaster())
130  {
131  p_file->close();
132  }
133 }
134 
135 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
137  const std::string& rFileBaseName,
139  bool hasBath,
140  unsigned precision)
141  : AbstractHdf5Converter<ELEMENT_DIM,SPACE_DIM>(rInputDirectory, rFileBaseName, pMesh, "cmgui_output", precision)
142 {
144  while (this->mDatasetNames[this->mOpenDatasetIndex] != "Data")
145  {
146  bool next_open = this->MoveOntoNextDataset();
147  UNUSED_OPT(next_open);
148  assert(next_open);
149  }
150 
151  // Write the node data out
152  Write("");
153 
154  // Write mesh in a suitable form for cmgui
155  std::string output_directory = HeartConfig::Instance()->GetOutputDirectory() + "/cmgui_output";
156 
157  CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM> cmgui_mesh_writer(output_directory, HeartConfig::Instance()->GetOutputFilenamePrefix(), false);
158 
159  // Used to inform the mesh of the data names
160  std::vector<std::string> field_names = this->mpReader->GetVariableNames();
161  cmgui_mesh_writer.SetAdditionalFieldNames(field_names);
162  if (hasBath)
163  {
164  std::vector<std::string> names;
165  names.push_back("tissue");
166  names.push_back("bath");
167  cmgui_mesh_writer.SetRegionNames(names);
168  }
169 
170  // Normally the in-memory mesh is converted:
171  if (HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering() == false || !this->mpMesh->IsMeshOnDisk())
172  {
173  cmgui_mesh_writer.WriteFilesUsingMesh(*(this->mpMesh), false);
174  }
175  else
176  {
177  // In this case we expect the mesh to have been read in from file
179  // Note that the next line will throw if the mesh has not been read from file
180  std::string original_file=this->mpMesh->GetMeshFileBaseName();
181  std::shared_ptr<AbstractMeshReader<ELEMENT_DIM, SPACE_DIM> > p_original_mesh_reader
182  = GenericMeshReader<ELEMENT_DIM, SPACE_DIM>(original_file);
183  cmgui_mesh_writer.WriteFilesUsingMeshReader(*p_original_mesh_reader);
184  }
185 
187  PetscTools::Barrier("Hdf5ToCmguiConverter");
188 }
189 
190 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
192 {
193  unsigned num_timesteps = this->mpReader->GetUnlimitedDimensionValues().size();
194  assert(this->mpReader->GetVariableNames().size() > 0); // seg fault guard
195  std::string variable_name = this->mpReader->GetVariableNames()[0];
196 
197  if (PetscTools::AmMaster())
198  {
199  out_stream p_script_file = this->mpOutputFileHandler->OpenOutputFile("LoadSolutions.com");
200 
201  // Write provenance info, note the # instead of ! because this is - essentially - a PERL script that Cmgui interprets
202  std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
203  *p_script_file << comment;
204 
205  *p_script_file << "# Read the mesh \n"
206  << "gfx read node "<<HeartConfig::Instance()->GetOutputFilenamePrefix()<<".exnode \n"
207  << "gfx read elem "<<HeartConfig::Instance()->GetOutputFilenamePrefix()<<".exelem \n" // note the mesh file name is taken from HeartConfig...
208  << "gfx define faces egroup "<<HeartConfig::Instance()->GetOutputFilenamePrefix()<<"\n"
209  << "# Create a window \n"
210  << "gfx cre win 1 \n"
211  << "# Modify the scene (obtained by gfx list g_element XXXX commands) to visualize first var on lines and nodes \n"
212  << "gfx modify g_element "<< HeartConfig::Instance()->GetOutputFilenamePrefix()<<" general clear circle_discretization 6 default_coordinate coordinates element_discretization \"4*4*4\" native_discretization none; \n"
213  << "gfx modify g_element "<< HeartConfig::Instance()->GetOutputFilenamePrefix()<<" lines select_on material default data "<<variable_name<<" spectrum default selected_material default_selected; \n"
214  << "gfx modify g_element "<< HeartConfig::Instance()->GetOutputFilenamePrefix()<<" node_points glyph point general size \"1*1*1\" centre 0,0,0 font default select_on material default data "<<variable_name<<" spectrum default selected_material default_selected; \n"
215  << "# Load the data \n"
216  << "for ($i=0; $i<" << num_timesteps << "; $i++) { \n"
217  << " gfx read node " << this->mFileBaseName << "_$i.exnode time $i\n" // ...while the data file from mFileBaseName...
218  << "}\n";
219  p_script_file->close();
220  }
221 }
222 
223 // Explicit instantiation
224 template class Hdf5ToCmguiConverter<1,1>;
225 template class Hdf5ToCmguiConverter<1,2>;
226 template class Hdf5ToCmguiConverter<2,2>;
227 template class Hdf5ToCmguiConverter<1,3>;
228 template class Hdf5ToCmguiConverter<2,3>;
229 template class Hdf5ToCmguiConverter<3,3>;
std::string GetOutputFilenamePrefix() const
static void Barrier(const std::string callerId="")
Definition: PetscTools.cpp:134
boost::shared_ptr< Hdf5DataReader > mpReader
void Write(std::string type)
OutputFileHandler * mpOutputFileHandler
static bool AmMaster()
Definition: PetscTools.cpp:120
void SetRegionNames(std::vector< std::string > &rRegionNames)
void WriteFilesUsingMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
Hdf5ToCmguiConverter(const FileFinder &rInputDirectory, const std::string &rFileBaseName, AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, bool hasBath=false, unsigned precision=0u)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
std::vector< std::string > mDatasetNames
static void Destroy(Vec &rVec)
Definition: PetscTools.hpp:352
void SetAdditionalFieldNames(std::vector< std::string > &rFieldNames)
#define UNUSED_OPT(var)
Definition: Exception.hpp:216
std::string GetOutputDirectory() const
static std::string GetProvenanceString()
virtual void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)
AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpMesh
static HeartConfig * Instance()