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 60 of file SWMMInterface.h.

#include <SWMMInterface.h>

Classes

struct  Subcatchment
 

Public Member Functions

MeshLib::MeshgetMesh () const
 Returns the mesh generated from SWMM file content.
 
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::vector< std::string > getNames (SwmmObject obj_type) const
 Get all the object names for a given object type.
 
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).
 
std::size_t getNumberOfObjects (SwmmObject obj_type) const
 Returns the number of objects of the given type.
 
std::size_t getNumberOfParameters (SwmmObject obj_type) const
 Returns the number of parameters (incl. pollutants) of the given type.
 
std::size_t getNumberOfTimeSteps () const
 Returns the number of time steps for the simulation results.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
bool existsSwmmOutputFile () const
 Checks if a SWMM output file exists for the current input.
 
 ~SwmmInterface ()
 Destructor.
 

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.
 
static std::string swmmObjectTypeToString (SwmmObject const obj_type)
 Returns a string with the name of the object type.
 
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.
 

Private Member Functions

 SwmmInterface (std::string const &swmm_base_name)
 Constructor.
 
bool readSwmmInputToLineMesh ()
 Reading a SWMM input file and creating an OGS line mesh. This is automatically called when the object is created.
 
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.)
 
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.
 
bool readSubcatchments (std::ifstream &in, std::map< std::string, std::size_t > const &name_id_map)
 Reads subcatchment information.
 
bool readPollutants (std::ifstream &in)
 Reads pollutant names and parameters.
 
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)
 
bool addRainGaugeTimeSeriesLocations (std::ifstream &in)
 Reads the location of external rain gauge time series files.
 
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.
 
std::vector< std::string > getSubcatchmentNameMap () const
 Creates a temporary string vector containing all subcatchment names in correct order.
 

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.
 
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 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.
 
static bool isCommentLine (std::string const &str)
 Checks if the given line string is a comment line.
 

Private Attributes

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

Constructor & Destructor Documentation

◆ ~SwmmInterface()

FileIO::SwmmInterface::~SwmmInterface ( )

Destructor.

Definition at line 114 of file SWMMInterface.cpp.

115{
116 for (Subcatchment& sc : _subcatchments)
117 delete sc.outline;
118
120 delete pnt;
121}
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 109 of file SWMMInterface.cpp.

110 : _base_name(swmm_base_name), _mesh(nullptr)
111{
112}
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 266 of file SWMMInterface.cpp.

269{
270 std::string line;
271 while (std::getline(in, line))
272 {
273 if (isSectionFinished(line))
274 return true;
275
276 if (isCommentLine(line))
277 continue;
278
279 std::vector<std::string> const split_str(BaseLib::splitString(line));
280 // Junctions = 6, Outfalls = 4, Storage = 8
281 if (split_str.size() < 4)
282 {
283 ERR("Format not recognised.");
284 return false;
285 }
286 std::string const current_name(split_str[0]);
287 auto const it = name_id_map.find(current_name);
288 if (it == name_id_map.end())
289 {
290 ERR("SwmmInterface::addPointElevation(): Name {:s} not found in "
291 "coordinates map.",
292 current_name);
293 return false;
294 }
295 std::size_t const id = it->second;
296 (*points[id])[2] = BaseLib::str2number<double>(split_str[1]);
297 }
298 return true;
299}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
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)

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

1232{
1233 std::string line;
1234 while (std::getline(in, line))
1235 {
1236 if (isSectionFinished(line))
1237 break;
1238
1239 if (isCommentLine(line))
1240 continue;
1241
1242 std::vector<std::string> const split_str(BaseLib::splitString(line));
1243 if (split_str.size() < 6)
1244 {
1245 ERR("Rain gauge parameter format not recognised.");
1246 return false;
1247 }
1248
1249 for (auto& stn : _rain_gauges)
1250 {
1251 if (stn.first.getName() == split_str[0] && split_str[4] == "FILE")
1252 stn.second = split_str[5].substr(1, split_str[5].size() - 2);
1253 }
1254 }
1255
1256 for (auto const& stn : _rain_gauges)
1257 if (stn.second.empty())
1258 WARN("No associated time series found for rain gauge '{:s}'.",
1259 stn.first.getName());
1260 return true;
1261}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
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).
std::vector< std::pair< GeoLib::Station, std::string > > _rain_gauges
Vector containing rain gauge information as well the position of external time series files.
constexpr int size(int const displacement_dim)
Vectorized tensor size for given displacement dimension.

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

994{
995 if (!(swmm_type == SwmmObject::NODE || swmm_type == SwmmObject::LINK))
996 {
997 ERR("Information of this object type cannot be added to mesh.");
998 return false;
999 }
1000
1001 if (data.empty())
1002 {
1003 ERR("Data array is empty and cannot be added to mesh.");
1004 return false;
1005 }
1006
1007 if (swmm_type == SwmmObject::NODE && data.size() != mesh.getNumberOfNodes())
1008 {
1009 ERR("Number of mesh nodes ({:d}) does not match length of array "
1010 "({:d}).",
1011 mesh.getNumberOfNodes(), data.size());
1012 return false;
1013 }
1014
1015 if (swmm_type == SwmmObject::LINK &&
1016 data.size() != mesh.getNumberOfElements())
1017 {
1018 ERR("Number of mesh elements ({:d}) does not match length of array "
1019 "({:d}).",
1020 mesh.getNumberOfElements(), data.size());
1021 return false;
1022 }
1023
1024 MeshLib::MeshItemType const item_type = (swmm_type == SwmmObject::NODE)
1028 MeshLib::getOrCreateMeshProperty<double>(mesh, vec_name, item_type, 1);
1029 if (!prop)
1030 {
1031 ERR("Error fetching array '{:s}'.", vec_name);
1032 return false;
1033 }
1034 std::copy(data.cbegin(), data.cend(), prop->begin());
1035 return true;
1036}
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition Mesh.h:100
std::size_t getNumberOfElements() const
Get the number of elements.
Definition Mesh.h:97
MeshItemType
Definition Location.h:21

References MeshLib::Cell, 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 353 of file SWMMInterface.cpp.

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

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

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

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

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

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

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

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

1186{
1187 std::string const outfile(_base_name + ".out");
1188 if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1189 return std::string("");
1190
1191 std::string const name = getArrayName(obj_type, var_idx, SWMM_Npolluts);
1192 CloseSwmmOutFile();
1193 return name;
1194}

References _base_name, and getArrayName().

Referenced by addObjectsToMesh(), getArrayAtTimeStep(), getArrayName(), 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 1196 of file SWMMInterface.cpp.

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

1318{
1319 std::vector<MeshLib::Element*> const& elements(_mesh->getElements());
1320 for (MeshLib::Element const* const elem : elements)
1321 {
1322 if (elem->getGeomType() != MeshLib::MeshElemType::LINE)
1323 {
1324 ERR("Non line-element found in mesh.");
1325 return false;
1326 }
1327 inlets.push_back(getNodeIndex(*elem, 0));
1328 outlets.push_back(getNodeIndex(*elem, 1));
1329 }
1330 return true;
1331}
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition Element.cpp:219

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

◆ getMesh()

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

Returns the mesh generated from SWMM file content.

Definition at line 73 of file SWMMInterface.h.

73{ 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 907 of file SWMMInterface.cpp.

908{
909 switch (obj_type)
910 {
911 case SwmmObject::NODE:
912 if (idx < _id_nodename_map.size())
913 return _id_nodename_map[idx];
914 case SwmmObject::LINK:
915 if (idx < _id_linkname_map.size())
916 return _id_linkname_map[idx];
918 if (idx < _subcatchments.size())
919 return _subcatchments[idx].name;
921 if (idx == 0)
922 return std::string("System");
923 }
924 ERR("Index out of bounds.");
925 return std::string("");
926}
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 888 of file SWMMInterface.cpp.

889{
890 switch (obj_type)
891 {
892 case SwmmObject::NODE:
893 return _id_nodename_map;
894 case SwmmObject::LINK:
895 return _id_linkname_map;
897 return getSubcatchmentNameMap();
899 std::vector<std::string> system_name{"System"};
900 return system_name;
901 }
902 ERR("Object type has no name map");
903 std::vector<std::string> empty_vec;
904 return empty_vec;
905}
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 1302 of file SWMMInterface.cpp.

1305{
1306 std::vector<MeshLib::Node*> const& nodes(_mesh->getNodes());
1307 for (MeshLib::Node const* const node : nodes)
1308 {
1309 x.push_back((*node)[0]);
1310 y.push_back((*node)[1]);
1311 z.push_back((*node)[2]);
1312 }
1313 return true;
1314}

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

929{
930 std::string const outfile(_base_name + ".out");
931 if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
932 return 0;
933
934 switch (obj_type)
935 {
937 return SWMM_Nsubcatch;
938 case SwmmObject::NODE:
939 return SWMM_Nnodes;
940 case SwmmObject::LINK:
941 return SWMM_Nlinks;
943 return 1;
944 default:
945 ERR("Object type not recognised.");
946 }
947 CloseSwmmOutFile();
948 return 0;
949}

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

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

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

981{
982 std::string const outfile(_base_name + ".out");
983 if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
984 return std::numeric_limits<std::size_t>::max();
985 std::size_t const n_time_steps(static_cast<std::size_t>(SWMM_Nperiods));
986 CloseSwmmOutFile();
987 return n_time_steps;
988}

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

879{
880 std::vector<std::string> names;
881 names.reserve(_subcatchments.size());
882 std::transform(_subcatchments.begin(), _subcatchments.end(),
883 std::back_inserter(names),
884 [](auto const& sc) { return sc.name; });
885 return names;
886}
constexpr ranges::views::view_closure names
For an element of a range view return its name.
Definition Mesh.h:229

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

1298{
1299 return (str.compare(str.find_first_not_of(' ', 0), 1, ";") == 0);
1300}

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

1286{
1287 if (str.empty())
1288 return true;
1289
1290 std::size_t const pos_beg = str.find_first_not_of(' ', 0);
1291 if (pos_beg == str.find_first_of(" \n", pos_beg))
1292 return true;
1293
1294 return false;
1295}

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

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

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

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

References _subcatchments, and ERR().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1334{
1335 if (obj_type == SwmmObject::NODE)
1336 return "node";
1337 if (obj_type == SwmmObject::LINK)
1338 return "link";
1339 if (obj_type == SwmmObject::SUBCATCHMENT)
1340 return "subcatchment";
1341 if (obj_type == SwmmObject::SYSTEM)
1342 return "system";
1343 return "undefined";
1344}

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

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

1349{
1352 csv.addVectorForWriting("Name", getNames(obj_type));
1353 std::size_t const n_params(getNumberOfParameters(obj_type));
1354 for (std::size_t i = 0; i < n_params; ++i)
1355 {
1356 std::vector<double> data = getArrayAtTimeStep(obj_type, time_step, i);
1357 if (!data.empty())
1358 csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1359 }
1360 if (csv.getNArrays() < 2)
1361 {
1362 ERR("No data to write");
1363 return false;
1364 }
1366 return true;
1367}
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 201 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 205 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 203 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 215 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 207 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 213 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 211 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 209 of file SWMMInterface.h.

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


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