Chaste Commit::baa90ac2819b962188b7562f2326be23c47859a7
PottsMeshWriter.cpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include "PottsMeshWriter.hpp"
37#include "Version.hpp"
38
42template<unsigned SPACE_DIM>
50
52// Implementation
54
55template<unsigned SPACE_DIM>
56PottsMeshWriter<SPACE_DIM>::PottsMeshWriter(const std::string& rDirectory,
57 const std::string& rBaseName,
58 const bool clearOutputDir)
59 : AbstractMeshWriter<SPACE_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir),
60 mpMesh(nullptr),
61 mpIters(new MeshPottsWriterIterators<SPACE_DIM>),
62 mpNodeMap(nullptr),
63 mNodeMapCurrentIndex(0)
64{
65 mpIters->pNodeIter = nullptr;
66 mpIters->pElemIter = nullptr;
67}
68
69template<unsigned SPACE_DIM>
71{
72 if (mpIters->pNodeIter)
73 {
74 delete mpIters->pNodeIter;
75 delete mpIters->pElemIter;
76 }
77
78 delete mpIters;
79
80 if (mpNodeMap)
81 {
82 delete mpNodeMap;
83 }
84}
85
86template<unsigned SPACE_DIM>
88{
89 if (mpMesh)
90 {
91 // Sanity check
92 assert(this->mNumNodes == mpMesh->GetNumNodes());
93
94 std::vector<double> coordinates(SPACE_DIM+1);
95
96 // Get the node coordinates using the node iterator (thus skipping deleted nodes)
97 for (unsigned j=0; j<SPACE_DIM; j++)
98 {
99 coordinates[j] = (*(mpIters->pNodeIter))->GetPoint()[j];
100 }
101 coordinates[SPACE_DIM] = (*(mpIters->pNodeIter))->IsBoundaryNode();
102
103 ++(*(mpIters->pNodeIter));
104
105 return coordinates;
106 }
107 else
108 {
110 }
111}
112
113template<unsigned SPACE_DIM>
115{
116 if (mpMesh)
117 {
118 assert(this->mNumElements == mpMesh->GetNumElements());
119
120 ElementData elem_data;
121 elem_data.NodeIndices.resize((*(mpIters->pElemIter))->GetNumNodes());
122 for (unsigned j=0; j<elem_data.NodeIndices.size(); j++)
123 {
124 unsigned old_index = (*(mpIters->pElemIter))->GetNodeGlobalIndex(j);
125 elem_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
126 }
127
128 // Set attribute
129 elem_data.AttributeValue = (*(mpIters->pElemIter))->GetAttribute();
130 ++(*(mpIters->pElemIter));
131
132 return elem_data;
133 }
134 else
135 {
137 }
138}
139
141template<unsigned SPACE_DIM>
143{
144 this->mpMeshReader = nullptr;
145 mpMesh = &rMesh;
146
147 this->mNumNodes = mpMesh->GetNumNodes();
148 this->mNumElements = mpMesh->GetNumElements();
149
150 typedef typename AbstractMesh<SPACE_DIM,SPACE_DIM>::NodeIterator NodeIterType;
151 mpIters->pNodeIter = new NodeIterType(mpMesh->GetNodeIteratorBegin());
152
153 typedef typename PottsMesh<SPACE_DIM>::PottsElementIterator ElemIterType;
154 mpIters->pElemIter = new ElemIterType(mpMesh->GetElementIteratorBegin());
155
156 // Set up node map if we might have deleted nodes
157 mNodeMapCurrentIndex = 0;
158 if (mpMesh->IsMeshChanging())
159 {
160 mpNodeMap = new NodeMap(mpMesh->GetNumAllNodes());
161 for (NodeIterType it = mpMesh->GetNodeIteratorBegin(); it != mpMesh->GetNodeIteratorEnd(); ++it)
162 {
163 mpNodeMap->SetNewIndex(it->GetIndex(), mNodeMapCurrentIndex++);
164 }
165 }
166
167 WriteFiles();
168}
169
170template<unsigned SPACE_DIM>
172{
173 std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
174
175 // Write node file
176 std::string node_file_name = this->mBaseName + ".node";
177 out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name);
178
179 // Write the node header
180 unsigned num_attr = 0;
181 unsigned max_bdy_marker = 1; // as we include boundary node information in the node file
182 unsigned num_nodes = this->GetNumNodes();
183
184 *p_node_file << num_nodes << "\t";
185 *p_node_file << SPACE_DIM << "\t";
186 *p_node_file << num_attr << "\t";
187 *p_node_file << max_bdy_marker << "\n";
188 *p_node_file << std::setprecision(6);
189
190 // Write each node's data
191 for (unsigned item_num=0; item_num<num_nodes; item_num++)
192 {
193 std::vector<double> current_item = this->GetNextNode();
194 *p_node_file << item_num;
195 for (unsigned i=0; i<SPACE_DIM+1; i++)
196 {
197 *p_node_file << "\t" << current_item[i];
198 }
199 *p_node_file << "\n";
200 }
201 *p_node_file << comment << "\n";
202 p_node_file->close();
203
204 // Write element file
205 std::string element_file_name = this->mBaseName + ".cell";
206 out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name);
207
208 // Write the element header
209 unsigned num_elements = this->GetNumElements();
210 *p_element_file << num_elements << "\t";
211 num_attr = 1; // Always write attributes by default
212 /*
213 * Note that in contrast to other mesh classes, it is perfectly reasonable for
214 * a PottsMesh to have no elements, particularly in when it is being used in
215 * the context of a CaBasedCellPopulation.
216 */
217 if (num_elements != 0)
218 {
219 *p_element_file << num_attr << "\n";
220 }
221 else
222 {
223 *p_element_file << 0 << "\n";
224 }
225
226 // Write each element's data
227 for (unsigned item_num=0; item_num<num_elements; item_num++)
228 {
229 // Get data for this element
230 ElementData elem_data = this->GetNextElement();
231
232 // Get the node indices owned by this element
233 std::vector<unsigned> node_indices = elem_data.NodeIndices;
234
235 // Write this element's index and the number of nodes owned by it to file
236 *p_element_file << item_num << "\t" << node_indices.size();
237
238 // Write the node indices owned by this element to file
239 for (unsigned i=0; i<node_indices.size(); i++)
240 {
241 *p_element_file << "\t" << node_indices[i];
242 }
243
244 // Write the element attribute
245 *p_element_file << "\t" << elem_data.AttributeValue;
246
247 // New line
248 *p_element_file << "\n";
249 }
250
251 *p_element_file << comment << "\n";
252 p_element_file->close();
253}
254
255// Explicit instantiation
256template class PottsMeshWriter<1>;
257template class PottsMeshWriter<2>;
258template class PottsMeshWriter<3>;
virtual ElementData GetNextElement()
virtual std::vector< double > GetNextNode()
static std::string GetProvenanceString()
MeshPottsWriterIterators< SPACE_DIM > * mpIters
ElementData GetNextElement()
PottsMeshWriter(const std::string &rDirectory, const std::string &rBaseName, const bool clearOutputDir=true)
std::vector< double > GetNextNode()
void WriteFilesUsingMesh(PottsMesh< SPACE_DIM > &rMesh)
virtual unsigned GetNumNodes() const
std::vector< unsigned > NodeIndices
PottsMesh< SPACE_DIM >::PottsElementIterator * pElemIter
AbstractMesh< SPACE_DIM, SPACE_DIM >::NodeIterator * pNodeIter