Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "Hdf5ToCmguiConverter.hpp" 00037 #include "CmguiMeshWriter.hpp" 00038 #include "UblasCustomFunctions.hpp" 00039 #include "HeartConfig.hpp" 00040 #include "PetscTools.hpp" 00041 #include "Exception.hpp" 00042 #include "ReplicatableVector.hpp" 00043 #include "DistributedVector.hpp" 00044 #include "DistributedVectorFactory.hpp" 00045 #include "Version.hpp" 00046 #include "GenericMeshReader.hpp" 00047 00048 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00049 void Hdf5ToCmguiConverter<ELEMENT_DIM,SPACE_DIM>::Write(std::string type) 00050 { 00051 out_stream p_file = out_stream(NULL); 00052 00053 unsigned num_nodes = this->mpReader->GetNumberOfRows(); 00054 unsigned num_timesteps = this->mpReader->GetUnlimitedDimensionValues().size(); 00055 00056 DistributedVectorFactory factory(num_nodes); 00057 00058 Vec data = factory.CreateVec();//for V 00059 Vec data_phie = factory.CreateVec();//for phi_e 00060 Vec data_second_cell = factory.CreateVec();//for the V of the second cell, used in extended bidomain problems. 00061 00062 for (unsigned time_step=0; time_step<num_timesteps; time_step++) 00063 { 00064 // Create the file for this time step 00065 std::stringstream time_step_string; 00066 00067 // unsigned to string 00068 time_step_string << time_step; 00069 if (PetscTools::AmMaster()) 00070 { 00071 p_file = this->mpOutputFileHandler->OpenOutputFile(this->mFileBaseName + "_" + time_step_string.str() + ".exnode"); 00072 00073 // Check how many digits are to be output in the solution (0 goes to default value of digits) 00074 unsigned int num_digits = HeartConfig::Instance()->GetVisualizerOutputPrecision(); 00075 if (num_digits != 0) 00076 { 00077 p_file->precision(num_digits); 00078 } 00079 } 00080 00081 std::vector<ReplicatableVector*> all_data; 00082 unsigned num_vars = this->mpReader->GetVariableNames().size(); 00083 for (unsigned var=0; var<num_vars; var++) 00084 { 00085 // Read the data for this time step 00086 this->mpReader->GetVariableOverNodes(data, this->mpReader->GetVariableNames()[var], time_step); 00087 ReplicatableVector* p_repl_data = new ReplicatableVector(data); 00088 assert(p_repl_data->GetSize()==num_nodes); 00089 all_data.push_back(p_repl_data); 00090 } 00091 00092 if (PetscTools::AmMaster()) 00093 { 00094 // Write provenance info 00095 std::string comment = "! " + ChasteBuildInfo::GetProvenanceString(); 00096 *p_file << comment; 00097 // The header first 00098 *p_file << "Group name: " << this->mFileBaseName << "\n"; 00099 *p_file << "#Fields=" << num_vars << "\n"; 00100 for (unsigned var=0; var<num_vars; var++) 00101 { 00102 *p_file << " " << var+1 << ") " <<this->mpReader->GetVariableNames()[var]<< " , field, rectangular cartesian, #Components=1" << "\n" << "x. Value index=1, #Derivatives=0, #Versions=1"<<"\n"; 00103 if (var != num_vars-1) 00104 { 00105 *p_file << "\n"; 00106 } 00107 } 00108 00109 // Write the data 00110 for (unsigned i=0; i<num_nodes; i++) 00111 { 00112 // cmgui counts nodes from 1 00113 *p_file << "Node: "<< i+1 << "\n"; 00114 for (unsigned var=0; var<num_vars; var++) 00115 { 00116 *p_file << (*(all_data[var]))[i] << "\n"; 00117 } 00118 } 00119 } 00120 00121 for (unsigned var=0; var<num_vars; var++) 00122 { 00123 delete all_data[var]; 00124 } 00125 } 00126 PetscTools::Destroy(data); 00127 PetscTools::Destroy(data_phie); 00128 PetscTools::Destroy(data_second_cell); 00129 00130 if (PetscTools::AmMaster()) 00131 { 00132 p_file->close(); 00133 } 00134 } 00135 00136 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00137 Hdf5ToCmguiConverter<ELEMENT_DIM,SPACE_DIM>::Hdf5ToCmguiConverter(std::string inputDirectory, 00138 std::string fileBaseName, 00139 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh, 00140 bool hasBath) 00141 : AbstractHdf5Converter<ELEMENT_DIM,SPACE_DIM>(inputDirectory, fileBaseName, pMesh, "cmgui_output") 00142 { 00143 // Write the node data out 00144 Write(""); 00145 00146 // Write mesh in a suitable form for cmgui 00147 std::string output_directory = HeartConfig::Instance()->GetOutputDirectory() + "/cmgui_output"; 00148 00149 CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM> cmgui_mesh_writer(output_directory, HeartConfig::Instance()->GetOutputFilenamePrefix(), false); 00150 00151 // Used to inform the mesh of the data names 00152 std::vector<std::string> field_names = this->mpReader->GetVariableNames(); 00153 cmgui_mesh_writer.SetAdditionalFieldNames(field_names); 00154 if (hasBath) 00155 { 00156 std::vector<std::string> names; 00157 names.push_back("tissue"); 00158 names.push_back("bath"); 00159 cmgui_mesh_writer.SetRegionNames(names); 00160 } 00161 00162 // Normally the in-memory mesh is converted: 00163 if (HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering() == false) 00164 { 00165 cmgui_mesh_writer.WriteFilesUsingMesh(*(this->mpMesh), false); 00166 } 00167 else 00168 { 00169 // In this case we expect the mesh to have been read in from file 00171 // Note that the next line will throw if the mesh has not been read from file 00172 std::string original_file=this->mpMesh->GetMeshFileBaseName(); 00173 std::auto_ptr<AbstractMeshReader<ELEMENT_DIM, SPACE_DIM> > p_original_mesh_reader 00174 = GenericMeshReader<ELEMENT_DIM, SPACE_DIM>(original_file); 00175 cmgui_mesh_writer.WriteFilesUsingMeshReader(*p_original_mesh_reader); 00176 } 00177 00178 WriteCmguiScript(); 00179 PetscTools::Barrier("Hdf5ToCmguiConverter"); 00180 } 00181 00182 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00183 void Hdf5ToCmguiConverter<ELEMENT_DIM,SPACE_DIM>::WriteCmguiScript() 00184 { 00185 unsigned num_timesteps = this->mpReader->GetUnlimitedDimensionValues().size(); 00186 assert(this->mpReader->GetVariableNames().size() > 0); // seg fault guard 00187 std::string variable_name = this->mpReader->GetVariableNames()[0]; 00188 00189 if (PetscTools::AmMaster()) 00190 { 00191 out_stream p_script_file = this->mpOutputFileHandler->OpenOutputFile("LoadSolutions.com"); 00192 00193 // Write provenance info, note the # instead of ! because this is - essentially - a PERL script that Cmgui interprets 00194 std::string comment = "# " + ChasteBuildInfo::GetProvenanceString(); 00195 *p_script_file << comment; 00196 00197 *p_script_file << "# Read the mesh \n" 00198 << "gfx read node "<<HeartConfig::Instance()->GetOutputFilenamePrefix()<<".exnode \n" 00199 << "gfx read elem "<<HeartConfig::Instance()->GetOutputFilenamePrefix()<<".exelem \n" // note the mesh file name is taken from HeartConfig... 00200 << "gfx define faces egroup "<<HeartConfig::Instance()->GetOutputFilenamePrefix()<<"\n" 00201 << "# Create a window \n" 00202 << "gfx cre win 1 \n" 00203 << "# Modify the scene (obtained by gfx list g_element XXXX commands) to visualize first var on lines and nodes \n" 00204 << "gfx modify g_element "<< HeartConfig::Instance()->GetOutputFilenamePrefix()<<" general clear circle_discretization 6 default_coordinate coordinates element_discretization \"4*4*4\" native_discretization none; \n" 00205 << "gfx modify g_element "<< HeartConfig::Instance()->GetOutputFilenamePrefix()<<" lines select_on material default data "<<variable_name<<" spectrum default selected_material default_selected; \n" 00206 << "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" 00207 << "# Load the data \n" 00208 << "for ($i=0; $i<" << num_timesteps << "; $i++) { \n" 00209 << " gfx read node " << this->mFileBaseName << "_$i.exnode time $i\n" // ...while the data file from mFileBaseName... 00210 << "}\n"; 00211 p_script_file->close(); 00212 } 00213 } 00214 00216 // Explicit instantiation 00218 00219 template class Hdf5ToCmguiConverter<1,1>; 00220 template class Hdf5ToCmguiConverter<1,2>; 00221 template class Hdf5ToCmguiConverter<2,2>; 00222 template class Hdf5ToCmguiConverter<1,3>; 00223 template class Hdf5ToCmguiConverter<2,3>; 00224 template class Hdf5ToCmguiConverter<3,3>;