13#ifndef ANSYS_MESH_READER_HH
14#define ANSYS_MESH_READER_HH
28#include <boost/lexical_cast.hpp>
30#include <dune/common/fvector.hh>
31#include "dune/grid/config.h"
35#include <dune/grid/uggrid/uggridfactory.hh>
39#include <dune/grid/albertagrid/gridfactory.hh>
43#include <dune/grid/alugrid/3d/alu3dgridfactory.hh>
66 explicit AnsysMeshReader(
double scale_=1.0,
int verbose_=0) : scale(scale_), verbose(verbose_)
74 template <
class Gr
id,
class Scalar>
75 std::unique_ptr<Grid>
readGrid(std::string
const& fileName,
int initialGridSize = 1000)
77 constexpr int dim = Grid::dimension;
78 std::ifstream file(fileName);
81 if(!(
bool)file)
throw IOException(std::string(
"Could not read file ") + fileName, __FILE__, __LINE__);
82 else if(verbose>=1) std::cout <<
"Reading " << fileName << std::endl;
85 std::vector<Dune::FieldVector<Scalar,dim> > vertices;
86 std::vector<std::vector<unsigned int> > cubes;
87 std::vector<std::pair<unsigned int,unsigned int> > offsets(1,std::make_pair(0,0));
89 auto NOT_FOUND = std::string::npos;
94 if(buffer.find(
"*HEADING") == NOT_FOUND)
95 throw IOException(std::string(
"Error reading file ") + fileName +
"at line " + std::to_string(currentLine),__FILE__,__LINE__);
97 short elementSetId = 0;
104 getline(file,buffer);
108 if(verbose >= 1) std::cout << buffer << std::endl;
109 if(buffer[0] !=
'*')
throw IOException(std::string(
"Expected comment at line " + std::to_string(currentLine) +
"."),__FILE__,__LINE__);
110 if(buffer.find(
"**") != NOT_FOUND)
112 if(buffer.find(
"Materialdaten") != NOT_FOUND)
break;
113 if(verbose >= 1) std::cout <<
"End of section. Starting new one." << std::endl;
114 getline(file,buffer);
119 if(buffer.find(
"*NODE") != NOT_FOUND)
121 if(verbose >= 1) std::cout <<
"Reading vertices...";
122 readVertices<double>(file, buffer, vertices, offsets);
123 if(verbose >= 1) std::cout <<
"done: " << vertices.size() <<
" entries.\n" << std::endl;
128 if(buffer.find(
"*ELEMENT") != NOT_FOUND)
130 if(buffer.find(
"TYPE=C3D8") != NOT_FOUND)
132 std::string::size_type pos = buffer.find(
"ELSET=");
133 if(pos == NOT_FOUND)
throw IOException(std::string(
"Could not determine element set."),__FILE__,__LINE__);
136 if (verbose >= 1) std::cout <<
"Reading elements..." << std::flush;
137 readElements(file, buffer, cubes, offsets);
138 if (verbose >= 1) std::cout <<
"done: " << cubes.size() <<
" entries.\n" << std::endl;
142 if(buffer.find(
"TYPE=C3D4") != NOT_FOUND)
144 std::string::size_type pos = buffer.find(
"ELSET=");
145 if(pos == NOT_FOUND)
throw IOException(std::string(
"Could not determine element set."),__FILE__,__LINE__);
147 if (verbose >= 1) std::cout <<
"Reading tetrahedra..." << std::flush;
148 readTetrahedra(file, buffer, cubes, offsets, elementSetId++);
149 if (verbose >= 1) std::cout <<
"done: " << cubes.size() <<
" entries.\n" << std::endl;
153 throw IOException(std::string(
"For Ansys meshes currently only supported for cubic and tetrahedral geometries."),__FILE__,__LINE__);
158 Dune::GridFactory<Grid> factory = IOTools::FactoryGenerator<Grid>::createFactory(initialGridSize);
160 if (verbose >= 1) std::cout <<
"inserting vertices...";
161 for(
auto const& vertex : vertices) factory.insertVertex(vertex);
162 if (verbose >= 1) std::cout <<
"done." << std::endl;
165 if (verbose >= 1) std::cout <<
"inserting elements...";
167 for (
auto const& vertexIds: cubes) {
170 for (
auto vertexId: vertexIds)
174 factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex,dim),vertexIds);
176 if (verbose >= 1) std::cout <<
"done." << std::endl;
180 if (verbose >= 1) std::cout <<
"grid creation finished\n\n";
182 return std::unique_ptr<Grid>(factory.createGrid());
189 template <
class FSElement>
192 assert(element.coefficients().N() == elementSetIds.size());
193 for(
size_t i=0; i<elementSetIds.size(); ++i)
194 element.coefficients()[i][0] =
static_cast<typename FSElement::Scalar
>(elementSetIds[i]);
199 template <
class Scalar,
int dim>
202 BoundingBox() :
max(-1.0*std::numeric_limits<Scalar>::
max()),
min(std::numeric_limits<Scalar>::
max())
211 for(
int i=0; i<dim; ++i)
220 for(
int i=0; i<dim; ++i)
221 if ((
min[i] > v[i]) || (
max[i] < v[i]))
228 std::cout <<
"Bounding Box" << std::endl;
229 for(
int i=0; i<dim; ++i) std::cout << i <<
": [" <<
min[i] <<
", " <<
max[i] <<
"]" << std::endl;
230 std::cout << std::endl;
236 static const char delimiter =
',';
244 void sortElements(std::vector<std::vector<unsigned int> >& elements)
const;
252 void adjustElement(std::vector<unsigned int>& element, std::vector<std::pair<unsigned int,unsigned int> >
const& offsets);
254 inline void removeLeadingWhiteSpaces(std::string& buffer)
256 buffer.erase(0,buffer.find_first_not_of(
' '));
259 template <
class Type>
260 inline Type readEntry(std::ifstream& file, std::string& buffer)
262 getline(file,buffer,delimiter);
263 removeLeadingWhiteSpaces(buffer);
264 return boost::lexical_cast<Type>(buffer);
267 template <
class Scalar,
int dim>
269 std::vector<std::pair<unsigned int,unsigned int> >& offsets)
273 unsigned int currentIndex = 1, givenIndex;
276 getline(file,buffer,delimiter);
277 removeLeadingWhiteSpaces(buffer);
281 givenIndex = boost::lexical_cast<unsigned int>(buffer);
284 if(currentIndex+offsets.back().second > givenIndex)
286 std::cerr << vertices.size() <<
", " << currentIndex <<
", " << offsets.back().second <<
", " << givenIndex << std::endl;
287 throw IOException(std::string(
"currentIndex > givenIndex in line ") + std::to_string(currentLine),__FILE__,__LINE__);
290 if(currentIndex + offsets.back().second < givenIndex)
291 offsets.push_back(std::make_pair(givenIndex-1, givenIndex - currentIndex));
295 vertex[0] = readEntry<Scalar>(file,buffer);
296 vertex[1] = readEntry<Scalar>(file,buffer);
302 vertices.push_back(vertex);
304 getline(file,buffer);
309 getline(file,buffer);
312 getline(file,buffer,delimiter);
313 removeLeadingWhiteSpaces(buffer);
317 void readElements(std::ifstream& file, std::string& buffer, std::vector<std::vector<unsigned int> >& elements,
318 std::vector<std::pair<unsigned int,unsigned int> >
const& offsets);
321 void readTetrahedra(std::ifstream& file, std::string& buffer, std::vector<std::vector<unsigned int> >& elements,
322 const std::vector<std::pair<unsigned int,unsigned int> >& offsets,
short elementSetId);
324 template <
class Scalar,
int dim>
327 return (v0-v1).two_norm2() <= power<2>(100*std::numeric_limits<Scalar>::epsilon()) * (v0.two_norm2() + v1.two_norm2());
330 template <
class Scalar,
int dim>
333 for(
size_t i=0; i<vertices.size(); ++i)
334 if(equal(vertex,vertices[i]))
336 return vertices.size();
340 template <
class Scalar,
int dim>
342 std::vector<unsigned int>
const& element, std::vector<unsigned int>& newElement,
unsigned int index)
344 for(
size_t i=0; i<element.size(); ++i)
346 unsigned int index = getIndex(vertices[element[i]], elementVertices);
347 if(index==elementVertices.size())
349 newElement[i] = elementVertices.size();
350 elementVertices.push_back(vertices[element[i]]);
353 newElement[i] = index;
358 void getline(std::ifstream& file, std::string& line,
char const delim=
'\n');
360 std::vector<short> elementSetIds;
Reader for Ansys *.inp grid files.
void readElementSetIds(FSElement &element) const
Extracts the element set id of each cell and stores it in the coefficient of a discontinuous P0 FE fu...
std::unique_ptr< Grid > readGrid(std::string const &fileName, int initialGridSize=1000)
Reads an Ansys file and creates a corresponding grid.
AnsysMeshReader(double scale_=1.0, int verbose_=0)
Constructor.
An exception class for IO errors.
std::pair< Dune::FieldVector< typename GridView::ctype, GridView::dimensionworld >, Dune::FieldVector< typename GridView::ctype, GridView::dimensionworld > > boundingBox(GridView const &gv)
Computes a the bounding box of the given grid view.
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
Lagrange Finite Elements.