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

109{
110 for (Subcatchment& sc : _subcatchments)
111 delete sc.outline;
112
113 for (GeoLib::Point* pnt : _subcatchment_points)
114 delete pnt;
115}
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 103 of file SWMMInterface.cpp.

104 : _base_name(swmm_base_name), _mesh(nullptr)
105{
106}
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.

References _base_name, and _mesh.

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

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

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

Referenced by convertSwmmInputToGeometry().

◆ addRainGaugeTimeSeriesLocations()

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

Reads the location of external rain gauge time series files.

Definition at line 1224 of file SWMMInterface.cpp.

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

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

References MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), MeshLib::Cell, ERR(), MeshLib::Mesh::getNumberOfElements(), MeshLib::Mesh::getNumberOfNodes(), MeshLib::getOrCreateMeshProperty(), 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 347 of file SWMMInterface.cpp.

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

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

162{
163 std::string const outfile(_base_name + ".out");
164 if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
165 return false;
166 return true;
167}

References _base_name.

◆ getArrayAtTimeStep()

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

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

Definition at line 1031 of file SWMMInterface.cpp.

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

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

Referenced by addObjectsToMesh(), and writeCsvForTimestep().

◆ getArrayForObject()

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

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

Definition at line 1103 of file SWMMInterface.cpp.

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

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

Referenced by writeCsvForObject().

◆ getArrayName() [1/2]

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

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

Definition at line 1177 of file SWMMInterface.cpp.

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

References _base_name, and 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 1189 of file SWMMInterface.cpp.

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

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

◆ getLinkPointIds()

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

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

Definition at line 1309 of file SWMMInterface.cpp.

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

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

68{ return *_mesh; }

References _mesh.

◆ getName()

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

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

Definition at line 900 of file SWMMInterface.cpp.

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

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

Referenced by writeObjectsOfSwmmTypeToCsv().

◆ getNames()

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

Get all the object names for a given object type.

Definition at line 881 of file SWMMInterface.cpp.

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

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

Referenced by writeCsvForTimestep().

◆ getNodeCoordinateVectors()

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

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

Definition at line 1295 of file SWMMInterface.cpp.

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

References _mesh.

◆ getNumberOfObjects()

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

Returns the number of objects of the given type.

Definition at line 921 of file SWMMInterface.cpp.

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

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

Referenced by writeCsvForTimestep(), and writeObjectsOfSwmmTypeToCsv().

◆ getNumberOfParameters()

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

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

Definition at line 944 of file SWMMInterface.cpp.

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

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

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

◆ getNumberOfTimeSteps()

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

Returns the number of time steps for the simulation results.

Definition at line 973 of file SWMMInterface.cpp.

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

References _base_name.

Referenced by writeCsvForObject().

◆ getSubcatchmentNameMap()

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

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

Definition at line 871 of file SWMMInterface.cpp.

872{
873 std::vector<std::string> names;
874 names.reserve(_subcatchments.size());
875 std::transform(_subcatchments.begin(), _subcatchments.end(),
876 std::back_inserter(names),
877 [](auto const& sc) { return sc.name; });
878 return names;
879}
constexpr ranges::views::view_closure names
For an element of a range view return its name.
Definition Mesh.h:220

References _subcatchments.

Referenced by getNames().

◆ isCommentLine()

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

Checks if the given line string is a comment line.

Definition at line 1290 of file SWMMInterface.cpp.

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

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

◆ isSectionFinished()

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

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

Definition at line 1278 of file SWMMInterface.cpp.

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

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

◆ isSwmmInputFile()

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

Checks if file is a SWMM input file.

Definition at line 117 of file SWMMInterface.cpp.

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

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

References _subcatchments, 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 170 of file SWMMInterface.cpp.

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

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

Referenced by convertSwmmInputToGeometry(), and 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 550 of file SWMMInterface.cpp.

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

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

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

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

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

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

Referenced by readSwmmInputToLineMesh().

◆ readPollutants()

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

Reads pollutant names and parameters.

Definition at line 1256 of file SWMMInterface.cpp.

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

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

Referenced by readSwmmInputToLineMesh().

◆ readPolygons()

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

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

Definition at line 201 of file SWMMInterface.cpp.

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

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

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

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

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

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

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

References _base_name, _id_nodename_map, _mesh, _rain_gauges, _subcatchment_points, addRainGaugeTimeSeriesLocations(), MeshLib::PropertyVector< PROP_VAL_TYPE >::assign(), MeshLib::Cell, MeshLib::Properties::createNewPropertyVector(), ERR(), INFO(), isSwmmInputFile(), matchSubcatchmentsWithPolygons(), MeshLib::Node, readCoordinates(), readLineElements(), readNodeData(), readPollutants(), readPolygons(), readSubcatchments(), and MeshLib::PropertyVector< PROP_VAL_TYPE >::resize().

Referenced by create().

◆ swmmObjectTypeToString()

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

Returns a string with the name of the object type.

Definition at line 1326 of file SWMMInterface.cpp.

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

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

Referenced by writeCsvForObject(), and writeObjectsOfSwmmTypeToCsv().

◆ writeCsvForObject()

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

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

Definition at line 1362 of file SWMMInterface.cpp.

1365{
1366 FileIO::CsvInterface csv;
1367 INFO("Writing data for {:s} {:d}.", swmmObjectTypeToString(obj_type),
1368 obj_idx);
1370 std::size_t const n_params(getNumberOfParameters(obj_type));
1371 for (std::size_t i = 0; i < n_params; ++i)
1372 {
1373 std::vector<double> data = getArrayForObject(obj_type, obj_idx, i);
1374 if (!data.empty())
1375 csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1376 }
1377 if (csv.getNArrays() < 2)
1378 {
1379 ERR("No data to write");
1380 return false;
1381 }
1383 return true;
1384}
std::string writeToString()
Writes the object to a string.
Definition Writer.cpp:20
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:34

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

Referenced by writeObjectsOfSwmmTypeToCsv().

◆ writeCsvForTimestep()

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

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

Definition at line 1339 of file SWMMInterface.cpp.

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

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

Member Data Documentation

◆ _base_name

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

◆ _id_linkname_map

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

Vector storing the names of all links/conduits.

Definition at line 200 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 198 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 210 of file SWMMInterface.h.

Referenced by SwmmInterface(), 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 202 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 208 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 206 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 204 of file SWMMInterface.h.

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


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