Commit 5c3b9808 authored by David Moxey's avatar David Moxey Committed by Spencer Sherwin
Browse files

Add Semtex field converter, fix bug in Semtex .gz input in NekMesh

parent cf54567c
......@@ -7,6 +7,7 @@ SET(FieldUtilsHeaders
InputModules/InputXml.h
InputModules/InputPts.h
InputModules/InputNek5000.h
InputModules/InputSemtex.h
OutputModules/OutputInfo.h
OutputModules/OutputTecplot.h
OutputModules/OutputVtk.h
......@@ -55,6 +56,7 @@ SET(FieldUtilsSources
InputModules/InputXml.cpp
InputModules/InputPts.cpp
InputModules/InputNek5000.cpp
InputModules/InputSemtex.cpp
OutputModules/OutputInfo.cpp
OutputModules/OutputTecplot.cpp
OutputModules/OutputVtk.cpp
......
////////////////////////////////////////////////////////////////////////////////
//
// File: InputSemtex.cpp
//
// For more information, please see: http://www.nektar.info/
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Reads a Semtex checkpoint file.
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
#include <boost/algorithm/string.hpp>
#include "InputSemtex.h"
namespace Nektar
{
namespace FieldUtils
{
ModuleKey InputSemtex::m_className[1] = {
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eInputModule, "fldsem"), InputSemtex::create,
"Reads Semtex field file.")
};
/**
* @brief Swap endian ordering of the input variable.
*/
template <typename T>
void swap_endian(T &u)
{
union
{
T u;
unsigned char u8[sizeof(T)];
} source, dest;
source.u = u;
for (size_t k = 0; k < sizeof(T); k++)
{
dest.u8[k] = source.u8[sizeof(T) - k - 1];
}
u = dest.u;
}
/**
* @brief Set up InputSemtex object.
*
*/
InputSemtex::InputSemtex(FieldSharedPtr f) : InputModule(f)
{
m_allowedFiles.insert("fldsem");
}
/**
*
*/
InputSemtex::~InputSemtex()
{
}
/**
* @brief Process Semtex input file.
*
* This routine reads a binary-format Semtex field file, loads the data into
* memory and populates the field definitions to match the data format. Semtex
* is a classic nodal-Lagrangian spectral element code at a single polynomial
* order, meaning that the field data are set up according to this structure.
*
* This module is adapted from the VisIt visualisation software, which supports
* a number of Semtex inputs.
*/
void InputSemtex::Process(po::variables_map &vm)
{
if (m_f->m_verbose)
{
if (m_f->m_comm->TreatAsRankZero())
{
cout << "Processing Semtex field file" << endl;
}
}
string sessionName, date, fields;
int nr, ns, nz, nelmt, step;
NekDouble time, dt, kinvis, beta;
string fldending = "fldsem";
ifstream file(m_f->m_inputfiles[fldending][0].c_str(), ios::binary);
// -- Read header information.
char buf[25];
string line;
// Session name
file.read(buf, 25);
sessionName = string(buf, 25);
boost::trim(sessionName);
getline(file, line);
// Date
file.read(buf, 25);
date = string(buf, 25);
boost::trim(date);
getline(file, line);
// nP, nZ, nElmt
file >> nr >> ns >> nz >> nelmt;
getline(file, line);
// Step
file >> step;
getline(file, line);
// Time
file >> time;
getline(file, line);
// Timestep
file >> dt;
getline(file, line);
// Viscosity
file >> kinvis;
getline(file, line);
// Beta
file >> beta;
getline(file, line);
// Fields
file.read(buf, 25);
fields = string(buf, 25);
boost::trim(fields);
getline(file, line);
// TODO Endian-ness
file.read(buf, 25);
bool byteSwap = false;
getline(file, line);
// Print some basic information for input if in verbose mode.
if (m_f->m_verbose)
{
cout << "Found header information:" << endl;
cout << " -- From session : " << sessionName << endl;
cout << " -- File generated : " << date << endl;
cout << " -- Polynomial order : " << nr-1 << endl;
cout << " -- Number of planes : " << nz << endl;
cout << " -- Number of elements : " << nelmt << endl;
cout << " -- Simulation time : " << time << endl;
cout << " -- Timestep : " << dt << endl;
cout << " -- Viscosity : " << kinvis << endl;
cout << " -- Fields : " << fields
<< " (" << fields.size() << " total)" << endl;
if (nz > 1)
{
cout << " -- Homogeneous length : " << 2*M_PI/beta << endl;
}
cout << " -- " << (byteSwap ? "" : "do not ") << "need to swap endian"
<< endl;
}
ASSERTL0(nr == ns, "Semtex reader assumes values of nr and ns are equal");
// Set up a field definition
LibUtilities::FieldDefinitionsSharedPtr fielddef = MemoryManager<
LibUtilities::FieldDefinitions>::AllocateSharedPtr();
fielddef->m_shapeType = LibUtilities::eQuadrilateral;
fielddef->m_homoStrips = false;
fielddef->m_pointsDef = false;
fielddef->m_uniOrder = true;
fielddef->m_numPointsDef = false;
// Set up basis
fielddef->m_basis.push_back(LibUtilities::eGLL_Lagrange);
fielddef->m_basis.push_back(LibUtilities::eGLL_Lagrange);
fielddef->m_numModes.push_back(nr);
fielddef->m_numModes.push_back(nr);
// Set up elements
fielddef->m_elementIDs.resize(nelmt);
for (int i = 0; i < nelmt; ++i)
{
fielddef->m_elementIDs[i] = i;
}
// Deal with homogeneous direction.
if (nz > 1)
{
fielddef->m_numHomogeneousDir = 1;
fielddef->m_homogeneousLengths.push_back(2 * M_PI / beta);
fielddef->m_numModes.push_back(nz);
fielddef->m_basis.push_back(LibUtilities::eFourier);
for (int i = 0; i < nz; ++i)
{
fielddef->m_homogeneousZIDs.push_back(i);
}
}
else
{
fielddef->m_numHomogeneousDir = 0;
}
for (string::size_type i = 0; i < fields.size(); ++i)
{
fielddef->m_fields.push_back(string(&fields[i], 1));
}
// Size of data to read.
size_t elmtSize = nr * ns;
size_t planeSize = elmtSize * nelmt;
size_t fieldSize = planeSize * nz;
size_t dataSize = fieldSize * fields.size();
// Allocate our storage.
m_f->m_data.resize(1);
m_f->m_data[0].resize(dataSize);
// Temporary storage for one plane of data.
vector<NekDouble> tmp(planeSize);
size_t offset = nz * nr * ns;
// Now reorder data; Semtex ordering traverses memory fastest over planes,
// whereas Nektar++ expects it over elements
for (int i = 0; i < fields.size(); ++i)
{
NekDouble *data = &m_f->m_data[0][i * fieldSize];
for (int j = 0; j < nz; ++j)
{
size_t elSizeJ = j * elmtSize;
file.read((char *)&tmp[0], planeSize * sizeof(NekDouble));
for (int k = 0; k < nelmt; ++k)
{
std::copy(&tmp[k * elmtSize], &tmp[(k+1) * elmtSize],
data + k * offset + elSizeJ);
}
}
}
m_f->m_fielddef.push_back(fielddef);
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// File: InputSemtex.h
//
// For more information, please see: http://www.nektar.info/
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Reads a Semtex checkpoint file.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef FIELDUTILS_INPUTSEMTEX
#define FIELDUTILS_INPUTSEMTEX
#include "../Module.h"
namespace Nektar
{
namespace FieldUtils
{
/**
* Converter for Fld files.
*/
class InputSemtex : public InputModule
{
public:
InputSemtex(FieldSharedPtr f);
virtual ~InputSemtex();
virtual void Process(po::variables_map &vm);
/// Creates an instance of this class
static ModuleSharedPtr create(FieldSharedPtr f)
{
return MemoryManager<InputSemtex>::AllocateSharedPtr(f);
}
/// %ModuleKey for class.
static ModuleKey m_className[];
virtual std::string GetModuleName()
{
return "InputSemtex";
}
private:
};
}
}
#endif
......@@ -34,6 +34,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/counter.hpp>
#include "Module.h"
......
......@@ -86,8 +86,8 @@ void InputSem::Process()
// Read through input file and populate the section map.
map<string, streampos>::iterator it;
string line, word;
stringstream ss;
string fileContents, line, word;
stringstream ss, ssFile;
streampos linePos;
sectionMap["NODES"] = -1;
......@@ -98,10 +98,14 @@ void InputSem::Process()
sectionMap["BCS"] = -1;
sectionMap["FIELDS"] = -1;
while (!m_mshFile.eof())
// We need to read entire file into a string and wrap around a stringstream,
// since boost::io::filtered_stream does not support seeking with zlib.
m_fileStream << m_mshFile.rdbuf();
while (!m_fileStream.eof())
{
linePos = m_mshFile.tellg();
getline(m_mshFile, line);
linePos = m_fileStream.tellg();
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -118,8 +122,8 @@ void InputSem::Process()
}
// Clear eofbit and go back to the beginning of the file.
m_mshFile.clear();
m_mshFile.seekg(0);
m_fileStream.clear();
m_fileStream.seekg(0);
// Check that required sections exist in the file.
if (sectionMap["NODES"] == std::streampos(-1))
......@@ -168,8 +172,8 @@ void InputSem::Process()
// Begin by reading in list of nodes which define the linear
// elements.
m_mshFile.seekg(sectionMap["NODES"]);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["NODES"]);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -182,7 +186,7 @@ void InputSem::Process()
i = id = 0;
while (i < nVertices)
{
getline(m_mshFile, line);
getline(m_fileStream, line);
if (line.length() < 7)
continue;
ss.clear();
......@@ -205,8 +209,8 @@ void InputSem::Process()
}
// Now read in elements
m_mshFile.seekg(sectionMap["ELEMENTS"]);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["ELEMENTS"]);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -219,7 +223,7 @@ void InputSem::Process()
i = id = 0;
while (i < nEntities)
{
getline(m_mshFile, line);
getline(m_fileStream, line);
if (line.length() < 18)
{
continue;
......@@ -260,8 +264,8 @@ void InputSem::Process()
{
int np, nel, nodeId = m_mesh->m_node.size();
m_mshFile.seekg(sectionMap["CURVES"]);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["CURVES"]);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -320,7 +324,7 @@ void InputSem::Process()
i = id = 0;
while (i < nCurves)
{
getline(m_mshFile, line);
getline(m_fileStream, line);
if (line.length() < 18)
{
continue;
......@@ -427,9 +431,9 @@ void InputSem::Process()
// Process field names
if (sectionMap["FIELDS"] != std::streampos(-1))
{
m_mshFile.seekg(sectionMap["FIELDS"]);
getline(m_mshFile, line);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["FIELDS"]);
getline(m_fileStream, line);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
......@@ -447,8 +451,8 @@ void InputSem::Process()
int maxTag = -1;
// First read in list of groups, which defines each condition tag.
m_mshFile.seekg(sectionMap["GROUPS"]);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["GROUPS"]);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -461,7 +465,7 @@ void InputSem::Process()
i = id = 0;
while (i < nGroups)
{
getline(m_mshFile, line);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> id >> tag;
......@@ -472,8 +476,8 @@ void InputSem::Process()
// Now read in actual values for boundary conditions from BCS
// section.
m_mshFile.seekg(sectionMap["BCS"]);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["BCS"]);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -489,7 +493,7 @@ void InputSem::Process()
int nF;
string tmp;
ConditionSharedPtr p;
getline(m_mshFile, line);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> id >> tag >> nF;
......@@ -501,7 +505,7 @@ void InputSem::Process()
j = 0;
while (j < nF)
{
getline(m_mshFile, line);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> tmp;
......@@ -560,8 +564,8 @@ void InputSem::Process()
}
// Finally read surface information.
m_mshFile.seekg(sectionMap["SURFACES"]);
getline(m_mshFile, line);
m_fileStream.seekg(sectionMap["SURFACES"]);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> word;
......@@ -579,7 +583,7 @@ void InputSem::Process()
while (i < nSurf)
{
getline(m_mshFile, line);
getline(m_fileStream, line);
ss.clear();
ss.str(line);
ss >> id >> elmt >> side >> word;
......@@ -649,7 +653,6 @@ void InputSem::Process()
}
PrintSummary();
m_mshFile.reset();
// Process rest of mesh.
ProcessVertices();
......
......@@ -62,6 +62,7 @@ public:
static NekMeshUtils::ModuleKey className;
private:
stringstream m_fileStream;
void insertEdge(int elmt, int side, int tagId);
/// Maps Semtex sections to positions inside the input file.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment