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 1225 of file SWMMInterface.cpp.

1226 {
1227  std::string line;
1228  while (getline(in, line))
1229  {
1230  if (isSectionFinished(line))
1231  break;
1232 
1233  if (isCommentLine(line))
1234  continue;
1235 
1236  std::vector<std::string> const split_str(BaseLib::splitString(line));
1237  if (split_str.size() < 6)
1238  {
1239  ERR("Rain gauge parameter format not recognised.");
1240  return false;
1241  }
1242 
1243  for (auto& stn : _rain_gauges)
1244  {
1245  if (stn.first.getName() == split_str[0] && split_str[4] == "FILE")
1246  stn.second = split_str[5].substr(1, split_str[5].size() - 2);
1247  }
1248  }
1249 
1250  for (auto const& stn : _rain_gauges)
1251  if (stn.second.empty())
1252  WARN("No associated time series found for rain gauge '{:s}'.",
1253  stn.first.getName());
1254  return true;
1255 }
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 984 of file SWMMInterface.cpp.

988 {
989  if (!(swmm_type == SwmmObject::NODE || swmm_type == SwmmObject::LINK))
990  {
991  ERR("Information of this object type cannot be added to mesh.");
992  return false;
993  }
994 
995  if (data.empty())
996  {
997  ERR("Data array is empty and cannot be added to mesh.");
998  return false;
999  }
1000 
1001  if (swmm_type == SwmmObject::NODE && data.size() != mesh.getNumberOfNodes())
1002  {
1003  ERR("Number of mesh nodes ({:d}) does not match length of array "
1004  "({:d}).",
1005  mesh.getNumberOfNodes(), data.size());
1006  return false;
1007  }
1008 
1009  if (swmm_type == SwmmObject::LINK &&
1010  data.size() != mesh.getNumberOfElements())
1011  {
1012  ERR("Number of mesh elements ({:d}) does not match length of array "
1013  "({:d}).",
1014  mesh.getNumberOfElements(), data.size());
1015  return false;
1016  }
1017 
1018  MeshLib::MeshItemType const item_type = (swmm_type == SwmmObject::NODE)
1022  MeshLib::getOrCreateMeshProperty<double>(mesh, vec_name, item_type, 1);
1023  if (!prop)
1024  {
1025  ERR("Error fetching array '{:s}'.", vec_name);
1026  return false;
1027  }
1028  std::copy(data.cbegin(), data.cend(), prop->begin());
1029  return true;
1030 }
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  auto points = std::make_unique<std::vector<GeoLib::Point*>>();
366  auto lines = std::make_unique<std::vector<GeoLib::Polyline*>>();
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  auto name_id_map = std::make_unique<std::map<std::string, std::size_t>>();
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  auto line_id_map =
476  std::make_unique<std::map<std::string, std::size_t>>();
477  {
478  std::size_t const n_names(line_names.size());
479  for (std::size_t i = 0; i < n_names; ++i)
480  {
481  line_id_map->insert(std::make_pair(line_names[i], i));
482  }
483  }
484  std::vector<std::size_t> const& pnt_id_map(
485  geo_objects.getPointVecObj(geo_name)->getIDMap());
486  for (GeoLib::Polyline* polyline : *lines)
487  {
488  for (std::size_t i = 0; i < polyline->getNumberOfPoints(); ++i)
489  {
490  polyline->setPointID(i, pnt_id_map[polyline->getPointID(i)]);
491  if (i > 0 &&
492  polyline->getPointID(i - 1) == polyline->getPointID(i))
493  {
494  polyline->removePoint(i);
495  i--;
496  }
497  }
498  if (polyline->getPointID(0) ==
499  polyline->getPointID(polyline->getNumberOfPoints() - 1))
500  {
501  polyline->removePoint(polyline->getNumberOfPoints() - 1);
502  polyline->addPoint(polyline->getPointID(0));
503  }
504  }
505  geo_objects.addPolylineVec(std::move(lines), geo_name,
506  std::move(line_id_map));
507  }
508  return true;
509 }
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.
const PointVec * getPointVecObj(const std::string &name) const
Definition: GEOObjects.cpp:84
bool removePointVec(const std::string &name)
Definition: GEOObjects.cpp:97
void addPointVec(std::unique_ptr< std::vector< Point * >> points, std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> pnt_id_name_map=nullptr, double eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Definition: GEOObjects.cpp:51
void addPolylineVec(std::unique_ptr< std::vector< Polyline * >> lines, const std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> ply_names=nullptr)
Definition: GEOObjects.cpp:150
const std::vector< std::size_t > & getIDMap() const
Definition: PointVec.h:97
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition: Polyline.h:51
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
void cleanupVectorElements(std::vector< T1 * > const &items, std::vector< T2 * > const &dependent_items)
Definition: Algorithm.h:300

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 1032 of file SWMMInterface.cpp.

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

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

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 1178 of file SWMMInterface.cpp.

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

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 1190 of file SWMMInterface.cpp.

1193 {
1194  if (obj_type == SwmmObject::SUBCATCHMENT)
1195  {
1196  if (var_idx < n_obj_params[0])
1197  return subcatchment_vars[var_idx];
1198  if (var_idx < n_obj_params[0] + n_pollutants)
1199  return _pollutant_names[var_idx - n_obj_params[0]];
1200  }
1201  if (obj_type == SwmmObject::NODE)
1202  {
1203  if (var_idx < n_obj_params[1])
1204  return node_vars[var_idx];
1205  if (var_idx < n_obj_params[1] + n_pollutants)
1206  return std::string("Node_" +
1207  _pollutant_names[var_idx - n_obj_params[1]]);
1208  }
1209  if (obj_type == SwmmObject::LINK)
1210  {
1211  if (var_idx < n_obj_params[2])
1212  return link_vars[var_idx];
1213  if (var_idx < n_obj_params[2] + n_pollutants)
1214  return std::string("Link_" +
1215  _pollutant_names[var_idx - n_obj_params[2]]);
1216  }
1217  if (obj_type == SwmmObject::SYSTEM && var_idx < n_obj_params[3])
1218  {
1219  return system_vars[var_idx];
1220  }
1221  ERR("SwmmInterface::getArrayName() - Index error, no name found.");
1222  return std::string("");
1223 }
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 1310 of file SWMMInterface.cpp.

1312 {
1313  std::vector<MeshLib::Element*> const& elements(_mesh->getElements());
1314  for (MeshLib::Element const* const elem : elements)
1315  {
1316  if (elem->getGeomType() != MeshLib::MeshElemType::LINE)
1317  {
1318  ERR("Non line-element found in mesh.");
1319  return false;
1320  }
1321  inlets.push_back(getNodeIndex(*elem, 0));
1322  outlets.push_back(getNodeIndex(*elem, 1));
1323  }
1324  return true;
1325 }
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 901 of file SWMMInterface.cpp.

902 {
903  switch (obj_type)
904  {
905  case SwmmObject::NODE:
906  if (idx < _id_nodename_map.size())
907  return _id_nodename_map[idx];
908  case SwmmObject::LINK:
909  if (idx < _id_linkname_map.size())
910  return _id_linkname_map[idx];
912  if (idx < _subcatchments.size())
913  return _subcatchments[idx].name;
914  case SwmmObject::SYSTEM:
915  if (idx == 0)
916  return std::string("System");
917  }
918  ERR("Index out of bounds.");
919  return std::string("");
920 }
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 882 of file SWMMInterface.cpp.

883 {
884  switch (obj_type)
885  {
886  case SwmmObject::NODE:
887  return _id_nodename_map;
888  case SwmmObject::LINK:
889  return _id_linkname_map;
891  return getSubcatchmentNameMap();
892  case SwmmObject::SYSTEM:
893  std::vector<std::string> system_name{"System"};
894  return system_name;
895  }
896  ERR("Object type has no name map");
897  std::vector<std::string> empty_vec;
898  return empty_vec;
899 }
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 1296 of file SWMMInterface.cpp.

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

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 922 of file SWMMInterface.cpp.

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

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 945 of file SWMMInterface.cpp.

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

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 974 of file SWMMInterface.cpp.

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

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 872 of file SWMMInterface.cpp.

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

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 1291 of file SWMMInterface.cpp.

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

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 1279 of file SWMMInterface.cpp.

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

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 839 of file SWMMInterface.cpp.

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

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 552 of file SWMMInterface.cpp.

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

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:34

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 511 of file SWMMInterface.cpp.

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

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 1257 of file SWMMInterface.cpp.

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

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 602 of file SWMMInterface.cpp.

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

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 653 of file SWMMInterface.cpp.

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

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

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 1363 of file SWMMInterface.cpp.

1366 {
1368  INFO("Writing data for {:s} {:d}.", swmmObjectTypeToString(obj_type),
1369  obj_idx);
1371  std::size_t const n_params(getNumberOfParameters(obj_type));
1372  for (std::size_t i = 0; i < n_params; ++i)
1373  {
1374  std::vector<double> data = getArrayForObject(obj_type, obj_idx, i);
1375  if (!data.empty())
1376  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1377  }
1378  if (csv.getNArrays() < 2)
1379  {
1380  ERR("No data to write");
1381  return false;
1382  }
1384  return true;
1385 }
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 1340 of file SWMMInterface.cpp.

1343 {
1346  csv.addVectorForWriting("Name", getNames(obj_type));
1347  std::size_t const n_params(getNumberOfParameters(obj_type));
1348  for (std::size_t i = 0; i < n_params; ++i)
1349  {
1350  std::vector<double> data = getArrayAtTimeStep(obj_type, time_step, i);
1351  if (!data.empty())
1352  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1353  }
1354  if (csv.getNArrays() < 2)
1355  {
1356  ERR("No data to write");
1357  return false;
1358  }
1360  return true;
1361 }
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: