Commit 13953d56 authored by David Moxey's avatar David Moxey

Add a NekMesh logger, enable Python as a backend to allow native output in...

Add a NekMesh logger, enable Python as a backend to allow native output in Jupyter notebooks. Change input modules to use this and remove abort() in as many places as possible.
parent 43ab5684
......@@ -282,6 +282,8 @@ MACRO(ADD_NEKPY_LIBRARY name)
# Python requires a .so extension, even on OS X.
SET_TARGET_PROPERTIES(_${name} PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES(_${name} PROPERTIES SUFFIX ".so")
SET_TARGET_PROPERTIES(_${name} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/NekPy/${name})
ADD_DEPENDENCIES(_${name} boost-numpy)
......@@ -301,7 +303,6 @@ MACRO(ADD_NEKPY_LIBRARY name)
SET(TMPOUT "${TMPOUT}from ._${name} import *")
FILE(WRITE ${CMAKE_BINARY_DIR}/NekPy/${name}/__init__.py ${TMPOUT})
INSTALL(TARGETS _${name} DESTINATION ${CMAKE_BINARY_DIR}/NekPy/${name})
ENDMACRO()
#
......
......@@ -85,10 +85,8 @@ void InputCADfix::Process()
module->SetDefaults();
module->Process();
if (m_mesh->m_verbose)
{
cout << endl << "Loading mesh from CFI" << endl;
}
m_log(VERBOSE) << "Loading mesh from CFI file '"
<< m_config["infile"].as<string>() << "'" << endl;
m_mesh->m_expDim = 3;
m_mesh->m_spaceDim = 3;
......@@ -117,10 +115,7 @@ void InputCADfix::Process()
map<int, NodeSharedPtr> nodes;
vector<cfi::NodeDefinition> *cfinodes = m_model->getFenodes();
if (m_mesh->m_verbose)
{
cout << "Nodes " << cfinodes->size() << endl;
}
m_log(VERBOSE) << "Nodes " << cfinodes->size() << endl;
// filter all mesh nodes into a indexed map and project to CAD
for (auto &it : *cfinodes)
......@@ -254,10 +249,7 @@ void InputCADfix::Process()
int prefix = m_mesh->m_cad->GetNumSurf() > 100 ? 1000 : 100;
if (m_mesh->m_verbose)
{
cout << "prisms " << prisms->size() << endl;
}
m_log(VERBOSE) << "Prisms " << prisms->size() << endl;
int nm[6] = {3, 2, 5, 0, 1, 4};
for (auto &it : *prisms)
......@@ -287,10 +279,7 @@ void InputCADfix::Process()
}
delete prisms;
if (m_mesh->m_verbose)
{
cout << "tets " << tets->size() << endl;
}
m_log(VERBOSE) << "tets " << tets->size() << endl;
for (auto &it : *tets)
{
......@@ -317,10 +306,7 @@ void InputCADfix::Process()
}
delete tets;
if (m_mesh->m_verbose)
{
cout << "hexes " << hexs->size() << endl;
}
m_log(VERBOSE) << "hexes " << hexs->size() << endl;
for (auto &it : *hexs)
{
......@@ -355,10 +341,8 @@ void InputCADfix::Process()
vector<cfi::ElementDefinition> *tris =
m_model->getElements(cfi::SUBTYPE_TR3, 3);
if (m_mesh->m_verbose)
{
cout << "tris " << tris->size() << endl;
}
m_log(VERBOSE) << "tris " << tris->size() << endl;
for (auto &it : *tris)
{
......@@ -386,8 +370,10 @@ void InputCADfix::Process()
E->GetEdgeList(), LibUtilities::ePolyEvenlySpaced));
FaceSet::iterator fnd = m_mesh->m_faceSet.find(fc);
ASSERTL0(fnd != m_mesh->m_faceSet.end(),
"surface element not found in mesh");
if (fnd == m_mesh->m_faceSet.end())
{
m_log(FATAL) << "Surface element not found in mesh" << endl;
}
FaceSharedPtr mf = *fnd;
......@@ -402,10 +388,8 @@ void InputCADfix::Process()
vector<cfi::ElementDefinition> *quads =
m_model->getElements(cfi::SUBTYPE_QU4, 4);
if (m_mesh->m_verbose)
{
cout << "quads " << quads->size() << endl;
}
m_log(VERBOSE) << "quads " << quads->size() << endl;
for (auto &it : *quads)
{
......@@ -434,8 +418,10 @@ void InputCADfix::Process()
E->GetEdgeList(), LibUtilities::ePolyEvenlySpaced));
FaceSet::iterator fnd = m_mesh->m_faceSet.find(fc);
ASSERTL0(fnd != m_mesh->m_faceSet.end(),
"surface element not found in mesh");
if (fnd == m_mesh->m_faceSet.end())
{
m_log(FATAL) << "Surface element not found in mesh" << endl;
}
FaceSharedPtr mf = *fnd;
......@@ -470,10 +456,8 @@ void InputCADfix::Process()
vector<cfi::ElementDefinition> *beams =
m_model->getElements(cfi::SUBTYPE_BE2, 2);
if (m_mesh->m_verbose)
{
cout << "beams " << beams->size() << endl;
}
m_log(VERBOSE) << "beams " << beams->size() << endl;
for (auto &it : *beams)
{
......@@ -527,11 +511,12 @@ void InputCADfix::Process()
}
catch (runtime_error &e)
{
cout << "High-order surface meshing has failed with message:" << endl;
cout << e.what() << endl;
cout << "The mesh will be written as normal but the incomplete surface "
"will remain faceted"
<< endl;
m_log(WARNING) << "High-order surface meshing has failed with message:"
<< endl;
m_log(WARNING) << e.what() << endl;
m_log(WARNING) << "The mesh will be written as normal but the "
<< "incomplete surface will remain faceted (linear)."
<< endl;
return;
}
......
......@@ -460,7 +460,8 @@ std::vector<int> tetTensorNodeOrdering(const std::vector<int> &nodes, int n)
*
* @return The nodes vector in tensor-product ordering.
*/
std::vector<int> prismTensorNodeOrdering(const std::vector<int> &nodes, int n)
std::vector<int> prismTensorNodeOrdering(const std::vector<int> &nodes, int n,
Logger &log)
{
std::vector<int> nodeList;
......@@ -497,8 +498,11 @@ std::vector<int> prismTensorNodeOrdering(const std::vector<int> &nodes, int n)
nodeList[8] = nodes[6];
}
ASSERTL0(n < 4, "Prism Gmsh input and output is incomplete for orders "
"larger than 4");
if (n >= 4)
{
log(FATAL) << "Prism Gmsh input and output is incomplete for orders "
<< "larger than 4." << endl;
}
return nodeList;
}
......@@ -742,10 +746,8 @@ void InputGmsh::Process()
int elm_type = 0;
int tmp = 0;
if (m_mesh->m_verbose)
{
cout << "InputGmsh: Start reading file..." << endl;
}
m_log(VERBOSE) << "Reading Gmsh file: '" << m_config["infile"].as<string>()
<< "'" << std::endl;
std::vector<std::map<int, GmshEntity>> entityMap(4);
......@@ -762,9 +764,18 @@ void InputGmsh::Process()
getline(m_mshFile, line);
stringstream s(line);
s >> m_version;
if (m_version > 4.1)
{
m_log(FATAL) << "Cannot read .msh file format versions greater "
<< "than version 4.1." << endl;
}
s >> fileType;
ASSERTL0(fileType == 0, "Cannot read binary Gmsh files.")
ASSERTL0(m_version <= 4.1, ".msh file format versions greater than 4.1 are not currently supported.")
if (fileType != 0)
{
m_log(FATAL) << "Cannot read binary Gmsh files." << endl;
}
}
// Process entities (v4+)
else if (word == "$Entities")
......@@ -948,23 +959,26 @@ void InputGmsh::Process()
if (printInfo)
{
cout << "Multiple elements in composite detected; remapped:" << endl;
m_log << "Multiple elements of different types in the same physical "
<< "surface or volume detected." << endl;
m_log << "These will be remapped to:" << endl;
for (auto &cIt : compMap)
{
if (cIt.second.size() > 1)
{
auto sIt = cIt.second.begin();
cout << "- Tag " << cIt.first << " => " << sIt->second << " ("
<< LibUtilities::ShapeTypeMap[sIt->first] << ")";
m_log << "- Tag " << cIt.first << " => " << sIt->second << " ("
<< LibUtilities::ShapeTypeMap[sIt->first] << ")";
sIt++;
for (; sIt != cIt.second.end(); ++sIt)
{
cout << ", " << sIt->second << " ("
<< LibUtilities::ShapeTypeMap[sIt->first] << ")";
m_log << ", " << sIt->second << " ("
<< LibUtilities::ShapeTypeMap[sIt->first] << ")";
}
cout << endl;
m_log << endl;
}
}
}
......@@ -975,6 +989,8 @@ void InputGmsh::Process()
ProcessFaces();
ProcessElements();
ProcessComposites();
PrintSummary();
}
/**
......@@ -1084,8 +1100,7 @@ void InputGmsh::ReadNextElement(int tag, int elm_type)
auto it = elmMap.find(elm_type);
if (it == elmMap.end())
{
cerr << "Error: element type " << elm_type << " not supported" << endl;
abort();
m_log(FATAL) << "Element type " << elm_type << " not supported" << endl;
}
// Read element tags (version 2 only)
......@@ -1128,9 +1143,8 @@ void InputGmsh::ReadNextElement(int tag, int elm_type)
// If it's not created, then create it.
if (oIt == m_orderingMap.end())
{
oIt =
m_orderingMap.insert(make_pair(elm_type, CreateReordering(elm_type)))
.first;
oIt = m_orderingMap.insert(
make_pair(elm_type, CreateReordering(elm_type, m_log))).first;
}
// Apply reordering map where necessary.
......@@ -1161,14 +1175,14 @@ void InputGmsh::ReadNextElement(int tag, int elm_type)
*/
int InputGmsh::GetNnodes(unsigned int InputGmshEntity)
{
int nNodes;
int nNodes = 0;
auto it = elmMap.find(InputGmshEntity);
if (it == elmMap.end())
{
cerr << "Unknown element type " << InputGmshEntity << endl;
abort();
m_log(FATAL) << "Gmsh file contains an unknown element type "
<< InputGmshEntity << endl;
}
switch (it->second.m_e)
......@@ -1199,8 +1213,8 @@ int InputGmsh::GetNnodes(unsigned int InputGmshEntity)
nNodes = Hexahedron::GetNumNodes(it->second);
break;
default:
cerr << "Unknown element type!" << endl;
abort();
m_log(FATAL) << "Gmsh file contains an unknown element type"
<< endl;
break;
}
......@@ -1215,14 +1229,15 @@ int InputGmsh::GetNnodes(unsigned int InputGmshEntity)
* they work with the Nektar++ orderings, since this is what is used in
* the elements defined in the converter.
*/
vector<int> InputGmsh::CreateReordering(unsigned int InputGmshEntity)
vector<int> InputGmsh::CreateReordering(unsigned int InputGmshEntity,
Logger &log)
{
auto it = elmMap.find(InputGmshEntity);
if (it == elmMap.end())
{
cerr << "Unknown element type " << InputGmshEntity << endl;
abort();
log(FATAL) << "Gmsh file contains an unknown element type "
<< InputGmshEntity << endl;
}
// For specific elements, call the appropriate function to perform
......@@ -1239,7 +1254,7 @@ vector<int> InputGmsh::CreateReordering(unsigned int InputGmshEntity)
return TetReordering(it->second);
break;
case LibUtilities::ePrism:
return PrismReordering(it->second);
return PrismReordering(it->second, log);
break;
case LibUtilities::eHexahedron:
return HexReordering(it->second);
......@@ -1520,7 +1535,7 @@ vector<int> InputGmsh::TetReordering(ElmtConfig conf)
* generating higher than second-order prismatic meshes, so most of the
* following is untested.
*/
vector<int> InputGmsh::PrismReordering(ElmtConfig conf)
vector<int> InputGmsh::PrismReordering(ElmtConfig conf, Logger &log)
{
const int order = conf.m_order;
const int n = order - 1;
......@@ -1730,7 +1745,7 @@ vector<int> InputGmsh::PrismReordering(ElmtConfig conf)
}
// Reorder interior points
tmp = prismTensorNodeOrdering(intPoints, order - 1);
tmp = prismTensorNodeOrdering(intPoints, order - 1, log);
mapping.insert(mapping.end(), tmp.begin(), tmp.end());
return mapping;
......
......@@ -65,14 +65,21 @@ public:
* Element map; takes a msh id to an %ElmtConfig object.
*/
static std::map<unsigned int, NekMesh::ElmtConfig> elmMap;
static std::vector<int> CreateReordering(unsigned int InputGmshEntity);
static std::vector<int> CreateReordering(unsigned int InputGmshEntity,
Logger &log);
virtual std::string GetModuleName()
{
return "InputGmsh";
}
private:
int GetNnodes(unsigned int InputGmshEntity);
static std::vector<int> TriReordering (NekMesh::ElmtConfig conf);
static std::vector<int> QuadReordering (NekMesh::ElmtConfig conf);
static std::vector<int> HexReordering (NekMesh::ElmtConfig conf);
static std::vector<int> PrismReordering(NekMesh::ElmtConfig conf);
static std::vector<int> PrismReordering(NekMesh::ElmtConfig conf,
Logger &log);
static std::vector<int> TetReordering (NekMesh::ElmtConfig conf);
static std::vector<int> LineReordering (NekMesh::ElmtConfig conf);
......
......@@ -81,11 +81,20 @@ void InputMCF::ParseFile(string nm)
m_mesh->m_comm = comm;
}
ASSERTL0(pSession->DefinesElement("NEKTAR/MESHING"), "no meshing tag");
ASSERTL0(pSession->DefinesElement("NEKTAR/MESHING/INFORMATION"),
"no information tag");
ASSERTL0(pSession->DefinesElement("NEKTAR/MESHING/PARAMETERS"),
"no parameters tag");
if (!pSession->DefinesElement("NEKTAR/MESHING"))
{
m_log(FATAL) << "Input file is missing a MESHING tag." << endl;
}
if (!pSession->DefinesElement("NEKTAR/MESHING/INFORMATION"))
{
m_log(FATAL) << "Input file is missing an INFORMATION tag." << endl;
}
if (!pSession->DefinesElement("NEKTAR/MESHING/PARAMETERS"))
{
m_log(FATAL) << "Input file is missing a PARAMETERS tag." << endl;
}
TiXmlElement *mcf = pSession->GetElement("NEKTAR/MESHING");
......@@ -198,11 +207,20 @@ void InputMCF::ParseFile(string nm)
}
auto it = information.find("CADFile");
ASSERTL0(it != information.end(), "no cadfile defined");
if (it == information.end())
{
m_log(FATAL) << "No 'CADFile' property found in the INFORMATION "
<< "section." << endl;
}
m_cadfile = it->second;
it = information.find("MeshType");
ASSERTL0(it != information.end(), "no meshtype defined");
if (it == information.end())
{
m_log(FATAL) << "No 'MeshType' property found in the INFORMATION "
<< "section." << endl;
}
m_makeBL = it->second == "3DBndLayer";
m_2D = it->second == "2D";
......@@ -214,35 +232,64 @@ void InputMCF::ParseFile(string nm)
m_2D = true;
}
if (!m_makeBL && !m_2D && !m_manifold)
if (!m_makeBL && !m_2D && !m_manifold && it->second != "3D")
{
ASSERTL0(it->second == "3D", "unsure on MeshType")
if (it == information.end())
{
m_log(FATAL) << "Invalid 'MeshType' property found in the "
<< "INFORMATION section: should be one of 2D, 3D, "
<< "2DBndLayer, 3DBndLayer or Manifold." << endl;
}
}
it = parameters.find("MinDelta");
ASSERTL0(it != parameters.end(), "no mindelta defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'MinDelta' parameter found in the PARAMETERS "
<< "section." << endl;
}
m_minDelta = it->second;
it = parameters.find("MaxDelta");
ASSERTL0(it != parameters.end(), "no maxdelta defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'MaxDelta' parameter found in the PARAMETERS "
<< "section." << endl;
}
m_maxDelta = it->second;
it = parameters.find("EPS");
ASSERTL0(it != parameters.end(), "no eps defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'EPS' parameter found in the PARAMETERS "
<< "section." << endl;
}
m_eps = it->second;
it = parameters.find("Order");
ASSERTL0(it != parameters.end(), "no order defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'Order' parameter found in the PARAMETERS "
<< "section." << endl;
}
m_order = it->second;
if (m_makeBL)
{
it = parameters.find("BndLayerSurfaces");
ASSERTL0(it != parameters.end(), "no BndLayersurfs defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'BndLayerSurfaces' parameter found in the "
<< "PARAMETERS section." << endl;
}
m_blsurfs = it->second;
it = parameters.find("BndLayerThickness");
ASSERTL0(it != parameters.end(), "no BndLayerthick defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'BndLayerThickness' parameter found in the "
<< "PARAMETERS section." << endl;
}
m_blthick = it->second;
it = parameters.find("BndLayerLayers");
......@@ -294,19 +341,39 @@ void InputMCF::ParseFile(string nm)
stringstream ss;
it = parameters.find("Xmin");
ASSERTL0(it != parameters.end(), "no xmin defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'Xmin' parameter found in the "
<< "PARAMETERS section." << endl;
}
ss << it->second << ",";
it = parameters.find("Ymin");
ASSERTL0(it != parameters.end(), "no ymin defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'Ymin' parameter found in the "
<< "PARAMETERS section." << endl;
}
ss << it->second << ",";
it = parameters.find("Xmax");
ASSERTL0(it != parameters.end(), "no xmax defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'Xmax' parameter found in the "
<< "PARAMETERS section." << endl;
}
ss << it->second << ",";
it = parameters.find("Ymax");
ASSERTL0(it != parameters.end(), "no zmax defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'Ymax' parameter found in the "
<< "PARAMETERS section." << endl;
}
ss << it->second << ",";
it = parameters.find("AOA");
ASSERTL0(it != parameters.end(), "no aoa defined");
if (it == parameters.end())
{
m_log(FATAL) << "No 'AOA' parameter found in the "
<< "PARAMETERS section." << endl;
}
ss << it->second;
m_nacadomain = ss.str();
......@@ -444,10 +511,10 @@ void InputMCF::Process()
}
catch (runtime_error &e)
{
cout << "2D linear mesh generator failed with message:" << endl;
cout << e.what() << endl;
cout << "No mesh file has been created" << endl;
abort();
m_log(WARNING) << "2D linear mesh generator failed with message:"
<< endl;
m_log(WARNING) << e.what() << endl;
m_log(FATAL) << "No mesh file has been created." << endl;
}
}
else
......@@ -463,12 +530,15 @@ void InputMCF::Process()
}
catch (runtime_error &e)
{
cout << "Surface meshing has failed with message:" << endl;
cout << e.what() << endl;
cout << "Any surfaces which were succsessfully meshed will be "
"dumped as a manifold mesh"
<< endl;
m_log(WARNING) << "Surface meshing has failed with message:"
<< endl;
m_log(WARNING) << e.what() << endl;
m_log(WARNING) << "Any surfaces which were successfully meshed will"
<< " be written as a manifold mesh."
<< endl;
m_mesh->m_expDim = 2;
ProcessVertices();
ProcessEdges();
ProcessFaces();
......@@ -479,7 +549,7 @@ void InputMCF::Process()
if (m_manifold)
{
// dont want to volume mesh
// Don't want to volume mesh.
m_mesh->m_expDim = 2;
}
else
......@@ -502,18 +572,22 @@ void InputMCF::Process()
}
catch (runtime_error &e)
{
cout << "Volume meshing has failed with message:" << endl;
cout << e.what() << endl;
cout << "The linear surface mesh be dumped as a manifold "
"mesh"
<< endl;
m_log(WARNING) << "Volume meshing has failed with message:"
<< endl;
m_log(WARNING) << e.what() << endl;
m_log(WARNING) << "The linear surface mesh be written as a "
<< "manifold mesh"
<< endl;
m_mesh->m_expDim = 2;
m_mesh->m_element[3].clear();
ProcessVertices();
ProcessEdges();
ProcessFaces();
ProcessElements();
ProcessComposites();
return;
}
}
......@@ -534,11 +608,12 @@ void InputMCF::Process()
}
catch (runtime_error &e)
{
cout << "High-order surface meshing has failed with message:" << endl;
cout << e.what() << endl;