dune-grid 2.9.1
Loading...
Searching...
No Matches
gmshwriter.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5#ifndef DUNE_GRID_IO_FILE_GMSHWRITER_HH
6#define DUNE_GRID_IO_FILE_GMSHWRITER_HH
7
8#include <fstream>
9#include <iostream>
10#include <iomanip>
11#include <string>
12#include <vector>
13
15#include <dune/geometry/type.hh>
19
20namespace Dune {
21
35 template <class GridView>
37 {
38 private:
39 const GridView gv;
40 int precision;
41
42 static const unsigned int dim = GridView::dimension;
43 static const unsigned int dimWorld = GridView::dimensionworld;
44 static_assert( (dimWorld <= 3), "GmshWriter requires dimWorld <= 3." );
45
47 template<typename Entity>
48 std::size_t nodeIndexFromEntity(const Entity& entity, int i) const {
49 return gv.indexSet().subIndex(entity, i, dim)+1;
50 }
51
55 static std::size_t translateDuneToGmshType(const GeometryType& type) {
56 std::size_t element_type;
57
58 if (type.isLine())
59 element_type = 1;
60 else if (type.isTriangle())
61 element_type = 2;
62 else if (type.isQuadrilateral())
63 element_type = 3;
64 else if (type.isTetrahedron())
65 element_type = 4;
66 else if (type.isHexahedron())
67 element_type = 5;
68 else if (type.isPrism())
69 element_type = 6;
70 else if (type.isPyramid())
71 element_type = 7;
72 else if (type.isVertex())
73 element_type = 15;
74 else
75 DUNE_THROW(Dune::IOError, "GeometryType " << type << " is not supported by gmsh.");
76
77 return element_type;
78 }
79
94 void outputElements(std::ofstream& file, const std::vector<int>& physicalEntities, const std::vector<int>& physicalBoundaries) const {
96 std::size_t counter(1);
97 for (const auto& entity : elements(gv)) {
98 // Check whether the type is compatible. If not, close file and rethrow exception.
99 try {
100 std::size_t element_type = translateDuneToGmshType(entity.type());
101
102 file << counter << " " << element_type;
103 // If present, set the first tag to the physical entity
104 if (!physicalEntities.empty())
105 file << " " << 1 << " " << physicalEntities[elementMapper.index(entity)];
106 else
107 file << " " << 0; // "0" for "I do not use any tags."
108
109 // Output list of nodes.
110 // 3, 5 and 7 got different vertex numbering compared to Dune
111 if (3 == element_type)
112 file << " "
113 << nodeIndexFromEntity(entity, 0) << " " << nodeIndexFromEntity(entity, 1) << " "
114 << nodeIndexFromEntity(entity, 3) << " " << nodeIndexFromEntity(entity, 2);
115 else if (5 == element_type)
116 file << " "
117 << nodeIndexFromEntity(entity, 0) << " " << nodeIndexFromEntity(entity, 1) << " "
118 << nodeIndexFromEntity(entity, 3) << " " << nodeIndexFromEntity(entity, 2) << " "
119 << nodeIndexFromEntity(entity, 4) << " " << nodeIndexFromEntity(entity, 5) << " "
120 << nodeIndexFromEntity(entity, 7) << " " << nodeIndexFromEntity(entity, 6);
121 else if (7 == element_type)
122 file << " "
123 << nodeIndexFromEntity(entity, 0) << " " << nodeIndexFromEntity(entity, 1) << " "
124 << nodeIndexFromEntity(entity, 3) << " " << nodeIndexFromEntity(entity, 2) << " "
125 << nodeIndexFromEntity(entity, 4);
126 else {
127 for (int k = 0; k < entity.geometry().corners(); ++k)
128 file << " " << nodeIndexFromEntity(entity, k);
129 }
130 ++counter;
131
132 file << std::endl;
133
134 // Write boundaries
135 if (!physicalBoundaries.empty()) {
136 auto refElement = referenceElement<typename GridView::ctype,dim>(entity.type());
137 for(const auto& intersection : intersections(gv, entity)) {
138 if(intersection.boundary()) {
139 const auto faceLocalIndex(intersection.indexInInside());
140 file << counter << " " << translateDuneToGmshType(intersection.type())
141 << " " << 1 << " " << physicalBoundaries[intersection.boundarySegmentIndex()];
142 for (int k = 0; k < intersection.geometry().corners(); ++k)
143 {
144 const auto vtxLocalIndex(refElement.subEntity(faceLocalIndex, 1, k, dim));
145 file << " " << nodeIndexFromEntity(entity, vtxLocalIndex);
146 }
147 ++counter;
148 file << std::endl;
149 }
150 }
151 }
152
153 } catch(Exception& e) {
154 file.close();
155 throw;
156 }
157 }
158 }
159
160
167 void outputNodes(std::ofstream& file) const {
168 for (const auto& vertex : vertices(gv)) {
169 const auto globalCoord = vertex.geometry().center();
170 const auto nodeIndex = gv.indexSet().index(vertex)+1; // Start counting indices by "1".
171
172 if (1 == dimWorld)
173 file << nodeIndex << " " << globalCoord[0] << " " << 0 << " " << 0 << std::endl;
174 else if (2 == dimWorld)
175 file << nodeIndex << " " << globalCoord[0] << " " << globalCoord[1] << " " << 0 << std::endl;
176 else // (3 == dimWorld)
177 file << nodeIndex << " " << globalCoord[0] << " " << globalCoord[1] << " " << globalCoord[2] << std::endl;
178 }
179 }
180
181 public:
187 GmshWriter(const GridView& gridView, int numDigits=6) : gv(gridView), precision(numDigits) {}
188
193 void setPrecision(int numDigits) {
194 precision = numDigits;
195 }
196
218 void write(const std::string& fileName,
219 const std::vector<int>& physicalEntities=std::vector<int>(),
220 const std::vector<int>& physicalBoundaries=std::vector<int>()) const {
221 // Open file
222 std::ofstream file(fileName.c_str());
223 if (!file.is_open())
224 DUNE_THROW(Dune::IOError, "Could not open " << fileName << " with write access.");
225
226 // Set precision
227 file << std::setprecision( precision );
228
229 // Output Header
230 file << "$MeshFormat" << std::endl
231 << "2.0 0 " << sizeof(double) << std::endl // "2.0" for "version 2.0", "0" for ASCII
232 << "$EndMeshFormat" << std::endl;
233
234 // Output Nodes
235 file << "$Nodes" << std::endl
236 << gv.size(dim) << std::endl;
237
238 outputNodes(file);
239
240 file << "$EndNodes" << std::endl;
241
242 // Output Elements;
243 int boundariesSize(0);
244 if(!physicalBoundaries.empty())
245 for(const auto& entity : elements(gv))
246 for(const auto& intersection : intersections(gv, entity))
247 if(intersection.boundary())
248 ++boundariesSize;
249
250 file << "$Elements" << std::endl
251 << gv.size(0) + boundariesSize<< std::endl;
252
253 outputElements(file, physicalEntities, physicalBoundaries);
254
255 file << "$EndElements" << std::endl;
256 }
257
258 };
259
260} // namespace Dune
261
262#endif // DUNE_GRID_IO_FILE_GMSHWRITER_HH
Mapper for multiple codim and multiple geometry types.
size_type dim() const
#define DUNE_THROW(E, m)
const IndexSet & indexSet() const
obtain the index set
Definition common/gridview.hh:191
int size(int codim) const
obtain number of entities in a given codimension
Definition common/gridview.hh:197
static constexpr int dimension
The dimension of the grid.
Definition common/gridview.hh:148
static constexpr int dimensionworld
The dimension of the world the grid lives in.
Definition common/gridview.hh:151
MCMGLayout mcmgElementLayout()
layout for elements (codim-0 entities)
Definition mcmgmapper.hh:97
Include standard header files.
constexpr bool isPyramid() const
constexpr bool isTetrahedron() const
constexpr bool isPrism() const
constexpr bool isVertex() const
constexpr bool isTriangle() const
constexpr bool isLine() const
constexpr bool isQuadrilateral() const
constexpr bool isHexahedron() const
Wrapper class for entities.
Definition common/entity.hh:66
Geometry geometry() const
obtain geometric realization of the entity
Definition common/entity.hh:141
GeometryType type() const
Return the name of the reference element. The type can be used to access the Dune::ReferenceElement.
Definition common/entity.hh:146
Grid view abstract base class.
Definition common/gridview.hh:66
Implementation class for a multiple codim and multiple geometry type mapper.
Definition mcmgmapper.hh:129
Index index(const EntityType &e) const
Map entity to starting index in array for dof block.
Definition mcmgmapper.hh:171
Write Gmsh mesh file.
Definition gmshwriter.hh:37
GmshWriter(const GridView &gridView, int numDigits=6)
Constructor expecting GridView of Grid to be written.
Definition gmshwriter.hh:187
void setPrecision(int numDigits)
Set the number of digits to be used when writing the vertices. By default is 6.
Definition gmshwriter.hh:193
void write(const std::string &fileName, const std::vector< int > &physicalEntities=std::vector< int >(), const std::vector< int > &physicalBoundaries=std::vector< int >()) const
Write given grid in Gmsh 2.0 compatible ASCII file.
Definition gmshwriter.hh:218
Different resources needed by all grid implementations.
T c_str(T... args)
T close(T... args)
T empty(T... args)
T endl(T... args)
T is_open(T... args)
T setprecision(T... args)