OGS
FileIO::SwmmInterface Class Referencefinal

Detailed Description

Interface for reading files used within the Storm Water Management Model (SWMM) and converting the data therein into corresponding OGS data structures. SWMM distinguishes four different object types (defined in the SwmmObject enum):

  • Subcatchments
  • Nodes (or junctions)
  • Links (or conduits)
  • System Note that each object in a SWMM input file has a name. Each of the four object types has a (different) number of parameters. There can be an arbitrary number of nodes, links or subcatchments but only ever one system. The interface can convert the SWMM input data into a geometry or a (line-)mesh. For meshes, also output data can be added to nodes and elements. The interface also provides routines for returning data as vectors as well as convenience methods for outputting data into CSV files. CSV files will either contain all parameters for one object at all time steps or all parameters for all objects of a given type at one timestep.

Definition at line 59 of file SWMMInterface.h.

#include <SWMMInterface.h>

Classes

struct  Subcatchment
 

Public Member Functions

MeshLib::MeshgetMesh () const
 Returns the mesh generated from SWMM file content. More...
 
std::string getArrayName (SwmmObject obj_type, std::size_t var_idx) const
 Returns the name of the data array for the given object type and parameter index. More...
 
std::vector< std::string > getNames (SwmmObject obj_type) const
 Get all the object names for a given object type. More...
 
std::string getName (SwmmObject obj_type, std::size_t idx) const
 Returns the Name for the indexed object of the given type (or an empty string if an error occurred). More...
 
std::size_t getNumberOfObjects (SwmmObject obj_type) const
 Returns the number of objects of the given type. More...
 
std::size_t getNumberOfParameters (SwmmObject obj_type) const
 Returns the number of parameters (incl. pollutants) of the given type. More...
 
std::size_t getNumberOfTimeSteps () const
 Returns the number of time steps for the simulation results. More...
 
std::vector< double > getArrayAtTimeStep (SwmmObject obj_type, std::size_t time_step, std::size_t var_idx) const
 Returns an array for a given variable at all nodes/links from a SWMM output file for a given time step. More...
 
std::vector< double > getArrayForObject (SwmmObject obj_type, std::size_t obj_idx, std::size_t var_idx) const
 Returns an array for a given variable for one specific object from a SWMM output file for all time steps. More...
 
bool getNodeCoordinateVectors (std::vector< double > &x, std::vector< double > &y, std::vector< double > &z) const
 Writes the node coordinates into double vectors for writing of CSV files. More...
 
bool getLinkPointIds (std::vector< std::size_t > &inlets, std::vector< std::size_t > &outlets) const
 Writes the inlet- and outlet IDs for links into vectors for writing of CSV files. More...
 
bool writeCsvForTimestep (std::string const &file_name, SwmmObject obj_type, std::size_t time_step) const
 Write a CSV file for all object of the given type at one time step. More...
 
bool writeCsvForObject (std::string const &file_name, SwmmObject obj_type, std::size_t obj_idx) const
 Write a CSV file for one object of the given type for all time steps. More...
 
bool existsSwmmOutputFile () const
 Checks if a SWMM output file exists for the current input. More...
 
 ~SwmmInterface ()
 Destructor. More...
 

Static Public Member Functions

static std::unique_ptr< SwmmInterfacecreate (std::string const &file_name)
 
static bool addResultsToMesh (MeshLib::Mesh &mesh, SwmmObject const type, std::string const &vec_name, std::vector< double > const &data)
 
static bool isSwmmInputFile (std::string const &inp_file_name)
 Checks if file is a SWMM input file. More...
 
static std::string swmmObjectTypeToString (SwmmObject const obj_type)
 Returns a string with the name of the object type. More...
 
static bool convertSwmmInputToGeometry (std::string const &inp_file_name, GeoLib::GEOObjects &geo_objects, bool add_subcatchments)
 Reading a SWMM input file and conversion into OGS geometry. More...
 

Private Member Functions

 SwmmInterface (std::string const &swmm_base_name)
 Constructor. More...
 
bool readSwmmInputToLineMesh ()
 Reading a SWMM input file and creating an OGS line mesh. This is automatically called when the object is created. More...
 
bool readNodeData (std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::map< std::string, std::size_t > const &name_id_map, std::vector< double > &max_depth, bool read_max_depth)
 Reads input information associated with nodes (elevation, depth, etc.) More...
 
bool readLineElements (std::ifstream &in, std::vector< MeshLib::Element * > &elements, std::vector< MeshLib::Node * > const &nodes, std::map< std::string, std::size_t > const &name_id_map)
 Reads links/conduits and returns them as a vector of OGS line elements. More...
 
bool readSubcatchments (std::ifstream &in, std::map< std::string, std::size_t > const &name_id_map)
 Reads subcatchment information. More...
 
bool readPollutants (std::ifstream &in)
 Reads pollutant names and parameters. More...
 
std::string getArrayName (SwmmObject obj_type, std::size_t var_idx, std::size_t n_pollutants) const
 Returns the name of an array (or an empty string if errors occurred) More...
 
bool addRainGaugeTimeSeriesLocations (std::ifstream &in)
 Reads the location of external rain gauge time series files. More...
 
bool matchSubcatchmentsWithPolygons (std::vector< GeoLib::Polyline * > const &lines, std::vector< std::string > const &names)
 Matches existing subcatchment names with subsequently read polylines marking the outlines of said subcatchments. More...
 
std::vector< std::string > getSubcatchmentNameMap () const
 Creates a temporary string vector containing all subcatchment names in correct order. More...
 

Static Private Member Functions

template<typename T >
static bool readCoordinates (std::ifstream &in, std::vector< T * > &points, std::vector< std::string > &names)
 
static bool addPointElevation (std::ifstream &in, std::vector< GeoLib::Point * > &points, std::map< std::string, std::size_t > const &name_id_map)
 During geometry conversion, this adds elevation values to the existing point vector. More...
 
static bool readLinksAsPolylines (std::ifstream &in, std::vector< GeoLib::Polyline * > &lines, std::vector< std::string > &line_names, std::vector< GeoLib::Point * > const &points, std::map< std::string, std::size_t > const &point_names)
 During geometry conversion, this reads links (conduits/pumps/weirs) and converts them into polylines. More...
 
static bool readPolygons (std::ifstream &in, std::vector< GeoLib::Polyline * > &lines, std::vector< std::string > &line_names, std::vector< GeoLib::Point * > &points, std::vector< std::string > &pnt_names)
 
static bool isSectionFinished (std::string const &str)
 Checks if the given line string is empty. Empty strings mark the end of sections in a SWMM input file. More...
 
static bool isCommentLine (std::string const &str)
 Checks if the given line string is a comment line. More...
 

Private Attributes

std::string const _base_name
 All files for a given SWMM simulation have the same base name. More...
 
std::vector< std::string > _id_nodename_map
 Vector storing the names of all nodes/junctions. More...
 
std::vector< std::string > _id_linkname_map
 Vector storing the names of all links/conduits. More...
 
std::vector< std::string > _pollutant_names
 Vector storing the names of all pollutants. More...
 
std::vector< Subcatchment_subcatchments
 Vector storing information about all subcatchments. More...
 
std::vector< GeoLib::Point * > _subcatchment_points
 Separate node vector containing points for defining subcatchment outlines. More...
 
std::vector< std::pair< GeoLib::Station, std::string > > _rain_gauges
 Vector containing rain gauge information as well the position of external time series files. More...
 
std::unique_ptr< MeshLib::Mesh_mesh
 Mesh generated from SWMM input (+ optional output data) More...
 

Constructor & Destructor Documentation

◆ ~SwmmInterface()

FileIO::SwmmInterface::~SwmmInterface ( )

Destructor.

Definition at line 112 of file SWMMInterface.cpp.

113 {
114  for (Subcatchment& sc : _subcatchments)
115  delete sc.outline;
116 
118  delete pnt;
119 }
std::vector< GeoLib::Point * > _subcatchment_points
Separate node vector containing points for defining subcatchment outlines.
std::vector< Subcatchment > _subcatchments
Vector storing information about all subcatchments.

References _subcatchment_points, and _subcatchments.

◆ SwmmInterface()

FileIO::SwmmInterface::SwmmInterface ( std::string const &  swmm_base_name)
private

Constructor.

Definition at line 107 of file SWMMInterface.cpp.

108  : _base_name(swmm_base_name), _mesh(nullptr)
109 {
110 }
std::unique_ptr< MeshLib::Mesh > _mesh
Mesh generated from SWMM input (+ optional output data)
std::string const _base_name
All files for a given SWMM simulation have the same base name.

Referenced by create().

Member Function Documentation

◆ addPointElevation()

bool FileIO::SwmmInterface::addPointElevation ( std::ifstream &  in,
std::vector< GeoLib::Point * > &  points,
std::map< std::string, std::size_t > const &  name_id_map 
)
staticprivate

During geometry conversion, this adds elevation values to the existing point vector.

Definition at line 264 of file SWMMInterface.cpp.

267 {
268  std::string line;
269  while (std::getline(in, line))
270  {
271  if (isSectionFinished(line))
272  return true;
273 
274  if (isCommentLine(line))
275  continue;
276 
277  std::vector<std::string> const split_str(BaseLib::splitString(line));
278  // Junctions = 6, Outfalls = 4, Storage = 8
279  if (split_str.size() < 4)
280  {
281  ERR("Format not recognised.");
282  return false;
283  }
284  std::string const current_name(split_str[0]);
285  auto const it = name_id_map.find(current_name);
286  if (it == name_id_map.end())
287  {
288  ERR("SwmmInterface::addPointElevation(): Name {:s} not found in "
289  "coordinates map.",
290  current_name);
291  return false;
292  }
293  std::size_t const id = it->second;
294  (*points[id])[2] = BaseLib::str2number<double>(split_str[1]);
295  }
296  return true;
297 }
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
static bool isCommentLine(std::string const &str)
Checks if the given line string is a comment line.
static bool isSectionFinished(std::string const &str)
Checks if the given line string is empty. Empty strings mark the end of sections in a SWMM input file...
std::vector< std::string > splitString(std::string const &str)
Definition: StringTools.cpp:28

References ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by convertSwmmInputToGeometry().

◆ addRainGaugeTimeSeriesLocations()

bool FileIO::SwmmInterface::addRainGaugeTimeSeriesLocations ( std::ifstream &  in)
private

Reads the location of external rain gauge time series files.

Definition at line 1224 of file SWMMInterface.cpp.

1225 {
1226  std::string line;
1227  while (getline(in, line))
1228  {
1229  if (isSectionFinished(line))
1230  break;
1231 
1232  if (isCommentLine(line))
1233  continue;
1234 
1235  std::vector<std::string> const split_str(BaseLib::splitString(line));
1236  if (split_str.size() < 6)
1237  {
1238  ERR("Rain gauge parameter format not recognised.");
1239  return false;
1240  }
1241 
1242  for (auto& stn : _rain_gauges)
1243  {
1244  if (stn.first.getName() == split_str[0] && split_str[4] == "FILE")
1245  stn.second = split_str[5].substr(1, split_str[5].size() - 2);
1246  }
1247  }
1248 
1249  for (auto const& stn : _rain_gauges)
1250  if (stn.second.empty())
1251  WARN("No associated time series found for rain gauge '{:s}'.",
1252  stn.first.getName());
1253  return true;
1254 }
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
std::vector< std::pair< GeoLib::Station, std::string > > _rain_gauges
Vector containing rain gauge information as well the position of external time series files.

References _rain_gauges, ERR(), isCommentLine(), isSectionFinished(), BaseLib::splitString(), and WARN().

Referenced by readSwmmInputToLineMesh().

◆ addResultsToMesh()

bool FileIO::SwmmInterface::addResultsToMesh ( MeshLib::Mesh mesh,
SwmmObject const  type,
std::string const &  vec_name,
std::vector< double > const &  data 
)
static

If a mesh has already been created, this methods allows to add node- or link-arrays as property to that mesh. The data vectors can be created using the getArrayAtTimeStep() method.

Definition at line 983 of file SWMMInterface.cpp.

987 {
988  if (!(swmm_type == SwmmObject::NODE || swmm_type == SwmmObject::LINK))
989  {
990  ERR("Information of this object type cannot be added to mesh.");
991  return false;
992  }
993 
994  if (data.empty())
995  {
996  ERR("Data array is empty and cannot be added to mesh.");
997  return false;
998  }
999 
1000  if (swmm_type == SwmmObject::NODE && data.size() != mesh.getNumberOfNodes())
1001  {
1002  ERR("Number of mesh nodes ({:d}) does not match length of array "
1003  "({:d}).",
1004  mesh.getNumberOfNodes(), data.size());
1005  return false;
1006  }
1007 
1008  if (swmm_type == SwmmObject::LINK &&
1009  data.size() != mesh.getNumberOfElements())
1010  {
1011  ERR("Number of mesh elements ({:d}) does not match length of array "
1012  "({:d}).",
1013  mesh.getNumberOfElements(), data.size());
1014  return false;
1015  }
1016 
1017  MeshLib::MeshItemType const item_type = (swmm_type == SwmmObject::NODE)
1021  MeshLib::getOrCreateMeshProperty<double>(mesh, vec_name, item_type, 1);
1022  if (!prop)
1023  {
1024  ERR("Error fetching array '{:s}'.", vec_name);
1025  return false;
1026  }
1027  std::copy(data.cbegin(), data.cend(), prop->begin());
1028  return true;
1029 }
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition: Mesh.h:89
std::size_t getNumberOfElements() const
Get the number of elements.
Definition: Mesh.h:86
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
MeshItemType
Definition: Location.h:21

References MeshLib::Cell, MathLib::LinAlg::copy(), ERR(), MeshLib::Mesh::getNumberOfElements(), MeshLib::Mesh::getNumberOfNodes(), FileIO::LINK, FileIO::NODE, and MeshLib::Node.

Referenced by addObjectsToMesh().

◆ convertSwmmInputToGeometry()

bool FileIO::SwmmInterface::convertSwmmInputToGeometry ( std::string const &  inp_file_name,
GeoLib::GEOObjects geo_objects,
bool  add_subcatchments 
)
static

Reading a SWMM input file and conversion into OGS geometry.

Definition at line 351 of file SWMMInterface.cpp.

354 {
355  if (!isSwmmInputFile(inp_file_name))
356  return false;
357 
358  std::ifstream in(inp_file_name.c_str());
359  if (!in.is_open())
360  {
361  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
362  return false;
363  }
364 
365  std::vector<GeoLib::Point*> points;
366  std::vector<GeoLib::Polyline*> lines;
367  std::vector<std::string> pnt_names;
368  std::vector<std::string> line_names;
369 
370  std::string geo_name =
372  std::string line;
373  while (std::getline(in, line))
374  {
375  if (line == "[COORDINATES]" || line == "[VERTICES]" ||
376  line == "[SYMBOLS]")
377  {
378  if (!readCoordinates<GeoLib::Point>(in, points, pnt_names))
379  {
380  BaseLib::cleanupVectorElements(points, lines);
381  return false;
382  }
383  }
384  if (line == "[Polygons]" && add_subcatchments)
385  {
386  if (!readPolygons(in, lines, line_names, points, pnt_names))
387  {
388  BaseLib::cleanupVectorElements(points, lines);
389  return false;
390  }
391  }
392  }
393 
394  if (points.empty())
395  {
396  ERR("No points found in file");
397  return false;
398  }
399  if (points.size() != pnt_names.size())
400  {
401  ERR("Length of point vector and point name vector do not match.");
402  BaseLib::cleanupVectorElements(points, lines);
403  return false;
404  }
405 
406  GeoLib::PointVec::NameIdMap name_id_map;
407  {
408  std::size_t const n_names(pnt_names.size());
409  for (std::size_t i = 0; i < n_names; ++i)
410  {
411  if (!pnt_names[i].empty())
412  name_id_map.insert(std::make_pair(pnt_names[i], i));
413  }
414  }
415 
416  // rewind stream and read links between junctions
417  in.clear();
418  in.seekg(0, in.beg);
419 
420  while (std::getline(in, line))
421  {
422  if (line == "[JUNCTIONS]")
423  {
424  INFO("Reading point elevation...");
425  if (!addPointElevation(in, points, name_id_map))
426  {
427  BaseLib::cleanupVectorElements(points, lines);
428  return false;
429  }
430  }
431  if (line == "[CONDUITS]")
432  {
433  INFO("Reading conduits...");
434  if (!readLinksAsPolylines(in, lines, line_names, points,
435  name_id_map))
436  {
437  BaseLib::cleanupVectorElements(points, lines);
438  return false;
439  }
440  }
441  else if (line == "[PUMPS]")
442  {
443  INFO("Reading pumps...");
444  if (!readLinksAsPolylines(in, lines, line_names, points,
445  name_id_map))
446  {
447  BaseLib::cleanupVectorElements(points, lines);
448  return false;
449  }
450  }
451  else if (line == "[WEIRS]")
452  {
453  INFO("Reading weirs...");
454  if (!readLinksAsPolylines(in, lines, line_names, points,
455  name_id_map))
456  {
457  BaseLib::cleanupVectorElements(points, lines);
458  return false;
459  }
460  }
461  }
462 
463  geo_objects.addPointVec(std::move(points), geo_name,
464  std::move(name_id_map));
465  if (!lines.empty())
466  {
467  if (lines.size() != line_names.size())
468  {
469  ERR("Length of line vector and line name vector do not match.");
470  geo_objects.removePointVec(geo_name);
471  for (auto ply : lines)
472  delete ply;
473  return false;
474  }
475  GeoLib::PolylineVec::NameIdMap line_id_map;
476  {
477  std::size_t const n_names(line_names.size());
478  for (std::size_t i = 0; i < n_names; ++i)
479  {
480  line_id_map.insert(std::make_pair(line_names[i], i));
481  }
482  }
483  std::vector<std::size_t> const& pnt_id_map(
484  geo_objects.getPointVecObj(geo_name)->getIDMap());
485  for (GeoLib::Polyline* polyline : lines)
486  {
487  for (std::size_t i = 0; i < polyline->getNumberOfPoints(); ++i)
488  {
489  polyline->setPointID(i, pnt_id_map[polyline->getPointID(i)]);
490  if (i > 0 &&
491  polyline->getPointID(i - 1) == polyline->getPointID(i))
492  {
493  polyline->removePoint(i);
494  i--;
495  }
496  }
497  if (polyline->getPointID(0) ==
498  polyline->getPointID(polyline->getNumberOfPoints() - 1))
499  {
500  polyline->removePoint(polyline->getNumberOfPoints() - 1);
501  polyline->addPoint(polyline->getPointID(0));
502  }
503  }
504  geo_objects.addPolylineVec(std::move(lines), geo_name,
505  std::move(line_id_map));
506  }
507  return true;
508 }
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
static bool readPolygons(std::ifstream &in, std::vector< GeoLib::Polyline * > &lines, std::vector< std::string > &line_names, std::vector< GeoLib::Point * > &points, std::vector< std::string > &pnt_names)
static bool isSwmmInputFile(std::string const &inp_file_name)
Checks if file is a SWMM input file.
static bool readLinksAsPolylines(std::ifstream &in, std::vector< GeoLib::Polyline * > &lines, std::vector< std::string > &line_names, std::vector< GeoLib::Point * > const &points, std::map< std::string, std::size_t > const &point_names)
During geometry conversion, this reads links (conduits/pumps/weirs) and converts them into polylines.
static bool addPointElevation(std::ifstream &in, std::vector< GeoLib::Point * > &points, std::map< std::string, std::size_t > const &name_id_map)
During geometry conversion, this adds elevation values to the existing point vector.
void addPolylineVec(std::vector< Polyline * > &&lines, std::string const &name, PolylineVec::NameIdMap &&ply_names)
Definition: GEOObjects.cpp:152
void addPointVec(std::vector< Point * > &&points, std::string &name, PointVec::NameIdMap &&pnt_id_name_map, double const eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Definition: GEOObjects.cpp:47
const PointVec * getPointVecObj(const std::string &name) const
Definition: GEOObjects.cpp:85
bool removePointVec(const std::string &name)
Definition: GEOObjects.cpp:98
const std::vector< std::size_t > & getIDMap() const
Definition: PointVec.h:96
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition: Polyline.h:53
std::map< std::string, std::size_t > NameIdMap
Definition: TemplateVec.h:44
void cleanupVectorElements(std::vector< T * > &items)
Definition: Algorithm.h:300
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180

References addPointElevation(), GeoLib::GEOObjects::addPointVec(), GeoLib::GEOObjects::addPolylineVec(), BaseLib::cleanupVectorElements(), ERR(), BaseLib::extractBaseNameWithoutExtension(), GeoLib::PointVec::getIDMap(), GeoLib::GEOObjects::getPointVecObj(), INFO(), isSwmmInputFile(), readLinksAsPolylines(), readPolygons(), and GeoLib::GEOObjects::removePointVec().

Referenced by writeGeoOutput().

◆ create()

std::unique_ptr< SwmmInterface > FileIO::SwmmInterface::create ( std::string const &  file_name)
static

Basic method to create the interface (containing a mesh) from a SWMM file Other non-static methods rely on this being called in the beginning.

Definition at line 84 of file SWMMInterface.cpp.

86 {
87  // The input/output methods take a base name and check if the corresponding
88  // i/o file for that base name exists. This check takes any swmm project
89  // file, i.e. [base name].[extension] which needs to be at least 5 chars
90  // because the extension is always 3 chars.
91  if (file_name.length() < 5)
92  return nullptr;
93 
94  if (!SwmmInterface::isSwmmInputFile(file_name))
95  return nullptr;
96 
97  std::string const base_name(file_name.substr(0, file_name.length() - 4));
98  SwmmInterface* swmm = new SwmmInterface(base_name);
99  if (swmm->readSwmmInputToLineMesh())
100  return std::unique_ptr<SwmmInterface>(swmm);
101 
102  ERR("Error creating mesh from SWMM file.");
103  delete swmm;
104  return nullptr;
105 }
SwmmInterface(std::string const &swmm_base_name)
Constructor.

References SwmmInterface(), ERR(), isSwmmInputFile(), and readSwmmInputToLineMesh().

Referenced by writeCsvOutput(), and writeMeshOutput().

◆ existsSwmmOutputFile()

bool FileIO::SwmmInterface::existsSwmmOutputFile ( ) const

Checks if a SWMM output file exists for the current input.

Definition at line 165 of file SWMMInterface.cpp.

166 {
167  std::string const outfile(_base_name + ".out");
168  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
169  return false;
170  return true;
171 }

References _base_name.

◆ getArrayAtTimeStep()

std::vector< double > FileIO::SwmmInterface::getArrayAtTimeStep ( SwmmObject  obj_type,
std::size_t  time_step,
std::size_t  var_idx 
) const

Returns an array for a given variable at all nodes/links from a SWMM output file for a given time step.

Definition at line 1031 of file SWMMInterface.cpp.

1034 {
1035  std::vector<double> data;
1036  std::string const outfile(_base_name + ".out");
1037  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1038  return data;
1039 
1040  if (time_step >= SWMM_Nperiods)
1041  {
1042  ERR("Time step {:d} not available, file contains only {:d} periods.",
1043  time_step, SWMM_Nperiods);
1044  return data;
1045  }
1046 
1047  bool is_var_idx_okay = true;
1048  int obj_type_id;
1049  std::size_t n_objects;
1050  switch (obj_type)
1051  {
1053  obj_type_id = 0;
1054  n_objects = SWMM_Nsubcatch;
1055  if (var_idx > (n_obj_params[obj_type_id] - 1 + SWMM_Npolluts))
1056  is_var_idx_okay = false;
1057  break;
1058  case SwmmObject::NODE:
1059  obj_type_id = 1;
1060  n_objects = SWMM_Nnodes;
1061  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1062  is_var_idx_okay = false;
1063  break;
1064  case SwmmObject::LINK:
1065  obj_type_id = 2;
1066  n_objects = SWMM_Nlinks;
1067  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1068  is_var_idx_okay = false;
1069  break;
1070  case SwmmObject::SYSTEM:
1071  obj_type_id = 3;
1072  n_objects = 1;
1073  if (var_idx > n_obj_params[obj_type_id])
1074  is_var_idx_okay = false;
1075  break;
1076  default:
1077  ERR("Object type not recognised.");
1078  CloseSwmmOutFile();
1079  return data;
1080  }
1081 
1082  if (!is_var_idx_okay)
1083  {
1084  ERR("Requested variable does not exist.");
1085  CloseSwmmOutFile();
1086  return data;
1087  }
1088 
1089  INFO("Fetching '{:s}'-data for time step {:d}...",
1090  getArrayName(obj_type, var_idx, SWMM_Npolluts), time_step);
1091 
1092  for (std::size_t i = 0; i < n_objects; ++i)
1093  {
1094  float val;
1095  GetSwmmResult(obj_type_id, i, var_idx, time_step, &val);
1096  data.push_back(static_cast<double>(val));
1097  }
1098 
1099  CloseSwmmOutFile();
1100  return data;
1101 }
std::string getArrayName(SwmmObject obj_type, std::size_t var_idx) const
Returns the name of the data array for the given object type and parameter index.
std::array< std::size_t, 4 > const n_obj_params

References _base_name, ERR(), getArrayName(), INFO(), FileIO::LINK, FileIO::n_obj_params, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by addObjectsToMesh(), and writeCsvForTimestep().

◆ getArrayForObject()

std::vector< double > FileIO::SwmmInterface::getArrayForObject ( SwmmObject  obj_type,
std::size_t  obj_idx,
std::size_t  var_idx 
) const

Returns an array for a given variable for one specific object from a SWMM output file for all time steps.

Definition at line 1103 of file SWMMInterface.cpp.

1106 {
1107  std::vector<double> data;
1108  std::string const outfile(_base_name + ".out");
1109  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1110  return data;
1111 
1112  bool is_var_idx_okay = true;
1113  bool is_obj_idx_okay = true;
1114  int obj_type_id;
1115  switch (obj_type)
1116  {
1118  obj_type_id = 0;
1119  if (obj_idx >= SWMM_Nsubcatch)
1120  is_obj_idx_okay = false;
1121  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1122  is_var_idx_okay = false;
1123  break;
1124  case SwmmObject::NODE:
1125  obj_type_id = 1;
1126  if (obj_idx >= SWMM_Nnodes)
1127  is_obj_idx_okay = false;
1128  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1129  is_var_idx_okay = false;
1130  break;
1131  case SwmmObject::LINK:
1132  obj_type_id = 2;
1133  if (obj_idx >= SWMM_Nlinks)
1134  is_obj_idx_okay = false;
1135  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1136  is_var_idx_okay = false;
1137  break;
1138  case SwmmObject::SYSTEM:
1139  obj_type_id = 3;
1140  if (obj_idx >= 1)
1141  is_obj_idx_okay = false;
1142  if (var_idx > n_obj_params[obj_type_id])
1143  is_var_idx_okay = false;
1144  break;
1145  default:
1146  ERR("Object type not recognised.");
1147  CloseSwmmOutFile();
1148  return data;
1149  }
1150 
1151  if (!is_obj_idx_okay)
1152  {
1153  ERR("Requested object index does not exist.");
1154  CloseSwmmOutFile();
1155  return data;
1156  }
1157 
1158  if (!is_var_idx_okay)
1159  {
1160  ERR("Requested variable does not exist.");
1161  CloseSwmmOutFile();
1162  return data;
1163  }
1164 
1165  std::size_t const n_time_steps(static_cast<std::size_t>(SWMM_Nperiods));
1166  for (std::size_t i = 0; i < n_time_steps; ++i)
1167  {
1168  float val;
1169  GetSwmmResult(obj_type_id, obj_idx, var_idx, i, &val);
1170  data.push_back(static_cast<double>(val));
1171  }
1172 
1173  CloseSwmmOutFile();
1174  return data;
1175 }

References _base_name, ERR(), FileIO::LINK, FileIO::n_obj_params, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by writeCsvForObject().

◆ getArrayName() [1/2]

std::string FileIO::SwmmInterface::getArrayName ( SwmmObject  obj_type,
std::size_t  var_idx 
) const

Returns the name of the data array for the given object type and parameter index.

Definition at line 1177 of file SWMMInterface.cpp.

1179 {
1180  std::string const outfile(_base_name + ".out");
1181  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1182  return std::string("");
1183 
1184  std::string const name = getArrayName(obj_type, var_idx, SWMM_Npolluts);
1185  CloseSwmmOutFile();
1186  return name;
1187 }

References _base_name, and MaterialPropertyLib::name.

Referenced by addObjectsToMesh(), getArrayAtTimeStep(), writeCsvForObject(), and writeCsvForTimestep().

◆ getArrayName() [2/2]

std::string FileIO::SwmmInterface::getArrayName ( SwmmObject  obj_type,
std::size_t  var_idx,
std::size_t  n_pollutants 
) const
private

Returns the name of an array (or an empty string if errors occurred)

Definition at line 1189 of file SWMMInterface.cpp.

1192 {
1193  if (obj_type == SwmmObject::SUBCATCHMENT)
1194  {
1195  if (var_idx < n_obj_params[0])
1196  return subcatchment_vars[var_idx];
1197  if (var_idx < n_obj_params[0] + n_pollutants)
1198  return _pollutant_names[var_idx - n_obj_params[0]];
1199  }
1200  if (obj_type == SwmmObject::NODE)
1201  {
1202  if (var_idx < n_obj_params[1])
1203  return node_vars[var_idx];
1204  if (var_idx < n_obj_params[1] + n_pollutants)
1205  return std::string("Node_" +
1206  _pollutant_names[var_idx - n_obj_params[1]]);
1207  }
1208  if (obj_type == SwmmObject::LINK)
1209  {
1210  if (var_idx < n_obj_params[2])
1211  return link_vars[var_idx];
1212  if (var_idx < n_obj_params[2] + n_pollutants)
1213  return std::string("Link_" +
1214  _pollutant_names[var_idx - n_obj_params[2]]);
1215  }
1216  if (obj_type == SwmmObject::SYSTEM && var_idx < n_obj_params[3])
1217  {
1218  return system_vars[var_idx];
1219  }
1220  ERR("SwmmInterface::getArrayName() - Index error, no name found.");
1221  return std::string("");
1222 }
std::vector< std::string > _pollutant_names
Vector storing the names of all pollutants.
const std::array< std::string, 15 > system_vars
All variables that exist for the system.
const std::array< std::string, 6 > link_vars
Variables that always exist for links. There might be more.
const std::array< std::string, 9 > subcatchment_vars
Variables that always exist for subcatchments. There might be more.
const std::array< std::string, 7 > node_vars
Variables that always exist for nodes. There might be more.

References _pollutant_names, ERR(), FileIO::LINK, FileIO::link_vars, FileIO::n_obj_params, FileIO::NODE, FileIO::node_vars, FileIO::SUBCATCHMENT, FileIO::subcatchment_vars, FileIO::SYSTEM, and FileIO::system_vars.

◆ getLinkPointIds()

bool FileIO::SwmmInterface::getLinkPointIds ( std::vector< std::size_t > &  inlets,
std::vector< std::size_t > &  outlets 
) const

Writes the inlet- and outlet IDs for links into vectors for writing of CSV files.

Definition at line 1309 of file SWMMInterface.cpp.

1311 {
1312  std::vector<MeshLib::Element*> const& elements(_mesh->getElements());
1313  for (MeshLib::Element const* const elem : elements)
1314  {
1315  if (elem->getGeomType() != MeshLib::MeshElemType::LINE)
1316  {
1317  ERR("Non line-element found in mesh.");
1318  return false;
1319  }
1320  inlets.push_back(getNodeIndex(*elem, 0));
1321  outlets.push_back(getNodeIndex(*elem, 1));
1322  }
1323  return true;
1324 }
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition: Element.cpp:225

References _mesh, ERR(), MeshLib::getNodeIndex(), and MeshLib::LINE.

◆ getMesh()

MeshLib::Mesh& FileIO::SwmmInterface::getMesh ( ) const
inline

Returns the mesh generated from SWMM file content.

Definition at line 72 of file SWMMInterface.h.

72 { return *_mesh; }

References _mesh.

◆ getName()

std::string FileIO::SwmmInterface::getName ( SwmmObject  obj_type,
std::size_t  idx 
) const

Returns the Name for the indexed object of the given type (or an empty string if an error occurred).

Definition at line 900 of file SWMMInterface.cpp.

901 {
902  switch (obj_type)
903  {
904  case SwmmObject::NODE:
905  if (idx < _id_nodename_map.size())
906  return _id_nodename_map[idx];
907  case SwmmObject::LINK:
908  if (idx < _id_linkname_map.size())
909  return _id_linkname_map[idx];
911  if (idx < _subcatchments.size())
912  return _subcatchments[idx].name;
913  case SwmmObject::SYSTEM:
914  if (idx == 0)
915  return std::string("System");
916  }
917  ERR("Index out of bounds.");
918  return std::string("");
919 }
std::vector< std::string > _id_nodename_map
Vector storing the names of all nodes/junctions.
std::vector< std::string > _id_linkname_map
Vector storing the names of all links/conduits.

References _id_linkname_map, _id_nodename_map, _subcatchments, ERR(), FileIO::LINK, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by writeObjectsOfSwmmTypeToCsv().

◆ getNames()

std::vector< std::string > FileIO::SwmmInterface::getNames ( SwmmObject  obj_type) const

Get all the object names for a given object type.

Definition at line 881 of file SWMMInterface.cpp.

882 {
883  switch (obj_type)
884  {
885  case SwmmObject::NODE:
886  return _id_nodename_map;
887  case SwmmObject::LINK:
888  return _id_linkname_map;
890  return getSubcatchmentNameMap();
891  case SwmmObject::SYSTEM:
892  std::vector<std::string> system_name{"System"};
893  return system_name;
894  }
895  ERR("Object type has no name map");
896  std::vector<std::string> empty_vec;
897  return empty_vec;
898 }
std::vector< std::string > getSubcatchmentNameMap() const
Creates a temporary string vector containing all subcatchment names in correct order.

References _id_linkname_map, _id_nodename_map, ERR(), getSubcatchmentNameMap(), FileIO::LINK, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by writeCsvForTimestep().

◆ getNodeCoordinateVectors()

bool FileIO::SwmmInterface::getNodeCoordinateVectors ( std::vector< double > &  x,
std::vector< double > &  y,
std::vector< double > &  z 
) const

Writes the node coordinates into double vectors for writing of CSV files.

Definition at line 1295 of file SWMMInterface.cpp.

1298 {
1299  std::vector<MeshLib::Node*> const& nodes(_mesh->getNodes());
1300  for (MeshLib::Node const* const node : nodes)
1301  {
1302  x.push_back((*node)[0]);
1303  y.push_back((*node)[1]);
1304  z.push_back((*node)[2]);
1305  }
1306  return true;
1307 }

References _mesh.

◆ getNumberOfObjects()

std::size_t FileIO::SwmmInterface::getNumberOfObjects ( SwmmObject  obj_type) const

Returns the number of objects of the given type.

Definition at line 921 of file SWMMInterface.cpp.

922 {
923  std::string const outfile(_base_name + ".out");
924  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
925  return 0;
926 
927  switch (obj_type)
928  {
930  return SWMM_Nsubcatch;
931  case SwmmObject::NODE:
932  return SWMM_Nnodes;
933  case SwmmObject::LINK:
934  return SWMM_Nlinks;
935  case SwmmObject::SYSTEM:
936  return 1;
937  default:
938  ERR("Object type not recognised.");
939  }
940  CloseSwmmOutFile();
941  return 0;
942 }

References _base_name, ERR(), FileIO::LINK, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by writeCsvForTimestep(), and writeObjectsOfSwmmTypeToCsv().

◆ getNumberOfParameters()

std::size_t FileIO::SwmmInterface::getNumberOfParameters ( SwmmObject  obj_type) const

Returns the number of parameters (incl. pollutants) of the given type.

Definition at line 944 of file SWMMInterface.cpp.

945 {
946  std::string const outfile(_base_name + ".out");
947  std::size_t n_time_steps(std::numeric_limits<std::size_t>::max());
948  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
949  return 0;
950 
951  std::size_t n_params(0);
952  switch (obj_type)
953  {
955  n_params = n_obj_params[0] + SWMM_Npolluts;
956  break;
957  case SwmmObject::NODE:
958  n_params = n_obj_params[1] + SWMM_Npolluts;
959  break;
960  case SwmmObject::LINK:
961  n_params = n_obj_params[2] + SWMM_Npolluts;
962  break;
963  case SwmmObject::SYSTEM:
964  n_params = n_obj_params[3];
965  break;
966  default:
967  ERR("Object type not recognised.");
968  }
969  CloseSwmmOutFile();
970  return n_params;
971 }

References _base_name, ERR(), FileIO::LINK, FileIO::n_obj_params, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by addObjectsToMesh(), writeCsvForObject(), and writeCsvForTimestep().

◆ getNumberOfTimeSteps()

std::size_t FileIO::SwmmInterface::getNumberOfTimeSteps ( ) const

Returns the number of time steps for the simulation results.

Definition at line 973 of file SWMMInterface.cpp.

974 {
975  std::string const outfile(_base_name + ".out");
976  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
977  return std::numeric_limits<std::size_t>::max();
978  std::size_t const n_time_steps(static_cast<std::size_t>(SWMM_Nperiods));
979  CloseSwmmOutFile();
980  return n_time_steps;
981 }

References _base_name.

Referenced by writeCsvForObject().

◆ getSubcatchmentNameMap()

std::vector< std::string > FileIO::SwmmInterface::getSubcatchmentNameMap ( ) const
private

Creates a temporary string vector containing all subcatchment names in correct order.

Definition at line 871 of file SWMMInterface.cpp.

872 {
873  std::vector<std::string> names;
874  names.reserve(_subcatchments.size());
875  std::transform(_subcatchments.begin(), _subcatchments.end(),
876  std::back_inserter(names),
877  [](auto const& sc) { return sc.name; });
878  return names;
879 }

References _subcatchments.

Referenced by getNames().

◆ isCommentLine()

bool FileIO::SwmmInterface::isCommentLine ( std::string const &  str)
staticprivate

Checks if the given line string is a comment line.

Definition at line 1290 of file SWMMInterface.cpp.

1291 {
1292  return (str.compare(str.find_first_not_of(' ', 0), 1, ";") == 0);
1293 }

Referenced by addPointElevation(), addRainGaugeTimeSeriesLocations(), isSwmmInputFile(), readCoordinates(), readLineElements(), readLinksAsPolylines(), readNodeData(), readPollutants(), readPolygons(), and readSubcatchments().

◆ isSectionFinished()

bool FileIO::SwmmInterface::isSectionFinished ( std::string const &  str)
staticprivate

Checks if the given line string is empty. Empty strings mark the end of sections in a SWMM input file.

Definition at line 1278 of file SWMMInterface.cpp.

1279 {
1280  if (str.empty())
1281  return true;
1282 
1283  std::size_t const pos_beg = str.find_first_not_of(' ', 0);
1284  if (pos_beg == str.find_first_of(" \n", pos_beg))
1285  return true;
1286 
1287  return false;
1288 }

Referenced by addPointElevation(), addRainGaugeTimeSeriesLocations(), readCoordinates(), readLineElements(), readLinksAsPolylines(), readNodeData(), readPollutants(), readPolygons(), and readSubcatchments().

◆ isSwmmInputFile()

bool FileIO::SwmmInterface::isSwmmInputFile ( std::string const &  inp_file_name)
static

Checks if file is a SWMM input file.

Definition at line 121 of file SWMMInterface.cpp.

122 {
123  if (!boost::iequals(BaseLib::getFileExtension(inp_file_name), ".inp"))
124  {
125  ERR("SWMMInterface: {:s} is not a SWMM input file.", inp_file_name);
126  return false;
127  }
128 
129  std::ifstream in(inp_file_name.c_str());
130  if (!in.is_open())
131  {
132  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
133  return false;
134  }
135 
136  std::string line;
137  bool header_found(false);
138  std::size_t pos_end(0);
139  while (!header_found)
140  {
141  if (!std::getline(in, line))
142  return false;
143 
144  std::size_t const pos_beg = line.find_first_not_of(' ', pos_end);
145  pos_end = line.find_first_of(" \n", pos_beg);
146 
147  // skip empty or comment lines at the beginning of the file
148  if (line.empty() || pos_beg == pos_end || isCommentLine(line))
149  continue;
150 
151  if (line == "[TITLE]")
152  header_found = true;
153  else
154  {
155  INFO("SWMMInterface: input file type {:s} not recognised.",
156  BaseLib::getFileExtension(inp_file_name));
157  return false;
158  }
159  }
160 
161  in.close();
162  return true;
163 }
std::string getFileExtension(const std::string &path)
Definition: FileTools.cpp:186

References ERR(), BaseLib::getFileExtension(), INFO(), and isCommentLine().

Referenced by convertSwmmInputToGeometry(), create(), and readSwmmInputToLineMesh().

◆ matchSubcatchmentsWithPolygons()

bool FileIO::SwmmInterface::matchSubcatchmentsWithPolygons ( std::vector< GeoLib::Polyline * > const &  lines,
std::vector< std::string > const &  names 
)
private

Matches existing subcatchment names with subsequently read polylines marking the outlines of said subcatchments.

Definition at line 838 of file SWMMInterface.cpp.

841 {
842  std::size_t const n_lines(lines.size());
843  std::size_t const n_subcatchments(_subcatchments.size());
844 
845  if (n_lines != n_subcatchments)
846  {
847  ERR("Number of subcatchments does not match number of outlines.");
848  return false;
849  }
850  for (std::size_t i = 0; i < n_lines; ++i)
851  {
852  bool found = false;
853  for (std::size_t j = 0; j < n_subcatchments; ++j)
854  {
855  if (names[i] == _subcatchments[j].name)
856  {
857  _subcatchments[j].outline = lines[i];
858  found = true;
859  break;
860  }
861  }
862  if (found == false)
863  {
864  ERR("No match in subcatcments for outline '{:s}'.", names[i]);
865  return false;
866  }
867  }
868  return true;
869 }

References _subcatchments, ERR(), and MaterialPropertyLib::name.

Referenced by readSwmmInputToLineMesh().

◆ readCoordinates()

template<typename T >
bool FileIO::SwmmInterface::readCoordinates ( std::ifstream &  in,
std::vector< T * > &  points,
std::vector< std::string > &  names 
)
staticprivate

Reading points from SWMM input file and converting them into OGS point-type vector. This method is shared by geometry- and mesh conversion.

Definition at line 174 of file SWMMInterface.cpp.

176 {
177  std::size_t id(points.size());
178  std::string line;
179 
180  while (std::getline(in, line))
181  {
182  if (isSectionFinished(line))
183  return true;
184 
185  if (isCommentLine(line))
186  continue;
187 
188  std::vector<std::string> split_str(BaseLib::splitString(line));
189  if (split_str.size() != 3)
190  {
191  ERR("Format not recognised.");
192  return false;
193  }
194  names.push_back(split_str[0]);
195 
196  double const x = BaseLib::str2number<double>(split_str[1]);
197  double const y = BaseLib::str2number<double>(split_str[2]);
198  T* pnt = new T(x, y, 0, id);
199  points.push_back(pnt);
200  id++;
201  }
202  return true;
203 }

References ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by readSwmmInputToLineMesh().

◆ readLineElements()

bool FileIO::SwmmInterface::readLineElements ( std::ifstream &  in,
std::vector< MeshLib::Element * > &  elements,
std::vector< MeshLib::Node * > const &  nodes,
std::map< std::string, std::size_t > const &  name_id_map 
)
private

Reads links/conduits and returns them as a vector of OGS line elements.

Definition at line 551 of file SWMMInterface.cpp.

555 {
556  std::string line;
557  while (std::getline(in, line))
558  {
559  if (isSectionFinished(line))
560  return true;
561 
562  if (isCommentLine(line))
563  continue;
564 
565  std::vector<std::string> const split_str(BaseLib::splitString(line));
566  // Conduits = 9, Pumps = 7, Weirs = 8
567  if (split_str.size() < 7)
568  {
569  ERR("Conduit format not recognised.");
570  return false;
571  }
572 
573  std::string const inlet(split_str[1]);
574  auto const i_it = name_id_map.find(inlet);
575  if (i_it == name_id_map.end())
576  {
577  ERR("SwmmInterface::readLineElements(): Inlet node {:s} not found "
578  "in coordinates map.",
579  inlet);
580  return false;
581  }
582 
583  std::string const outlet(split_str[2]);
584  auto const o_it = name_id_map.find(outlet);
585  if (o_it == name_id_map.end())
586  {
587  ERR("SwmmInterface::readLineElements(): Outlet node {:s} not found "
588  "in coordinates map.",
589  outlet);
590  return false;
591  }
592 
593  std::array<MeshLib::Node*, 2> const line_nodes = {nodes[i_it->second],
594  nodes[o_it->second]};
595  elements.push_back(new MeshLib::Line(line_nodes));
596  _id_linkname_map.push_back(split_str[0]);
597  }
598  return true;
599 }

References _id_linkname_map, ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by readSwmmInputToLineMesh().

◆ readLinksAsPolylines()

bool FileIO::SwmmInterface::readLinksAsPolylines ( std::ifstream &  in,
std::vector< GeoLib::Polyline * > &  lines,
std::vector< std::string > &  line_names,
std::vector< GeoLib::Point * > const &  points,
std::map< std::string, std::size_t > const &  point_names 
)
staticprivate

During geometry conversion, this reads links (conduits/pumps/weirs) and converts them into polylines.

Definition at line 299 of file SWMMInterface.cpp.

304 {
305  std::string line;
306  while (std::getline(in, line))
307  {
308  if (isSectionFinished(line))
309  return true;
310 
311  if (isCommentLine(line))
312  continue;
313 
314  std::vector<std::string> const split_str(BaseLib::splitString(line));
315  // Conduits = 9, Pumps = 7, Weirs = 8
316  if (split_str.size() < 7)
317  {
318  ERR("Conduit format not recognised.");
319  return false;
320  }
321 
322  std::string const inlet(split_str[1]);
323  auto const i_it = point_names.find(inlet);
324  if (i_it == point_names.end())
325  {
326  ERR("SwmmInterface::readLineElements(): Inlet node {:s} not found "
327  "in coordinates map.",
328  inlet);
329  return false;
330  }
331 
332  std::string const outlet(split_str[2]);
333  auto const o_it = point_names.find(outlet);
334  if (o_it == point_names.end())
335  {
336  ERR("SwmmInterface::readLineElements(): Outlet node {:s} not found "
337  "in coordinates map.",
338  outlet);
339  return false;
340  }
341  GeoLib::Polyline* ply = new GeoLib::Polyline(points);
342  std::size_t a(i_it->second);
343  ply->addPoint(i_it->second);
344  ply->addPoint(o_it->second);
345  lines.push_back(ply);
346  line_names.push_back(split_str[0]);
347  }
348  return true;
349 }
virtual bool addPoint(std::size_t pnt_id)
Definition: Polyline.cpp:35

References GeoLib::Polyline::addPoint(), ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by convertSwmmInputToGeometry().

◆ readNodeData()

bool FileIO::SwmmInterface::readNodeData ( std::ifstream &  in,
std::vector< MeshLib::Node * > &  nodes,
std::map< std::string, std::size_t > const &  name_id_map,
std::vector< double > &  max_depth,
bool  read_max_depth 
)
private

Reads input information associated with nodes (elevation, depth, etc.)

Definition at line 510 of file SWMMInterface.cpp.

514 {
515  std::string line;
516  while (std::getline(in, line))
517  {
518  if (isSectionFinished(line))
519  return true;
520 
521  if (isCommentLine(line))
522  continue;
523 
524  std::vector<std::string> const split_str(BaseLib::splitString(line));
525  // Junctions = 6, Outfalls = 4, Storage = 8
526  if (split_str.size() < 3)
527  {
528  ERR("Format not recognised.");
529  return false;
530  }
531  std::string const current_name(split_str[0]);
532  auto const it = name_id_map.find(current_name);
533  if (it == name_id_map.end())
534  {
535  ERR("SwmmInterface::readNodeData(): Name {:s} not found in "
536  "coordinates map.",
537  current_name);
538  return false;
539  }
540  std::size_t const id = it->second;
541  (*nodes[id])[2] = BaseLib::str2number<double>(split_str[1]);
542 
543  if (read_max_depth)
544  max_depth[id] = BaseLib::str2number<double>(split_str[2]);
545  else
546  max_depth[id] = 0;
547  }
548  return true;
549 }

References ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by readSwmmInputToLineMesh().

◆ readPollutants()

bool FileIO::SwmmInterface::readPollutants ( std::ifstream &  in)
private

Reads pollutant names and parameters.

Definition at line 1256 of file SWMMInterface.cpp.

1257 {
1258  std::string line;
1259  while (getline(in, line))
1260  {
1261  if (isSectionFinished(line))
1262  return true;
1263 
1264  if (isCommentLine(line))
1265  continue;
1266 
1267  std::vector<std::string> split_str(BaseLib::splitString(line));
1268  if (split_str.size() < 6)
1269  {
1270  ERR("Parameter format for pollutants not recognised.");
1271  return false;
1272  }
1273  _pollutant_names.push_back(split_str[0]);
1274  }
1275  return true;
1276 }

References _pollutant_names, ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by readSwmmInputToLineMesh().

◆ readPolygons()

bool FileIO::SwmmInterface::readPolygons ( std::ifstream &  in,
std::vector< GeoLib::Polyline * > &  lines,
std::vector< std::string > &  line_names,
std::vector< GeoLib::Point * > &  points,
std::vector< std::string > &  pnt_names 
)
staticprivate

During geometry conversion, this reads polygones representing subcatchments from the SWMM input file and converts them into OGS polyline vector.

Definition at line 205 of file SWMMInterface.cpp.

210 {
211  bool finished(false);
212  std::size_t id(points.size());
213  std::string line;
214  std::string polygon_name("");
215  GeoLib::Polyline* p(nullptr);
216  while (std::getline(in, line))
217  {
218  if (isSectionFinished(line))
219  break;
220 
221  if (isCommentLine(line))
222  continue;
223 
224  std::vector<std::string> split_str(BaseLib::splitString(line));
225  if (split_str.size() != 3)
226  {
227  ERR("Polygon format not recognised.");
228  delete p;
229  return false;
230  }
231 
232  // if a new polygon starts, add the old one to the vector
233  if (split_str[0] != polygon_name)
234  {
235  if (p != nullptr)
236  {
237  p->addPoint(p->getPointID(0));
238  lines.push_back(p);
239  }
240 
241  polygon_name = split_str[0];
242  p = new GeoLib::Polyline(points);
243  ply_names.push_back(polygon_name);
244  }
245 
246  double const x = BaseLib::str2number<double>(split_str[1]);
247  double const y = BaseLib::str2number<double>(split_str[2]);
248  points.push_back(new GeoLib::Point(x, y, 0, id));
249  p->addPoint(points.size() - 1);
250  pnt_names.push_back("");
251  id++;
252  }
253 
254  // when the section is finished, add the last polygon
255  if (p != nullptr)
256  {
257  p->addPoint(p->getPointID(0));
258  lines.push_back(p);
259  }
260 
261  return true;
262 }

References ERR(), isCommentLine(), isSectionFinished(), and BaseLib::splitString().

Referenced by convertSwmmInputToGeometry(), and readSwmmInputToLineMesh().

◆ readSubcatchments()

bool FileIO::SwmmInterface::readSubcatchments ( std::ifstream &  in,
std::map< std::string, std::size_t > const &  name_id_map 
)
private

Reads subcatchment information.

Definition at line 601 of file SWMMInterface.cpp.

603 {
604  std::string line;
605  while (getline(in, line))
606  {
607  if (isSectionFinished(line))
608  return true;
609 
610  if (isCommentLine(line))
611  continue;
612 
613  std::vector<std::string> const split_str(BaseLib::splitString(line));
614  if (split_str.size() < 8)
615  {
616  ERR("Subcatchment format not recognised.");
617  return false;
618  }
619 
620  Subcatchment sc;
621  sc.name = split_str[0];
622  sc.rain_gauge = std::numeric_limits<std::size_t>::max();
623  std::size_t const n_gauges(_rain_gauges.size());
624  for (std::size_t i = 0; i < n_gauges; ++i)
625  {
626  if (_rain_gauges[i].first.getName() == split_str[1])
627  {
628  sc.rain_gauge = i;
629  break;
630  }
631  }
632  if (sc.rain_gauge == std::numeric_limits<std::size_t>::max())
633  {
634  ERR("Rain gauge for subcatchment '{:s}' not found.", split_str[0]);
635  return false;
636  }
637 
638  auto const it = name_id_map.find(split_str[2]);
639  if (it == name_id_map.end())
640  {
641  ERR("Outlet node for subcatchment '{:s}' not found.", split_str[0]);
642  return false;
643  }
644  sc.outlet = it->second;
645  sc.area = BaseLib::str2number<double>(split_str[3]);
646  _subcatchments.push_back(sc);
647  }
648 
649  return true;
650 }

References _rain_gauges, _subcatchments, FileIO::SwmmInterface::Subcatchment::area, ERR(), isCommentLine(), isSectionFinished(), FileIO::SwmmInterface::Subcatchment::name, FileIO::SwmmInterface::Subcatchment::outlet, FileIO::SwmmInterface::Subcatchment::rain_gauge, and BaseLib::splitString().

Referenced by readSwmmInputToLineMesh().

◆ readSwmmInputToLineMesh()

bool FileIO::SwmmInterface::readSwmmInputToLineMesh ( )
private

Reading a SWMM input file and creating an OGS line mesh. This is automatically called when the object is created.

Definition at line 652 of file SWMMInterface.cpp.

653 {
654  if (_mesh != nullptr)
655  {
656  ERR("Mesh already exists.");
657  return false;
658  }
659 
660  std::string const inp_file_name(_base_name + ".inp");
661  if (!isSwmmInputFile(inp_file_name))
662  return false;
663 
664  std::ifstream in(inp_file_name.c_str());
665  if (!in.is_open())
666  {
667  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
668  return false;
669  }
670 
671  _id_nodename_map.clear();
672  std::vector<MeshLib::Node*> nodes;
673  std::string line;
674  while (getline(in, line))
675  {
676  if (line == "[COORDINATES]")
677  {
678  INFO("Reading coordinates...");
679  if (!readCoordinates<MeshLib::Node>(in, nodes, _id_nodename_map))
680  return false;
681  }
682  /* TODO: check if needed
683  else if (line == "[VERTICES]")
684  {
685  INFO ("Reading vertices...");
686  if (!readCoordinates(in, nodes, _id_nodename_map))
687  return false;
688  }
689  */
690  else if (line == "[SYMBOLS]")
691  {
692  INFO("Reading symbols...");
693  std::vector<GeoLib::Point*> points;
694  std::vector<std::string> names;
695  if (!readCoordinates(in, points, names))
696  return false;
697  for (std::size_t i = 0; i < points.size(); ++i)
698  {
699  GeoLib::Station stn(points[i], names[i]);
700  _rain_gauges.push_back(
701  std::pair<GeoLib::Station, std::string>(stn, ""));
702  }
703  }
704  }
705 
706  if (nodes.empty())
707  return false;
708 
709  // After end of file is reached, create name-id-map and
710  // start reading again to get line elements and node data.
711  std::map<std::string, std::size_t> name_id_map;
712  std::size_t const n_nodes(nodes.size());
713  for (std::size_t i = 0; i < n_nodes; ++i)
714  name_id_map[_id_nodename_map[i]] = i;
715  in.clear();
716  in.seekg(0, in.beg);
717 
718  std::vector<MeshLib::Element*> elements;
719  std::vector<double> max_depth(n_nodes);
720  std::size_t const n_types = 3;
721  std::array<std::size_t, n_types> n_elem_types{{0, 0, 0}};
722  while (getline(in, line))
723  {
724  if (line == "[RAINGAGES]")
725  {
726  if (!_rain_gauges.empty())
728  }
729  else if (line == "[SUBCATCHMENTS]")
730  {
731  INFO("Reading subcatchment information...");
732  if (!readSubcatchments(in, name_id_map))
733  return false;
734  }
735  else if (line == "[SUBAREAS]")
736  {
737  // more subcatchment variables, not yet implemented
738  }
739  else if (line == "[INFILTRATION]")
740  {
741  // more subcatchment variables, not yet implemented
742  }
743  else if (line == "[JUNCTIONS]")
744  {
745  INFO("Reading junctions...");
746  if (!readNodeData(in, nodes, name_id_map, max_depth, true))
747  return false;
748  }
749  else if (line == "[OUTFALLS]")
750  {
751  INFO("Reading outfalls...");
752  if (!readNodeData(in, nodes, name_id_map, max_depth, false))
753  return false;
754  }
755  else if (line == "[STORAGE]")
756  {
757  INFO("Reading storages...");
758  if (!readNodeData(in, nodes, name_id_map, max_depth, true))
759  return false;
760  }
761  else if (line == "[CONDUITS]")
762  {
763  INFO("Reading conduits...");
764  if (!readLineElements(in, elements, nodes, name_id_map))
765  return false;
766  n_elem_types[0] = elements.size();
767  }
768  else if (line == "[PUMPS]")
769  {
770  INFO("Reading pumps...");
771  if (!readLineElements(in, elements, nodes, name_id_map))
772  return false;
773  n_elem_types[1] = elements.size();
774  }
775  else if (line == "[WEIRS]")
776  {
777  INFO("Reading weirs...");
778  if (!readLineElements(in, elements, nodes, name_id_map))
779  return false;
780  n_elem_types[2] = elements.size();
781  }
782  else if (line == "[POLLUTANTS]")
783  {
784  if (!readPollutants(in))
785  return false;
786  }
787  else if (line == "[Polygons]")
788  {
789  INFO("Reading subcatchments...");
790  std::vector<GeoLib::Polyline*> lines;
791  std::vector<std::string> line_names;
792  std::vector<std::string>
793  tmp_names; // polygon points are nameless but the method
794  // requires a vector
795  if (!readPolygons(in, lines, line_names, _subcatchment_points,
796  tmp_names))
797  return false;
798 
799  if (!matchSubcatchmentsWithPolygons(lines, line_names))
800  return false;
801  }
802  }
803 
804  if (elements.empty())
805  {
806  for (MeshLib::Node* node : nodes)
807  delete node;
808  return false;
809  }
810 
811  MeshLib::Properties props;
812  auto* const mat_ids = props.createNewPropertyVector<int>(
813  "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
814  mat_ids->resize(elements.size(), 0);
815  for (std::size_t i = 1; i < n_types; ++i)
816  {
817  if (n_elem_types[i] > 0)
818  std::fill(mat_ids->begin() + n_elem_types[i - 1],
819  mat_ids->begin() + n_elem_types[i], i);
820  }
821 
822  if (nodes.size() == max_depth.size())
823  {
824  auto* const depth = props.createNewPropertyVector<double>(
825  "Max Depth", MeshLib::MeshItemType::Node, 1);
826  depth->reserve(max_depth.size());
827  std::copy(max_depth.cbegin(), max_depth.cend(),
828  std::back_inserter(*depth));
829  }
830  else
831  ERR("Size of max depth array does not fit number of elements. Skipping "
832  "array.");
833 
834  _mesh.reset(new MeshLib::Mesh(_base_name, nodes, elements, props));
835  return true;
836 }
bool readPollutants(std::ifstream &in)
Reads pollutant names and parameters.
bool readSubcatchments(std::ifstream &in, std::map< std::string, std::size_t > const &name_id_map)
Reads subcatchment information.
bool matchSubcatchmentsWithPolygons(std::vector< GeoLib::Polyline * > const &lines, std::vector< std::string > const &names)
Matches existing subcatchment names with subsequently read polylines marking the outlines of said sub...
bool addRainGaugeTimeSeriesLocations(std::ifstream &in)
Reads the location of external rain gauge time series files.
bool readLineElements(std::ifstream &in, std::vector< MeshLib::Element * > &elements, std::vector< MeshLib::Node * > const &nodes, std::map< std::string, std::size_t > const &name_id_map)
Reads links/conduits and returns them as a vector of OGS line elements.
static bool readCoordinates(std::ifstream &in, std::vector< T * > &points, std::vector< std::string > &names)
bool readNodeData(std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::map< std::string, std::size_t > const &name_id_map, std::vector< double > &max_depth, bool read_max_depth)
Reads input information associated with nodes (elevation, depth, etc.)
A Station (observation site) is basically a Point with some additional information.
Definition: Station.h:37
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
Definition: Properties.h:36
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)

References _base_name, _id_nodename_map, _mesh, _rain_gauges, _subcatchment_points, addRainGaugeTimeSeriesLocations(), MeshLib::Cell, MathLib::LinAlg::copy(), MeshLib::Properties::createNewPropertyVector(), ERR(), INFO(), isSwmmInputFile(), matchSubcatchmentsWithPolygons(), MeshLib::Node, readCoordinates(), readLineElements(), readNodeData(), readPollutants(), readPolygons(), and readSubcatchments().

Referenced by create().

◆ swmmObjectTypeToString()

std::string FileIO::SwmmInterface::swmmObjectTypeToString ( SwmmObject const  obj_type)
static

Returns a string with the name of the object type.

Definition at line 1326 of file SWMMInterface.cpp.

1327 {
1328  if (obj_type == SwmmObject::NODE)
1329  return "node";
1330  if (obj_type == SwmmObject::LINK)
1331  return "link";
1332  if (obj_type == SwmmObject::SUBCATCHMENT)
1333  return "subcatchment";
1334  if (obj_type == SwmmObject::SYSTEM)
1335  return "system";
1336  return "undefined";
1337 }

References FileIO::LINK, FileIO::NODE, FileIO::SUBCATCHMENT, and FileIO::SYSTEM.

Referenced by writeCsvForObject(), and writeObjectsOfSwmmTypeToCsv().

◆ writeCsvForObject()

bool FileIO::SwmmInterface::writeCsvForObject ( std::string const &  file_name,
SwmmObject  obj_type,
std::size_t  obj_idx 
) const

Write a CSV file for one object of the given type for all time steps.

Definition at line 1362 of file SWMMInterface.cpp.

1365 {
1367  INFO("Writing data for {:s} {:d}.", swmmObjectTypeToString(obj_type),
1368  obj_idx);
1370  std::size_t const n_params(getNumberOfParameters(obj_type));
1371  for (std::size_t i = 0; i < n_params; ++i)
1372  {
1373  std::vector<double> data = getArrayForObject(obj_type, obj_idx, i);
1374  if (!data.empty())
1375  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1376  }
1377  if (csv.getNArrays() < 2)
1378  {
1379  ERR("No data to write");
1380  return false;
1381  }
1383  return true;
1384 }
std::string writeToString()
Writes the object to a string.
Definition: Writer.cpp:31
bool addVectorForWriting(std::string const &vec_name, std::vector< T > const &vec)
Definition: CsvInterface.h:64
void addIndexVectorForWriting(std::size_t s)
Adds an index vector of size s to the CSV file.
std::size_t getNArrays() const
Returns the number of vectors currently staged for writing.
Definition: CsvInterface.h:47
std::size_t getNumberOfTimeSteps() const
Returns the number of time steps for the simulation results.
static std::string swmmObjectTypeToString(SwmmObject const obj_type)
Returns a string with the name of the object type.
std::size_t getNumberOfParameters(SwmmObject obj_type) const
Returns the number of parameters (incl. pollutants) of the given type.
std::vector< double > getArrayForObject(SwmmObject obj_type, std::size_t obj_idx, std::size_t var_idx) const
Returns an array for a given variable for one specific object from a SWMM output file for all time st...
int writeStringToFile(std::string content, std::filesystem::path const &file_path)
Definition: Writer.cpp:45

References FileIO::CsvInterface::addIndexVectorForWriting(), FileIO::CsvInterface::addVectorForWriting(), ERR(), getArrayForObject(), getArrayName(), FileIO::CsvInterface::getNArrays(), getNumberOfParameters(), getNumberOfTimeSteps(), INFO(), swmmObjectTypeToString(), BaseLib::IO::writeStringToFile(), and BaseLib::IO::Writer::writeToString().

Referenced by writeObjectsOfSwmmTypeToCsv().

◆ writeCsvForTimestep()

bool FileIO::SwmmInterface::writeCsvForTimestep ( std::string const &  file_name,
SwmmObject  obj_type,
std::size_t  time_step 
) const

Write a CSV file for all object of the given type at one time step.

Definition at line 1339 of file SWMMInterface.cpp.

1342 {
1345  csv.addVectorForWriting("Name", getNames(obj_type));
1346  std::size_t const n_params(getNumberOfParameters(obj_type));
1347  for (std::size_t i = 0; i < n_params; ++i)
1348  {
1349  std::vector<double> data = getArrayAtTimeStep(obj_type, time_step, i);
1350  if (!data.empty())
1351  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1352  }
1353  if (csv.getNArrays() < 2)
1354  {
1355  ERR("No data to write");
1356  return false;
1357  }
1359  return true;
1360 }
std::size_t getNumberOfObjects(SwmmObject obj_type) const
Returns the number of objects of the given type.
std::vector< double > getArrayAtTimeStep(SwmmObject obj_type, std::size_t time_step, std::size_t var_idx) const
Returns an array for a given variable at all nodes/links from a SWMM output file for a given time ste...
std::vector< std::string > getNames(SwmmObject obj_type) const
Get all the object names for a given object type.

References FileIO::CsvInterface::addIndexVectorForWriting(), FileIO::CsvInterface::addVectorForWriting(), ERR(), getArrayAtTimeStep(), getArrayName(), getNames(), FileIO::CsvInterface::getNArrays(), getNumberOfObjects(), getNumberOfParameters(), BaseLib::IO::writeStringToFile(), and BaseLib::IO::Writer::writeToString().

Member Data Documentation

◆ _base_name

std::string const FileIO::SwmmInterface::_base_name
private

All files for a given SWMM simulation have the same base name.

Definition at line 200 of file SWMMInterface.h.

Referenced by existsSwmmOutputFile(), getArrayAtTimeStep(), getArrayForObject(), getArrayName(), getNumberOfObjects(), getNumberOfParameters(), getNumberOfTimeSteps(), and readSwmmInputToLineMesh().

◆ _id_linkname_map

std::vector<std::string> FileIO::SwmmInterface::_id_linkname_map
private

Vector storing the names of all links/conduits.

Definition at line 204 of file SWMMInterface.h.

Referenced by getName(), getNames(), and readLineElements().

◆ _id_nodename_map

std::vector<std::string> FileIO::SwmmInterface::_id_nodename_map
private

Vector storing the names of all nodes/junctions.

Definition at line 202 of file SWMMInterface.h.

Referenced by getName(), getNames(), and readSwmmInputToLineMesh().

◆ _mesh

std::unique_ptr<MeshLib::Mesh> FileIO::SwmmInterface::_mesh
private

Mesh generated from SWMM input (+ optional output data)

Definition at line 214 of file SWMMInterface.h.

Referenced by getLinkPointIds(), getMesh(), getNodeCoordinateVectors(), and readSwmmInputToLineMesh().

◆ _pollutant_names

std::vector<std::string> FileIO::SwmmInterface::_pollutant_names
private

Vector storing the names of all pollutants.

Definition at line 206 of file SWMMInterface.h.

Referenced by getArrayName(), and readPollutants().

◆ _rain_gauges

std::vector< std::pair<GeoLib::Station, std::string> > FileIO::SwmmInterface::_rain_gauges
private

Vector containing rain gauge information as well the position of external time series files.

Definition at line 212 of file SWMMInterface.h.

Referenced by addRainGaugeTimeSeriesLocations(), readSubcatchments(), and readSwmmInputToLineMesh().

◆ _subcatchment_points

std::vector<GeoLib::Point*> FileIO::SwmmInterface::_subcatchment_points
private

Separate node vector containing points for defining subcatchment outlines.

Definition at line 210 of file SWMMInterface.h.

Referenced by ~SwmmInterface(), and readSwmmInputToLineMesh().

◆ _subcatchments

std::vector<Subcatchment> FileIO::SwmmInterface::_subcatchments
private

Vector storing information about all subcatchments.

Definition at line 208 of file SWMMInterface.h.

Referenced by ~SwmmInterface(), getName(), getSubcatchmentNameMap(), matchSubcatchmentsWithPolygons(), and readSubcatchments().


The documentation for this class was generated from the following files: