Commit da03443f authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

cleanup of error handling

parent a595e019
Pipeline #4817 passed with stage
in 10 minutes and 3 seconds
......@@ -4,7 +4,6 @@ dune_add_library("gmsh4types" OBJECT
#install headers
install(FILES
filereader.hh
forward.hh
reader.hh
reader.impl.hh
gridcreatorinterface.hh
......
#pragma once
#include <cstddef>
namespace Dune
{
namespace Gmsh4
{
template <class Grid, class Derived>
class GridCreatorInterface;
template <class GridCreator, class Derived>
struct DerivedGridCreator;
// @{ gridcreators
template <class Grid>
struct ContinuousGridCreator;
template <class Grid>
struct DiscontinuousGridCreator;
template <class Grid>
struct LagrangeGridCreator;
template <class Grid>
struct ParallelGridCreator;
template <class Grid>
struct SerialGridCreator;
// @} gridcreators
} // end namespace Gmsh4
template <class Grid, class GridCreator = Gmsh4::ContinuousGridCreator<Grid>, class size_type = std::size_t>
class Gmsh4Reader;
} // end namespace Dune
......@@ -8,7 +8,6 @@
#include <dune/common/shared_ptr.hh>
#include <dune/gmsh4/filereader.hh>
#include <dune/gmsh4/forward.hh>
#include <dune/gmsh4/gridcreators/continuousgridcreator.hh> // default GridCreator
namespace Dune
......@@ -17,12 +16,17 @@ namespace Dune
/**
* Reads .msh files version 4.x and constructs a grid from the cells stored in the file
* Additionally, stored data can be read.
*
* \tparam Grid Type of the grid to construct.
* \tparam GridCreator Policy type to control what to pass to a grid factory with
* data given from the file.
* \tparam SizeType Data type for indices in the .msh file
**/
template <class Grid, class GridCreator, class SizeType>
template <class Grid, class GridCreator = Gmsh4::ContinuousGridCreator<Grid>, class SizeType = std::size_t>
class Gmsh4Reader
: public Gmsh4::FileReader<Grid, Gmsh4Reader<Grid, GridCreator>>
{
// Sections visited during the xml parsing
// Sections visited during the file parsing
enum class Sections {
NO_SECTION = 0, MESH_FORMAT, PHYSICAL_NAMES, ENTITIES, PARTITIONED_ENTITIES, NODES, ELEMENTS, PERIODIC,
GHOST_ELEMENTS, PARAMETRIZATION, NODE_DATA, ELEMENT_DATA, ELEMENT_NODE_DATA, INTERPOLATION_SCHEME
......@@ -35,9 +39,8 @@ namespace Dune
using size_type = SizeType;
/// Constructor. Creates a new GridCreator with the passed factory
template <class... Args>
explicit Gmsh4Reader (Args&&... args)
: creator_(std::make_shared<GridCreator>(std::forward<Args>(args)...))
explicit Gmsh4Reader (GridFactory<Grid>& factory)
: creator_(std::make_shared<GridCreator>(factory))
{}
/// Constructor. Stores a references to the passed creator
......@@ -50,10 +53,11 @@ namespace Dune
: creator_(std::move(creator))
{}
/// Read the grid from file with `filename` into the GridFactory \ref factory_
/// Read the grid from file with `filename` into the GridFactory stored in the GridCreator
/**
* \param filename The name of the input file
* \param create If `false`, only fill internal data structures, if `true`, also create the grid. [true]
* \param filename The name of the input file
* \param fillCreator If `false`, only fill internal data structures,
* if `true`, also calls \ref fillGridCreator. [true]
**/
void read (std::string const& filename, bool fillCreator = true);
......@@ -67,23 +71,25 @@ namespace Dune
/// Advanced read methods
/// @{
/// Read the grid from an input stream, referring to a .vtu file, into the GridFactory \ref factory_
/// Read the grid from an input stream, referring to a .msh file, into the GridCreator
/**
* \param input A STL input stream to read the Gmsh file from.
* \param create If `false`, only fill internal data structures, if `true`, also create the grid. [true]
* \param input A STL input stream to read the Gmsh file from.
* \param fillCreator If `false`, only fill internal data structures,
* if `true`, also calls \ref fillGridCreator. [true]
**/
void readSerialFileFromStream (std::ifstream& input, bool create = true);
void readSerialFileFromStream (std::ifstream& input, bool fillCreator = true);
/// Read the grid from and input stream, referring to a .pvtu file, into the GridFactory \ref factory_
/// Read the grid from and input stream, referring to a .pro file, into the GridCreator
/**
* \param input A STL input stream to read the Gmsh file from.
* \param create If `false`, only fill internal data structures, if `true`, also create the grid. [true]
* \param input A STL input stream to read the Gmsh file from.
* \param fillCreator If `false`, only fill internal data structures,
* if `true`, also calls \ref fillGridCreator. [true]
**/
void readParallelFileFromStream (std::ifstream& input, int rank, int size, bool create = true);
void readParallelFileFromStream (std::ifstream& input, int rank, int size, bool fillCreator = true);
/// Construct a grid using the GridCreator
// NOTE: requires the internal data structures to be filled by an aforgoing call to readFromFile
void fillGridCreator(bool insertPieces = true);
// NOTE: requires the internal data structures to be filled by an aforgoing call to read
void fillGridCreator (bool insertPieces = true);
/// @}
......@@ -116,10 +122,6 @@ namespace Dune
void readElementNodeData (std::ifstream& input);
void readInterpolationScheme (std::ifstream& input);
//template <class BoundaryEntities>
//void determineBoundaryEntities (BoundaryEntities& boundaryEntities);
void reorderNodes ();
// Test whether line belongs to section
bool isSection (std::string line,
std::string key,
......@@ -241,7 +243,6 @@ namespace Dune
size_type minElementTag_ = 0;
size_type maxElementTag_ = 0;
std::vector<ElementAttributes> elements_;
std::vector<PeriodicAttributes> periodic_;
std::vector<GhostElementAttributes> ghostElements_;
std::vector<ParametrizationAttributes> parametrization_;
......@@ -253,7 +254,7 @@ namespace Dune
/// Map the elementType number to number of nodes
static std::map<int, size_type> elementType_;
// Associate a strong with the corresponding Sections enum
// Associate a string with the corresponding Sections enum
static std::map<std::string, Sections> sections_;
};
......
......@@ -7,6 +7,7 @@
#include <dune/common/classname.hh>
#include <dune/common/version.hh>
#include <dune/gmsh4/utility/errors.hh>
#include <dune/gmsh4/utility/filesystem.hh>
#include <dune/gmsh4/utility/string.hh>
......@@ -278,7 +279,7 @@ void Gmsh4Reader<G,C,S>::read (std::string const& filename, bool fillCreator)
DUNE_THROW(IOError, "File " << filename << " does not exist!");
std::ifstream input(filename, std::ios_base::in | std::ios_base::binary);
assert(input.is_open());
GMSH4_ASSERT(input.is_open());
std::string ext = Gmsh4::Path(filename).extension().string();
if (ext == ".msh") {
......@@ -320,14 +321,14 @@ void Gmsh4Reader<G,C,S>::readSerialFileFromStream (std::ifstream& input, bool fi
switch (section) {
case Sections::MESH_FORMAT: {
readMeshFormat(input, version, file_type, data_size);
if (version < 4.0 || version >= 5.0)
throw "Can only read gmsh files versions >= 4.0 and < 5.0)";
if (file_type != 0 and file_type != 1)
throw "Invalid file-type: 0 for ASCII mode, 1 for binary mode";
if (data_size < 4 || data_size > 16)
throw "Invalid data-size range: should be in {4, 16}";
if (file_type == 1 && data_size != sizeof(size_type))
throw "Invalid data-size: must be sizeof(size_t)";
GMSH4_ASSERT_MSG(version >= 4.0 && version < 5.0,
"Can only read gmsh files versions >= 4.0 and < 5.0");
GMSH4_ASSERT_MSG(file_type == 0 || file_type == 1,
"Invalid file-type: 0 for ASCII mode, 1 for binary mode");
GMSH4_ASSERT_MSG(data_size >= 4 && data_size <= 16,
"Invalid data-size range: should be in {4, 16}");
GMSH4_ASSERT_MSG(file_type != 1 || data_size == sizeof(size_type),
"Invalid data-size: must be sizeof(size_t)");
break;
}
case Sections::PHYSICAL_NAMES:
......@@ -377,48 +378,7 @@ template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readParallelFileFromStream (std::ifstream& input, int commRank, int commSize, bool fillCreator)
{
clear();
// Sections section = NO_SECTION;
// for (std::string line; std::getline(input, line); ) {
// Gmsh4::ltrim(line);
// if (isSection(line, "VTKFile", section)) {
// bool closed = false;
// auto attr = parseXml(line, closed);
// if (!attr["type"].empty())
// assert(attr["type"] == "PUnstructuredGrid");
// if (!attr["version"].empty())
// assert(std::stod(attr["version"]) == 1.0);
// if (!attr["byte_order"].empty())
// assert(attr["byte_order"] == "LittleEndian");
// if (!attr["header_type"].empty())
// assert(attr["header_type"] == "UInt64");
// if (!attr["compressor"].empty())
// assert(attr["compressor"] == "vtkZLibDataCompressor"); // only ZLib compression supported
// section = VTK_FILE;
// }
// else if (isSection(line, "/VTKFile", section, VTK_FILE))
// section = NO_SECTION;
// else if (isSection(line, "PUnstructuredGrid", section, VTK_FILE))
// section = UNSTRUCTURED_GRID;
// else if (isSection(line, "/PUnstructuredGrid", section, UNSTRUCTURED_GRID))
// section = VTK_FILE;
// else if (isSection(line, "Piece", section, UNSTRUCTURED_GRID)) {
// bool closed = false;
// auto attr = parseXml(line, closed);
// assert(attr.count("Source") > 0);
// pieces_.push_back(attr["Source"]);
// }
// if (section == NO_SECTION)
// break;
// }
// if (section != NO_SECTION)
// DUNE_THROW(IOError, "VTK-File is incomplete. It must end with </VTKFile>!");
DUNE_THROW(Dune::NotImplemented, "Reading parallel .pro files not yet implemented.");
if (fillCreator)
fillGridCreator();
}
......@@ -496,7 +456,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesAscii (std::ifstream& input)
points_.push_back(attr);
}
assert(points_.size() == numPoints);
GMSH4_ASSERT(points_.size() == numPoints);
// curves
curves_.reserve(numCurves);
......@@ -524,7 +484,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesAscii (std::ifstream& input)
curves_.push_back(attr);
}
assert(curves_.size() == numCurves);
GMSH4_ASSERT(curves_.size() == numCurves);
// surfaces
surfaces_.reserve(numSurfaces);
......@@ -552,7 +512,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesAscii (std::ifstream& input)
surfaces_.push_back(attr);
}
assert(surfaces_.size() == numSurfaces);
GMSH4_ASSERT(surfaces_.size() == numSurfaces);
// volumes
volumes_.reserve(numVolumes);
......@@ -580,7 +540,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesAscii (std::ifstream& input)
volumes_.push_back(attr);
}
assert(volumes_.size() == numVolumes);
GMSH4_ASSERT(volumes_.size() == numVolumes);
}
......@@ -612,7 +572,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesBinary (std::ifstream& input)
points_.push_back(attr);
}
assert(points_.size() == numPoints);
GMSH4_ASSERT(points_.size() == numPoints);
// curves
curves_.reserve(numCurves);
......@@ -641,7 +601,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesBinary (std::ifstream& input)
curves_.push_back(attr);
}
assert(curves_.size() == numCurves);
GMSH4_ASSERT(curves_.size() == numCurves);
// surfaces
surfaces_.reserve(numSurfaces);
......@@ -670,7 +630,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesBinary (std::ifstream& input)
surfaces_.push_back(attr);
}
assert(surfaces_.size() == numSurfaces);
GMSH4_ASSERT(surfaces_.size() == numSurfaces);
// volumes
volumes_.reserve(numVolumes);
......@@ -699,7 +659,7 @@ void Gmsh4Reader<G,C,S>::readEntitiesBinary (std::ifstream& input)
volumes_.push_back(attr);
}
assert(volumes_.size() == numVolumes);
GMSH4_ASSERT(volumes_.size() == numVolumes);
std::string line;
std::getline(input, line);
}
......@@ -731,7 +691,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesAscii (std::ifstream& input)
ghostEntities_.push_back(attr);
}
assert(ghostEntities_.size() == numGhostEntities);
GMSH4_ASSERT(ghostEntities_.size() == numGhostEntities);
}
std::getline(input, line);
......@@ -766,7 +726,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesAscii (std::ifstream& input)
partitionedPoints_.push_back(attr);
}
assert(partitionedPoints_.size() == numPoints);
GMSH4_ASSERT(partitionedPoints_.size() == numPoints);
// curves
partitionedCurves_.reserve(numCurves);
......@@ -801,7 +761,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesAscii (std::ifstream& input)
partitionedCurves_.push_back(attr);
}
assert(partitionedCurves_.size() == numCurves);
GMSH4_ASSERT(partitionedCurves_.size() == numCurves);
// surfaces
partitionedSurfaces_.reserve(numSurfaces);
......@@ -836,7 +796,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesAscii (std::ifstream& input)
partitionedSurfaces_.push_back(attr);
}
assert(partitionedSurfaces_.size() == numSurfaces);
GMSH4_ASSERT(partitionedSurfaces_.size() == numSurfaces);
// volumes
partitionedVolumes_.reserve(numVolumes);
......@@ -871,7 +831,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesAscii (std::ifstream& input)
partitionedVolumes_.push_back(attr);
}
assert(partitionedVolumes_.size() == numVolumes);
GMSH4_ASSERT(partitionedVolumes_.size() == numVolumes);
}
......@@ -892,7 +852,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesBinary (std::ifstream& input)
readValueBinary(input, attr.partition);
ghostEntities_.push_back(attr);
}
assert(ghostEntities_.size() == numGhostEntities);
GMSH4_ASSERT(ghostEntities_.size() == numGhostEntities);
readValueBinary(input, numPoints);
readValueBinary(input, numCurves);
......@@ -926,7 +886,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesBinary (std::ifstream& input)
partitionedPoints_.push_back(attr);
}
assert(partitionedPoints_.size() == numPoints);
GMSH4_ASSERT(partitionedPoints_.size() == numPoints);
// curves
partitionedCurves_.reserve(numCurves);
......@@ -964,7 +924,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesBinary (std::ifstream& input)
partitionedCurves_.push_back(attr);
}
assert(partitionedCurves_.size() == numCurves);
GMSH4_ASSERT(partitionedCurves_.size() == numCurves);
// surfaces
partitionedSurfaces_.reserve(numSurfaces);
......@@ -1002,7 +962,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesBinary (std::ifstream& input)
partitionedSurfaces_.push_back(attr);
}
assert(partitionedSurfaces_.size() == numSurfaces);
GMSH4_ASSERT(partitionedSurfaces_.size() == numSurfaces);
// volumes
partitionedVolumes_.reserve(numVolumes);
......@@ -1040,7 +1000,7 @@ void Gmsh4Reader<G,C,S>::readPartitionedEntitiesBinary (std::ifstream& input)
partitionedVolumes_.push_back(attr);
}
assert(partitionedVolumes_.size() == numVolumes);
GMSH4_ASSERT(partitionedVolumes_.size() == numVolumes);
std::string line;
std::getline(input, line);
}
......@@ -1058,10 +1018,6 @@ void Gmsh4Reader<G,C,S>::readNodesAscii (std::ifstream& input)
stream >> numEntityBlocks >> numNodes_ >> minNodeTag_ >> maxNodeTag_;
}
// assume continuous numbering
// TODO: generalize to sparse numbering
//assert(maxNodeTag_ - minNodeTag_ + 1 == numNodes_); // why? the numbering does not matter...
nodes_.resize(numEntityBlocks);
for (size_type i = 0; i < numEntityBlocks; ++i) {
if (!std::getline(input,line))
......@@ -1158,10 +1114,6 @@ void Gmsh4Reader<G,C,S>::readElementsAscii (std::ifstream& input)
stream >> numEntityBlocks >> numElements_ >> minElementTag_ >> maxElementTag_;
}
// assume continuous numbering
// TODO: generalize to sparse numbering
//assert(maxElementTag_ - minElementTag_ + 1 == numElements_); // why? numbering doesn't matter...
elements_.resize(numEntityBlocks);
for (size_type i = 0; i < numEntityBlocks; ++i) {
if (!std::getline(input,line))
......@@ -1230,174 +1182,53 @@ void Gmsh4Reader<G,C,S>::readElementsBinary (std::ifstream& input)
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readPeriodic (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readPeriodic() is not yet implemented.");
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readGhostElements (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readPeriodic() is not yet implemented.");
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readParametrization (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readParametrization() is not yet implemented.");
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readNodeData (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readNodeData() is not yet implemented.");
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readElementData (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readElementData() is not yet implemented.");
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readElementNodeData (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readElementNodeData() is not yet implemented.");
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::readInterpolationScheme (std::ifstream& input)
{
assert(false && "Not yet implemented");
DUNE_THROW(Dune::NotImplemented, "readInterpolationScheme() is not yet implemented.");
}
//this method was probably added due to a misunderstanding about gmsh's boundary-handling
/*template <class BoundaryEntities, class Elements, class PartitionedElements, class PartitionedFaces>
void getBoundaryEntities(BoundaryEntities& boundaryEntities,
Elements const& elements,
PartitionedElements const& partitionedElements,
PartitionedFaces const& partitionedFaces)
{
if (partitionedElements.empty()) {
for (auto const& element : elements) {
for (int segment : element.boundingEntities)
boundaryEntities.insert(segment);
}
} else {
for (auto const& element : partitionedElements) {
for (int segment : element.boundingEntities) {
for (auto const& face : partitionedFaces) {
if (face.tag == segment && face.partitions.size() == 1) {
boundaryEntities.insert(segment);
break;
}
}
}
}
}
}*/
//this method was probably added due to a misunderstanding about gmsh's boundary-handling
/*template <class G, class C, class S>
template <class BoundaryEntities>
void Gmsh4Reader<G,C,S>::determineBoundaryEntities (BoundaryEntities& boundaryEntities)
{
switch (G::dimension) {
case 1:
getBoundaryEntities(boundaryEntities, curves_, partitionedCurves_, partitionedPoints_);
break;
case 2:
getBoundaryEntities(boundaryEntities, surfaces_, partitionedSurfaces_, partitionedCurves_);
break;
case 3:
getBoundaryEntities(boundaryEntities, volumes_, partitionedVolumes_, partitionedSurfaces_);
break;
default:
std::abort();
}
}*/
//For ALUGrid the corner-vertices have to be listed before the higher-order vertices because
//ALUGrid uses an internal cache that uses the vertex-index and which is not big enough for more
//than all corner vertices.
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::reorderNodes ()
{
std::vector<std::pair<size_type*, bool>> nodeMap(maxNodeTag_ - minNodeTag_ + 1,
std::make_pair(nullptr, false));
for (auto &entityBlock : nodes_) {
for (auto &node : entityBlock.nodes) {
nodeMap[node.tag - minNodeTag_].first = &node.tag;
}
}
using Grid = G;
std::size_t i = 0;
//corner-vertices
for (auto &entityBlock : elements_) {
if (entityBlock.entityDim == Grid::dimension) { //element
auto type = Gmsh4::to_geometry(entityBlock.elementType);
Gmsh4::CellType cell{type};
auto refElem = referenceElement<double,Grid::dimension>(cell.type());
size_t numCorners = refElem.size(Grid::dimension);
for (auto &element : entityBlock.elements) {
assert(element.nodes.size() >= numCorners);
for (std::size_t j = 0; j < numCorners; ++j){
auto& nodeEntry = nodeMap[element.nodes[j] - minNodeTag_];
if(!nodeEntry.second){
nodeEntry.second = true;
*nodeEntry.first = i++;
}
element.nodes[j] = *nodeEntry.first;
}
}
}
}
//other vertices referenced by elements
for (auto &entityBlock : elements_) {
if (entityBlock.entityDim == Grid::dimension) { //element
auto type = Gmsh4::to_geometry(entityBlock.elementType);
Gmsh4::CellType cell{type};
auto refElem = referenceElement<double,Grid::dimension>(cell.type());
size_t numCorners = refElem.size(Grid::dimension);
for (auto &element : entityBlock.elements) {
size_t numVertices = element.nodes.size();
if(numVertices > numCorners){
for (std::size_t j = numCorners; j < numVertices; ++j){
auto& nodeEntry = nodeMap[element.nodes[j] - minNodeTag_];
if(!nodeEntry.second){
nodeEntry.second = true;
*nodeEntry.first = i++;
}
element.nodes[j] = *nodeEntry.first;
}
}
}
}
}
//vertices not referenced by elements
for(auto &nodeEntry : nodeMap){
if(!nodeEntry.second && nodeEntry.first != nullptr)
*nodeEntry.first = i++;
}
minNodeTag_ = 0;
maxNodeTag_ = i - 1;
}
template <class G, class C, class S>
void Gmsh4Reader<G,C,S>::fillGridCreator (bool insertPieces)
{
//if (!nodes_.empty() && !elements_.empty())
// reorderNodes();
if (!nodes_.empty())
creator_->insertVertices(numNodes_, {minNodeTag_, maxNodeTag_}, nodes_);
if (!elements_.empty()) {
std::set<int> boundaryEntities;
//determineBoundaryEntities(boundaryEntities);
creator_->insertElements(numElements_, {minElementTag_, maxElementTag_}, elements_, boundaryEntities);
}
if (insertPieces)
......
......@@ -7,8 +7,6 @@
#include <dune/common/version.hh>
#include <dune/grid/common/gridfactory.hh>
#include <dune/gmsh4/forward.hh>
namespace Dune
{