Commit 4028d756 authored by Douglas Serson's avatar Douglas Serson

Merge branch 'master' into feature/FC-streamfunction

parents 09ac2bda aa34ec09
......@@ -10,6 +10,9 @@ v5.0.0
- Fix ThridpartyCCM options (!802)
- Fix Windows CRLF tokens in GEO reader and improve comment handling (!805)
- Use chrono in Timer (!807)
- Fix caching of FUNCTION tags that read from file and provide the same
functionality in FUNCTIONs defined for forcings (!759)
- Added native support for csv files in addititon to pts (!760)
**NekMesh**:
- Add feature to read basic 2D geo files as CAD (!731)
......@@ -24,6 +27,7 @@ v5.0.0
**FieldConvert**:
- Add input module for Semtex field files (!777)
- Fixed interppoints module (!760)
- Move StreamFunction utility to a FieldConvert module (!809)
**Documentation**:
......
......@@ -221,7 +221,7 @@ to screen;
\item \inltt{TInf} farfield temperature (i.e. $T_{\infty}$). Default value = 288.15 $K$;
\item \inltt{Twall} temperature at the wall when isothermal boundary
conditions are employed (i.e. $T_{w}$). Default value = 300.15$K$;
\item \inltt{uint} farfield $X$-component of the velocity (i.e. $u_{\infty}$). Default value = 0.1 $m/s$;
\item \inltt{uInf} farfield $X$-component of the velocity (i.e. $u_{\infty}$). Default value = 0.1 $m/s$;
\item \inltt{vInf} farfield $Y$-component of the velocity (i.e. $v_{\infty}$). Default value = 0.0 $m/s$;
\item \inltt{wInf} farfield $Z$-component of the velocity (i.e. $w_{\infty}$). Default value = 0.0 $m/s$;
\item \inltt{mu} dynamic viscosity (i.e. $\mu_{\infty}$). Default value = 1.78e-05 $Pa s$;
......
......@@ -503,10 +503,14 @@ To interpolate discrete point data to a field, use the interppointdatatofld modu
\begin{lstlisting}[style=BashInputStyle]
FieldConvert -m interppointdatatofld:frompts=file1.pts file1.xml file1.fld
\end{lstlisting}
or alternatively for csv data:
\begin{lstlisting}[style=BashInputStyle]
FieldConvert -m interppointdatatofld:frompts=file1.csv file1.xml file1.fld
\end{lstlisting}
%
This command will interpolate the data from \inltt{file1.pts} to the mesh
This command will interpolate the data from \inltt{file1.pts} (\inltt{file1.csv}) to the mesh
and expansions defined in \inltt{file1.xml} and output the field to \inltt{file1.fld}.
The file \inltt{file.pts} is of the form:
The file \inltt{file.pts} must be of the form:
%
\begin{lstlisting}[style=XMLStyle]
<?xml version="1.0" encoding="utf-8" ?>
......@@ -527,6 +531,15 @@ the second one contains the $a$-values, the third the $b$-values and so on.
In case of $n$-dimensional data, the $n$ coordinates are specified in the first $n$
columns accordingly.
%
An equivalant csv file is:
\begin{lstlisting}[style=BashInputStyle]
# x, a, b, c
1.0000,-1.0000,1.0000,-0.7778
2.0000,-0.9798,0.9798,-0.7980
3.0000,-0.9596,0.9596,-0.8182
4.0000,-0.9394,0.9394,-0.8384
\end{lstlisting}
%
In order to interpolate 1D data to a $n$D field, specify the matching coordinate in
the output field using the \inltt{interpcoord} argument:
%
......@@ -569,6 +582,15 @@ The format of the file \inltt{file2.pts} is of the same form as for the
</POINTS>
</NEKTAR>
\end{lstlisting}
Similar to the \textit{interppointdatatofld} module, the \inltt{.pts} file can
be interchanged with a \inltt{.csv} file:
\begin{lstlisting}[style=BashInputStyle]
# x, y
0.0,0.0
0.5,0.0
1.0,0.0
\end{lstlisting}
There are three optional arguments \inltt{clamptolowervalue},
\inltt{clamptouppervalue} and \inltt{defaultvalue} the first two clamp the
interpolation between these two values and the third defines the default
......@@ -760,7 +782,8 @@ point, the first, second, and third columns contains the
$x,y,z$-coordinate and subsequent columns contain the field values, in
this case the $p$-value So in the general case of $n$-dimensional
data, the $n$ coordinates are specified in the first $n$ columns
accordingly followed by the field data.
accordingly followed by the field data. Alternatively, the \inltt{file.pts}
can be interchanged with a csv file.
The default argument is to use the equispaced (but potentially
collapsed) coordinates which can be obtained from the command.
......
......@@ -39,6 +39,7 @@ using namespace std;
#include <LibUtilities/BasicUtils/PtsField.h>
#include <LibUtilities/BasicUtils/PtsIO.h>
#include <LibUtilities/BasicUtils/CsvIO.h>
#include <tinyxml.h>
......@@ -53,7 +54,11 @@ ModuleKey InputPts::m_className[5] = {
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eInputModule, "pts"), InputPts::create, "Reads Pts file."),
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eInputModule, "pts.gz"), InputPts::create, "Reads Pts file.")
ModuleKey(eInputModule, "pts.gz"), InputPts::create, "Reads Pts file."),
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eInputModule, "csv"), InputPts::create, "Reads csv file."),
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eInputModule, "csv.gz"), InputPts::create, "Reads csv file."),
};
/**
......@@ -63,6 +68,7 @@ ModuleKey InputPts::m_className[5] = {
InputPts::InputPts(FieldSharedPtr f) : InputModule(f)
{
m_allowedFiles.insert("pts");
m_allowedFiles.insert("csv");
}
/**
......@@ -79,10 +85,23 @@ void InputPts::Process(po::variables_map &vm)
{
string inFile = m_config["infile"].as<string>();
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
ptsIO->Import(inFile, m_f->m_fieldPts);
// Determine appropriate field input
if (m_f->m_inputfiles.count("pts") != 0)
{
LibUtilities::CsvIOSharedPtr csvIO =
MemoryManager<LibUtilities::CsvIO>::AllocateSharedPtr(m_f->m_comm);
csvIO->Import(inFile, m_f->m_fieldPts);
}
else if (m_f->m_inputfiles.count("csv") != 0)
{
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
ptsIO->Import(inFile, m_f->m_fieldPts);
}
else
{
ASSERTL0(false, "unknown input file type");
}
// save field names
for (int j = 0; j < m_f->m_fieldPts->GetNFields(); ++j)
......
......@@ -147,7 +147,7 @@ public:
/// Returns the output field
FIELD_UTILS_EXPORT LibUtilities::PtsFieldSharedPtr GetOutField() const;
/// Print statics of the interpolation weights
/// Returns if the weights have already been computed
FIELD_UTILS_EXPORT void PrintStatistics();
/// sets a callback funtion which gets called every time the interpolation
......
......@@ -6,7 +6,7 @@
//
// The MIT License
//
// Copyright (c) 2016 Kilian Lackhove
// Copyright (c) 2017 Kilian Lackhove
// 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).
......@@ -40,14 +40,21 @@ using namespace std;
#include "OutputPts.h"
#include <LibUtilities/BasicUtils/FileSystem.h>
#include <LibUtilities/BasicUtils/PtsIO.h>
#include <LibUtilities/BasicUtils/CsvIO.h>
namespace Nektar
{
namespace FieldUtils
{
ModuleKey OutputPts::m_className = GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eOutputModule, "pts"), OutputPts::create, "Writes a pts file.");
ModuleKey OutputPts::m_className[5] = {
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eOutputModule, "pts"), OutputPts::create, "Writes a pts file."),
GetModuleFactory().RegisterCreatorFunction(
ModuleKey(eOutputModule, "csv"), OutputPts::create, "Writes a csv file."),
};
OutputPts::OutputPts(FieldSharedPtr f) : OutputFileBase(f)
{
......@@ -62,8 +69,16 @@ void OutputPts::OutputFromPts(po::variables_map &vm)
// Extract the output filename and extension
string filename = m_config["outfile"].as<string>();
LibUtilities::PtsIO ptsIO(m_f->m_comm);
ptsIO.Write(filename, m_f->m_fieldPts);
if (boost::filesystem::path(filename).extension() == ".csv")
{
LibUtilities::CsvIO csvIO(m_f->m_comm);
csvIO.Write(filename, m_f->m_fieldPts);
}
else
{
LibUtilities::PtsIO ptsIO(m_f->m_comm);
ptsIO.Write(filename, m_f->m_fieldPts);
}
}
void OutputPts::OutputFromExp(po::variables_map &vm)
......@@ -126,3 +141,4 @@ fs::path OutputPts::GetFullOutName(std::string &filename,
}
}
......@@ -53,7 +53,7 @@ public:
{
return MemoryManager<OutputPts>::AllocateSharedPtr(f);
}
static ModuleKey m_className;
static ModuleKey m_className[];
OutputPts(FieldSharedPtr f);
virtual ~OutputPts();
......
......@@ -45,6 +45,8 @@ using namespace std;
#include <LibUtilities/BasicUtils/ParseUtils.hpp>
#include <LibUtilities/BasicUtils/PtsField.h>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/BasicUtils/PtsIO.h>
#include <LibUtilities/BasicUtils/CsvIO.h>
#include <boost/math/special_functions/fpclassify.hpp>
namespace bg = boost::geometry;
......@@ -84,11 +86,25 @@ void ProcessInterpPointDataToFld::Process(po::variables_map &vm)
ASSERTL0( m_config["frompts"].as<string>().compare("NotSet") != 0,
"ProcessInterpPointDataToFld requires frompts parameter");
string inFile = m_config["frompts"].as<string>().c_str();
LibUtilities::CommSharedPtr c =
LibUtilities::GetCommFactory().CreateInstance("Serial", 0, 0);
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(c);
ptsIO->Import(inFile, fieldPts);
if (boost::filesystem::path(inFile).extension() == ".pts")
{
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
ptsIO->Import(inFile, fieldPts);
}
else if (boost::filesystem::path(inFile).extension() == ".csv")
{
LibUtilities::CsvIOSharedPtr csvIO =
MemoryManager<LibUtilities::CsvIO>::AllocateSharedPtr(m_f->m_comm);
csvIO->Import(inFile, fieldPts);
}
else
{
ASSERTL0(false, "unknown frompts file type");
}
int nFields = fieldPts->GetNFields();
ASSERTL0(nFields > 0, "No field values provided in input");
......
......@@ -45,6 +45,8 @@ using namespace std;
#include <LibUtilities/BasicUtils/ParseUtils.hpp>
#include <LibUtilities/BasicUtils/Progressbar.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/BasicUtils/PtsIO.h>
#include <LibUtilities/BasicUtils/CsvIO.h>
#include <boost/lexical_cast.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
......@@ -116,8 +118,15 @@ void ProcessInterpPoints::Process(po::variables_map &vm)
MemoryManager<SpatialDomains::DomainRange>::AllocateSharedPtr();
int coordim = m_f->m_fieldPts->GetDim();
int npts = m_f->m_fieldPts->GetNpoints();
std::vector<std::string> fieldNames = m_f->m_fieldPts->GetFieldNames();
for (auto it = fieldNames.begin(); it != fieldNames.end(); ++it)
{
m_f->m_fieldPts->RemoveField(*it);
}
Array<OneD, Array<OneD, NekDouble> > pts;
m_f->m_fieldPts->GetPts(pts);
rng->m_checkShape = false;
rng->m_zmin = -1;
rng->m_zmax = 1;
......@@ -216,14 +225,30 @@ void ProcessInterpPoints::CreateFieldPts(po::variables_map &vm)
int rank = m_f->m_comm->GetRank();
int nprocs = m_f->m_comm->GetSize();
// Check for command line point specification
if (m_config["topts"].as<string>().compare("NotSet") != 0)
{
string inFile = m_config["topts"].as<string>();
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
if (boost::filesystem::path(inFile).extension() == ".pts")
{
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
ptsIO->Import(inFile, m_f->m_fieldPts);
}
else if (boost::filesystem::path(inFile).extension() == ".csv")
{
LibUtilities::CsvIOSharedPtr csvIO =
MemoryManager<LibUtilities::CsvIO>::AllocateSharedPtr(m_f->m_comm);
csvIO->Import(inFile, m_f->m_fieldPts);
}
else
{
ASSERTL0(false, "unknown topts file type");
}
ptsIO->Import(inFile, m_f->m_fieldPts);
}
else if (m_config["line"].as<string>().compare("NotSet") != 0)
{
......@@ -432,7 +457,7 @@ void ProcessInterpPoints::InterpolateFieldToPts(
NekDouble clamp_up,
NekDouble def_value)
{
ASSERTL0(pts->GetNFields() >= field0.size(), "ptField has too few fields");
ASSERTL0(pts->GetNFields() == field0.size(), "ptField has too few fields");
int nfields = field0.size();
......
......@@ -43,6 +43,8 @@ using namespace std;
#include <LibUtilities/BasicUtils/ParseUtils.hpp>
#include <LibUtilities/BasicUtils/Progressbar.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/BasicUtils/PtsIO.h>
#include <LibUtilities/BasicUtils/CsvIO.h>
#include <boost/lexical_cast.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
......@@ -133,10 +135,24 @@ void ProcessInterpPtsToPts::CreateFieldPts(po::variables_map &vm)
{
string inFile = m_config["topts"].as<string>();
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
if (boost::filesystem::path(inFile).extension() == ".pts")
{
LibUtilities::PtsIOSharedPtr ptsIO =
MemoryManager<LibUtilities::PtsIO>::AllocateSharedPtr(m_f->m_comm);
ptsIO->Import(inFile, m_f->m_fieldPts);
}
else if (boost::filesystem::path(inFile).extension() == ".csv")
{
LibUtilities::CsvIOSharedPtr csvIO =
MemoryManager<LibUtilities::CsvIO>::AllocateSharedPtr(m_f->m_comm);
ptsIO->Import(inFile, m_f->m_fieldPts);
csvIO->Import(inFile, m_f->m_fieldPts);
}
else
{
ASSERTL0(false, "unknown topts file type");
}
}
else if (m_config["line"].as<string>().compare("NotSet") != 0)
{
......
////////////////////////////////////////////////////////////////////////////////
//
// File: CsvIO.cpp
//
// For more information, please see: http://www.nektar.info/
//
// The MIT License
//
// Copyright (c) 2017 Kilian Lackhove
// 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: Csv IO
//
////////////////////////////////////////////////////////////////////////////////
#include <LibUtilities/BasicUtils/CsvIO.h>
#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include <fstream>
#include <boost/format.hpp>
#ifdef NEKTAR_USE_MPI
#include <mpi.h>
#endif
#include "ErrorUtil.hpp"
#include <LibUtilities/BasicUtils/FileSystem.h>
using namespace std;
namespace Nektar
{
namespace LibUtilities
{
CsvIO::CsvIO(CommSharedPtr pComm, bool sharedFilesystem)
: PtsIO(pComm, sharedFilesystem)
{
}
/**
* @brief Save a pts field to a file
*
* @param outFile filename of the file
* @param ptsField the pts field
*/
void CsvIO::Write(const string &outFile,
const Nektar::LibUtilities::PtsFieldSharedPtr &ptsField,
const bool backup)
{
int nTotvars = ptsField->GetNFields() + ptsField->GetDim();
int np = ptsField->GetNpoints();
std::string filename = SetUpOutput(outFile, true, backup);
SetUpFieldMetaData(outFile);
std::ofstream ptsFile;
ptsFile.open(filename.c_str());
vector<string> xyz;
xyz.push_back("x");
xyz.push_back("y");
xyz.push_back("z");
xyz.resize(ptsField->GetDim());
string fn = boost::algorithm::join(xyz, ",");
ptsFile << "# " << fn << ",";
fn = boost::algorithm::join(ptsField->GetFieldNames(), ",");
ptsFile << fn;
ptsFile << endl;
Array<OneD, Array<OneD, NekDouble> > pts;
ptsField->GetPts(pts);
for (int i = 0; i < np; ++i)
{
ptsFile << pts[0][i];
for (int j = 1; j < nTotvars; ++j)
{
ptsFile << "," << pts[j][i];
}
ptsFile << endl;
}
ptsFile.close();
}
void CsvIO::v_ImportFieldData(const std::string inFile, PtsFieldSharedPtr& ptsField)
{
std::stringstream errstr;
errstr << "Unable to load file: " << inFile << std::endl;
ifstream in(inFile.c_str());
ASSERTL0(in.is_open(), errstr.str());
string line;
getline(in, line);
boost::erase_first(line, "#");
vector<string> fieldNames;
bool valid = ParseUtils::GenerateOrderedStringVector(line.c_str(), fieldNames);
ASSERTL0(valid, "Unable to process list of fields" + line);
int dim = 0;
for (vector<string>::iterator it = fieldNames.begin(); it != fieldNames.end(); ++it)
{
if (*it == "x" || *it == "y" || *it == "z")
{
dim++;
}
}
fieldNames.erase(fieldNames.begin(), fieldNames.begin() + dim);
int nfields = fieldNames.size();
int totvars = dim + nfields;
vector<NekDouble> ptsSerial;
typedef boost::tokenizer< boost::escaped_list_separator<char> > Tokenizer;
Tokenizer tok(line);
while (getline(in, line))
{
tok.assign(line);
ASSERTL0(distance(tok.begin(), tok.end()) == totvars, "wrong number of columns: " + line);
for (Tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
{
try
{
ptsSerial.push_back(boost::lexical_cast<NekDouble>(boost::trim_copy(string(*it))));
}
catch(const boost::bad_lexical_cast &)
{
ASSERTL0(false, "could not convert line: " + line);
}
}
}
int npts = ptsSerial.size() / totvars;
Array<OneD, Array<OneD, NekDouble> > pts(totvars);
for (int i = 0; i < totvars; ++i)
{
pts[i] = Array<OneD, NekDouble>(npts);
}
for (int i = 0; i < npts; ++i)
{
for (int j = 0; j < totvars; ++j)
{
pts[j][i] = ptsSerial[i * totvars + j];
}
}
ptsField = MemoryManager<PtsField>::AllocateSharedPtr(dim, fieldNames, pts);
}
}
}
///////////////////////////////////////////////////////////////////////////////
//
// File CsvIO.h
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2017 Kilian Lackhove
// 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: Csv IO
//
///////////////////////////////////////////////////////////////////////////////
#ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_CSVIO_H
#define NEKTAR_LIB_UTILITIES_BASIC_UTILS_CSVIO_H
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <LibUtilities/Communication/Comm.h>
#include <LibUtilities/BasicUtils/ErrorUtil.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/BasicUtils/ParseUtils.hpp>
#include <LibUtilities/BasicUtils/PtsField.h>
#include <LibUtilities/BasicUtils/PtsIO.h>
namespace Nektar
{
namespace LibUtilities
{
using namespace std;
class CsvIO : public PtsIO
{
public:
LIB_UTILITIES_EXPORT CsvIO(LibUtilities::CommSharedPtr pComm,
bool sharedFilesystem = false);
LIB_UTILITIES_EXPORT virtual ~CsvIO()