OGS
SWMMInterface.cpp
Go to the documentation of this file.
1 
9 #include "SwmmInterface.h"
10 
11 #include <swmm5_iface.h>
12 
13 #include <boost/algorithm/string/predicate.hpp>
14 #include <cctype>
15 #include <fstream>
16 #include <utility>
17 
19 #include "BaseLib/FileTools.h"
20 #include "BaseLib/StringTools.h"
21 #include "GeoLib/GEOObjects.h"
22 #include "GeoLib/Point.h"
23 #include "GeoLib/PointVec.h"
24 #include "GeoLib/Polygon.h"
25 #include "GeoLib/Polyline.h"
26 #include "MeshLib/Elements/Line.h"
27 #include "MeshLib/Mesh.h"
28 #include "MeshLib/Node.h"
29 #include "MeshLib/Properties.h"
30 
31 namespace FileIO
32 {
34 const std::array<std::string, 9> subcatchment_vars = {
35  "rainfall",
36  "snow depth",
37  "evaporation loss",
38  "infiltration losses",
39  "runoff rate",
40  "groundwater outflow",
41  "groundwater head",
42  "moisture content",
43  "concentration of pollutant"};
44 
46 const std::array<std::string, 7> node_vars = {"water depth",
47  "hydraulic head",
48  "volume of stored water",
49  "lateral inflow",
50  "total inflow",
51  "flow lost to flooding",
52  "concentration of pollutant"};
53 
55 const std::array<std::string, 6> link_vars = {"flow rate",
56  "flow depth",
57  "flow velocity",
58  "flow volume",
59  "fraction conduit/non-conduit",
60  "concentration of pollutant"};
61 
63 const std::array<std::string, 15> system_vars = {
64  "air temperature",
65  "rainfall",
66  "snow depth",
67  "evaporation + infiltration loss",
68  "runoff flow",
69  "dry weather inflow",
70  "groundwater inflow",
71  "RDII inflow",
72  "direct inflow",
73  "total lateral inflow",
74  "flow lost to flooding",
75  "flow leaving through outfalls",
76  "volume of stored water",
77  "actual evaporation rate",
78  "potential evaporation rate"};
79 
82 std::array<std::size_t, 4> const n_obj_params = {8, 6, 5, 15};
83 
84 std::unique_ptr<SwmmInterface> SwmmInterface::create(
85  std::string const& file_name)
86 {
87  // The input/output methods take a base name and check if the corresponding
88  // i/o file for that base name exists. This check takes any swmm project
89  // file, i.e. [base name].[extension] which needs to be at least 5 chars
90  // because the extension is always 3 chars.
91  if (file_name.length() < 5)
92  return nullptr;
93 
94  if (!SwmmInterface::isSwmmInputFile(file_name))
95  return nullptr;
96 
97  std::string const base_name(file_name.substr(0, file_name.length() - 4));
98  SwmmInterface* swmm = new SwmmInterface(base_name);
99  if (swmm->readSwmmInputToLineMesh())
100  return std::unique_ptr<SwmmInterface>(swmm);
101 
102  ERR("Error creating mesh from SWMM file.");
103  delete swmm;
104  return nullptr;
105 }
106 
107 SwmmInterface::SwmmInterface(std::string const& swmm_base_name)
108  : _base_name(swmm_base_name), _mesh(nullptr)
109 {
110 }
111 
113 {
114  for (Subcatchment& sc : _subcatchments)
115  delete sc.outline;
116 
118  delete pnt;
119 }
120 
121 bool SwmmInterface::isSwmmInputFile(std::string const& inp_file_name)
122 {
123  if (!boost::iequals(BaseLib::getFileExtension(inp_file_name), ".inp"))
124  {
125  ERR("SWMMInterface: {:s} is not a SWMM input file.", inp_file_name);
126  return false;
127  }
128 
129  std::ifstream in(inp_file_name.c_str());
130  if (!in.is_open())
131  {
132  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
133  return false;
134  }
135 
136  std::string line;
137  bool header_found(false);
138  std::size_t pos_end(0);
139  while (!header_found)
140  {
141  if (!std::getline(in, line))
142  return false;
143 
144  std::size_t const pos_beg = line.find_first_not_of(' ', pos_end);
145  pos_end = line.find_first_of(" \n", pos_beg);
146 
147  // skip empty or comment lines at the beginning of the file
148  if (line.empty() || pos_beg == pos_end || isCommentLine(line))
149  continue;
150 
151  if (line == "[TITLE]")
152  header_found = true;
153  else
154  {
155  INFO("SWMMInterface: input file type {:s} not recognised.",
156  BaseLib::getFileExtension(inp_file_name));
157  return false;
158  }
159  }
160 
161  in.close();
162  return true;
163 }
164 
166 {
167  std::string const outfile(_base_name + ".out");
168  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
169  return false;
170  return true;
171 }
172 
173 template <typename T>
174 bool SwmmInterface::readCoordinates(std::ifstream& in, std::vector<T*>& points,
175  std::vector<std::string>& names)
176 {
177  std::size_t id(points.size());
178  std::string line;
179 
180  while (std::getline(in, line))
181  {
182  if (isSectionFinished(line))
183  return true;
184 
185  if (isCommentLine(line))
186  continue;
187 
188  std::vector<std::string> split_str(BaseLib::splitString(line));
189  if (split_str.size() != 3)
190  {
191  ERR("Format not recognised.");
192  return false;
193  }
194  names.push_back(split_str[0]);
195 
196  double const x = BaseLib::str2number<double>(split_str[1]);
197  double const y = BaseLib::str2number<double>(split_str[2]);
198  T* pnt = new T(x, y, 0, id);
199  points.push_back(pnt);
200  id++;
201  }
202  return true;
203 }
204 
205 bool SwmmInterface::readPolygons(std::ifstream& in,
206  std::vector<GeoLib::Polyline*>& lines,
207  std::vector<std::string>& ply_names,
208  std::vector<GeoLib::Point*>& points,
209  std::vector<std::string>& pnt_names)
210 {
211  bool finished(false);
212  std::size_t id(points.size());
213  std::string line;
214  std::string polygon_name("");
215  GeoLib::Polyline* p(nullptr);
216  while (std::getline(in, line))
217  {
218  if (isSectionFinished(line))
219  break;
220 
221  if (isCommentLine(line))
222  continue;
223 
224  std::vector<std::string> split_str(BaseLib::splitString(line));
225  if (split_str.size() != 3)
226  {
227  ERR("Polygon format not recognised.");
228  delete p;
229  return false;
230  }
231 
232  // if a new polygon starts, add the old one to the vector
233  if (split_str[0] != polygon_name)
234  {
235  if (p != nullptr)
236  {
237  p->addPoint(p->getPointID(0));
238  lines.push_back(p);
239  }
240 
241  polygon_name = split_str[0];
242  p = new GeoLib::Polyline(points);
243  ply_names.push_back(polygon_name);
244  }
245 
246  double const x = BaseLib::str2number<double>(split_str[1]);
247  double const y = BaseLib::str2number<double>(split_str[2]);
248  points.push_back(new GeoLib::Point(x, y, 0, id));
249  p->addPoint(points.size() - 1);
250  pnt_names.push_back("");
251  id++;
252  }
253 
254  // when the section is finished, add the last polygon
255  if (p != nullptr)
256  {
257  p->addPoint(p->getPointID(0));
258  lines.push_back(p);
259  }
260 
261  return true;
262 }
263 
265  std::ifstream& in, std::vector<GeoLib::Point*>& points,
266  std::map<std::string, std::size_t> const& name_id_map)
267 {
268  std::string line;
269  while (std::getline(in, line))
270  {
271  if (isSectionFinished(line))
272  return true;
273 
274  if (isCommentLine(line))
275  continue;
276 
277  std::vector<std::string> const split_str(BaseLib::splitString(line));
278  // Junctions = 6, Outfalls = 4, Storage = 8
279  if (split_str.size() < 4)
280  {
281  ERR("Format not recognised.");
282  return false;
283  }
284  std::string const current_name(split_str[0]);
285  auto const it = name_id_map.find(current_name);
286  if (it == name_id_map.end())
287  {
288  ERR("SwmmInterface::addPointElevation(): Name {:s} not found in "
289  "coordinates map.",
290  current_name);
291  return false;
292  }
293  std::size_t const id = it->second;
294  (*points[id])[2] = BaseLib::str2number<double>(split_str[1]);
295  }
296  return true;
297 }
298 
300  std::ifstream& in, std::vector<GeoLib::Polyline*>& lines,
301  std::vector<std::string>& line_names,
302  std::vector<GeoLib::Point*> const& points,
303  std::map<std::string, std::size_t> const& point_names)
304 {
305  std::string line;
306  while (std::getline(in, line))
307  {
308  if (isSectionFinished(line))
309  return true;
310 
311  if (isCommentLine(line))
312  continue;
313 
314  std::vector<std::string> const split_str(BaseLib::splitString(line));
315  // Conduits = 9, Pumps = 7, Weirs = 8
316  if (split_str.size() < 7)
317  {
318  ERR("Conduit format not recognised.");
319  return false;
320  }
321 
322  std::string const inlet(split_str[1]);
323  auto const i_it = point_names.find(inlet);
324  if (i_it == point_names.end())
325  {
326  ERR("SwmmInterface::readLineElements(): Inlet node {:s} not found "
327  "in coordinates map.",
328  inlet);
329  return false;
330  }
331 
332  std::string const outlet(split_str[2]);
333  auto const o_it = point_names.find(outlet);
334  if (o_it == point_names.end())
335  {
336  ERR("SwmmInterface::readLineElements(): Outlet node {:s} not found "
337  "in coordinates map.",
338  outlet);
339  return false;
340  }
341  GeoLib::Polyline* ply = new GeoLib::Polyline(points);
342  std::size_t a(i_it->second);
343  ply->addPoint(i_it->second);
344  ply->addPoint(o_it->second);
345  lines.push_back(ply);
346  line_names.push_back(split_str[0]);
347  }
348  return true;
349 }
350 
351 bool SwmmInterface::convertSwmmInputToGeometry(std::string const& inp_file_name,
352  GeoLib::GEOObjects& geo_objects,
353  bool add_subcatchments)
354 {
355  if (!isSwmmInputFile(inp_file_name))
356  return false;
357 
358  std::ifstream in(inp_file_name.c_str());
359  if (!in.is_open())
360  {
361  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
362  return false;
363  }
364 
365  auto points = std::make_unique<std::vector<GeoLib::Point*>>();
366  auto lines = std::make_unique<std::vector<GeoLib::Polyline*>>();
367  std::vector<std::string> pnt_names;
368  std::vector<std::string> line_names;
369 
370  std::string geo_name =
372  std::string line;
373  while (std::getline(in, line))
374  {
375  if (line == "[COORDINATES]" || line == "[VERTICES]" ||
376  line == "[SYMBOLS]")
377  {
378  if (!readCoordinates<GeoLib::Point>(in, *points, pnt_names))
379  {
380  BaseLib::cleanupVectorElements(*points, *lines);
381  return false;
382  }
383  }
384  if (line == "[Polygons]" && add_subcatchments)
385  {
386  if (!readPolygons(in, *lines, line_names, *points, pnt_names))
387  {
388  BaseLib::cleanupVectorElements(*points, *lines);
389  return false;
390  }
391  }
392  }
393 
394  if (points->empty())
395  {
396  ERR("No points found in file");
397  return false;
398  }
399  if (points->size() != pnt_names.size())
400  {
401  ERR("Length of point vector and point name vector do not match.");
402  BaseLib::cleanupVectorElements(*points, *lines);
403  return false;
404  }
405 
406  auto name_id_map = std::make_unique<std::map<std::string, std::size_t>>();
407  {
408  std::size_t const n_names(pnt_names.size());
409  for (std::size_t i = 0; i < n_names; ++i)
410  {
411  if (!pnt_names[i].empty())
412  name_id_map->insert(std::make_pair(pnt_names[i], i));
413  }
414  }
415 
416  // rewind stream and read links between junctions
417  in.clear();
418  in.seekg(0, in.beg);
419 
420  while (std::getline(in, line))
421  {
422  if (line == "[JUNCTIONS]")
423  {
424  INFO("Reading point elevation...");
425  if (!addPointElevation(in, *points, *name_id_map))
426  {
427  BaseLib::cleanupVectorElements(*points, *lines);
428  return false;
429  }
430  }
431  if (line == "[CONDUITS]")
432  {
433  INFO("Reading conduits...");
434  if (!readLinksAsPolylines(in, *lines, line_names, *points,
435  *name_id_map))
436  {
437  BaseLib::cleanupVectorElements(*points, *lines);
438  return false;
439  }
440  }
441  else if (line == "[PUMPS]")
442  {
443  INFO("Reading pumps...");
444  if (!readLinksAsPolylines(in, *lines, line_names, *points,
445  *name_id_map))
446  {
447  BaseLib::cleanupVectorElements(*points, *lines);
448  return false;
449  }
450  }
451  else if (line == "[WEIRS]")
452  {
453  INFO("Reading weirs...");
454  if (!readLinksAsPolylines(in, *lines, line_names, *points,
455  *name_id_map))
456  {
457  BaseLib::cleanupVectorElements(*points, *lines);
458  return false;
459  }
460  }
461  }
462 
463  geo_objects.addPointVec(std::move(points), geo_name,
464  std::move(name_id_map));
465  if (!lines->empty())
466  {
467  if (lines->size() != line_names.size())
468  {
469  ERR("Length of line vector and line name vector do not match.");
470  geo_objects.removePointVec(geo_name);
471  for (auto ply : *lines)
472  delete ply;
473  return false;
474  }
475  auto line_id_map =
476  std::make_unique<std::map<std::string, std::size_t>>();
477  {
478  std::size_t const n_names(line_names.size());
479  for (std::size_t i = 0; i < n_names; ++i)
480  {
481  line_id_map->insert(std::make_pair(line_names[i], i));
482  }
483  }
484  std::vector<std::size_t> const& pnt_id_map(
485  geo_objects.getPointVecObj(geo_name)->getIDMap());
486  for (GeoLib::Polyline* polyline : *lines)
487  {
488  for (std::size_t i = 0; i < polyline->getNumberOfPoints(); ++i)
489  {
490  polyline->setPointID(i, pnt_id_map[polyline->getPointID(i)]);
491  if (i > 0 &&
492  polyline->getPointID(i - 1) == polyline->getPointID(i))
493  {
494  polyline->removePoint(i);
495  i--;
496  }
497  }
498  if (polyline->getPointID(0) ==
499  polyline->getPointID(polyline->getNumberOfPoints() - 1))
500  {
501  polyline->removePoint(polyline->getNumberOfPoints() - 1);
502  polyline->addPoint(polyline->getPointID(0));
503  }
504  }
505  geo_objects.addPolylineVec(std::move(lines), geo_name,
506  std::move(line_id_map));
507  }
508  return true;
509 }
510 
512  std::ifstream& in, std::vector<MeshLib::Node*>& nodes,
513  std::map<std::string, std::size_t> const& name_id_map,
514  std::vector<double>& max_depth, bool read_max_depth)
515 {
516  std::string line;
517  while (std::getline(in, line))
518  {
519  if (isSectionFinished(line))
520  return true;
521 
522  if (isCommentLine(line))
523  continue;
524 
525  std::vector<std::string> const split_str(BaseLib::splitString(line));
526  // Junctions = 6, Outfalls = 4, Storage = 8
527  if (split_str.size() < 3)
528  {
529  ERR("Format not recognised.");
530  return false;
531  }
532  std::string const current_name(split_str[0]);
533  auto const it = name_id_map.find(current_name);
534  if (it == name_id_map.end())
535  {
536  ERR("SwmmInterface::readNodeData(): Name {:s} not found in "
537  "coordinates map.",
538  current_name);
539  return false;
540  }
541  std::size_t const id = it->second;
542  (*nodes[id])[2] = BaseLib::str2number<double>(split_str[1]);
543 
544  if (read_max_depth)
545  max_depth[id] = BaseLib::str2number<double>(split_str[2]);
546  else
547  max_depth[id] = 0;
548  }
549  return true;
550 }
551 
553  std::ifstream& in, std::vector<MeshLib::Element*>& elements,
554  std::vector<MeshLib::Node*> const& nodes,
555  std::map<std::string, std::size_t> const& name_id_map)
556 {
557  std::string line;
558  while (std::getline(in, line))
559  {
560  if (isSectionFinished(line))
561  return true;
562 
563  if (isCommentLine(line))
564  continue;
565 
566  std::vector<std::string> const split_str(BaseLib::splitString(line));
567  // Conduits = 9, Pumps = 7, Weirs = 8
568  if (split_str.size() < 7)
569  {
570  ERR("Conduit format not recognised.");
571  return false;
572  }
573 
574  std::string const inlet(split_str[1]);
575  auto const i_it = name_id_map.find(inlet);
576  if (i_it == name_id_map.end())
577  {
578  ERR("SwmmInterface::readLineElements(): Inlet node {:s} not found "
579  "in coordinates map.",
580  inlet);
581  return false;
582  }
583 
584  std::string const outlet(split_str[2]);
585  auto const o_it = name_id_map.find(outlet);
586  if (o_it == name_id_map.end())
587  {
588  ERR("SwmmInterface::readLineElements(): Outlet node {:s} not found "
589  "in coordinates map.",
590  outlet);
591  return false;
592  }
593 
594  std::array<MeshLib::Node*, 2> const line_nodes = {nodes[i_it->second],
595  nodes[o_it->second]};
596  elements.push_back(new MeshLib::Line(line_nodes));
597  _id_linkname_map.push_back(split_str[0]);
598  }
599  return true;
600 }
601 
603  std::ifstream& in, std::map<std::string, std::size_t> const& name_id_map)
604 {
605  std::string line;
606  while (getline(in, line))
607  {
608  if (isSectionFinished(line))
609  return true;
610 
611  if (isCommentLine(line))
612  continue;
613 
614  std::vector<std::string> const split_str(BaseLib::splitString(line));
615  if (split_str.size() < 8)
616  {
617  ERR("Subcatchment format not recognised.");
618  return false;
619  }
620 
621  Subcatchment sc;
622  sc.name = split_str[0];
623  sc.rain_gauge = std::numeric_limits<std::size_t>::max();
624  std::size_t const n_gauges(_rain_gauges.size());
625  for (std::size_t i = 0; i < n_gauges; ++i)
626  {
627  if (_rain_gauges[i].first.getName() == split_str[1])
628  {
629  sc.rain_gauge = i;
630  break;
631  }
632  }
633  if (sc.rain_gauge == std::numeric_limits<std::size_t>::max())
634  {
635  ERR("Rain gauge for subcatchment '{:s}' not found.", split_str[0]);
636  return false;
637  }
638 
639  auto const it = name_id_map.find(split_str[2]);
640  if (it == name_id_map.end())
641  {
642  ERR("Outlet node for subcatchment '{:s}' not found.", split_str[0]);
643  return false;
644  }
645  sc.outlet = it->second;
646  sc.area = BaseLib::str2number<double>(split_str[3]);
647  _subcatchments.push_back(sc);
648  }
649 
650  return true;
651 }
652 
654 {
655  if (_mesh != nullptr)
656  {
657  ERR("Mesh already exists.");
658  return false;
659  }
660 
661  std::string const inp_file_name(_base_name + ".inp");
662  if (!isSwmmInputFile(inp_file_name))
663  return false;
664 
665  std::ifstream in(inp_file_name.c_str());
666  if (!in.is_open())
667  {
668  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
669  return false;
670  }
671 
672  _id_nodename_map.clear();
673  std::vector<MeshLib::Node*> nodes;
674  std::string line;
675  while (getline(in, line))
676  {
677  if (line == "[COORDINATES]")
678  {
679  INFO("Reading coordinates...");
680  if (!readCoordinates<MeshLib::Node>(in, nodes, _id_nodename_map))
681  return false;
682  }
683  /* TODO: check if needed
684  else if (line == "[VERTICES]")
685  {
686  INFO ("Reading vertices...");
687  if (!readCoordinates(in, nodes, _id_nodename_map))
688  return false;
689  }
690  */
691  else if (line == "[SYMBOLS]")
692  {
693  INFO("Reading symbols...");
694  std::vector<GeoLib::Point*> points;
695  std::vector<std::string> names;
696  if (!readCoordinates(in, points, names))
697  return false;
698  for (std::size_t i = 0; i < points.size(); ++i)
699  {
700  GeoLib::Station stn(points[i], names[i]);
701  _rain_gauges.push_back(
702  std::pair<GeoLib::Station, std::string>(stn, ""));
703  }
704  }
705  }
706 
707  if (nodes.empty())
708  return false;
709 
710  // After end of file is reached, create name-id-map and
711  // start reading again to get line elements and node data.
712  std::map<std::string, std::size_t> name_id_map;
713  std::size_t const n_nodes(nodes.size());
714  for (std::size_t i = 0; i < n_nodes; ++i)
715  name_id_map[_id_nodename_map[i]] = i;
716  in.clear();
717  in.seekg(0, in.beg);
718 
719  std::vector<MeshLib::Element*> elements;
720  std::vector<double> max_depth(n_nodes);
721  std::size_t const n_types = 3;
722  std::array<std::size_t, n_types> n_elem_types{{0, 0, 0}};
723  while (getline(in, line))
724  {
725  if (line == "[RAINGAGES]")
726  {
727  if (!_rain_gauges.empty())
729  }
730  else if (line == "[SUBCATCHMENTS]")
731  {
732  INFO("Reading subcatchment information...");
733  if (!readSubcatchments(in, name_id_map))
734  return false;
735  }
736  else if (line == "[SUBAREAS]")
737  {
738  // more subcatchment variables, not yet implemented
739  }
740  else if (line == "[INFILTRATION]")
741  {
742  // more subcatchment variables, not yet implemented
743  }
744  else if (line == "[JUNCTIONS]")
745  {
746  INFO("Reading junctions...");
747  if (!readNodeData(in, nodes, name_id_map, max_depth, true))
748  return false;
749  }
750  else if (line == "[OUTFALLS]")
751  {
752  INFO("Reading outfalls...");
753  if (!readNodeData(in, nodes, name_id_map, max_depth, false))
754  return false;
755  }
756  else if (line == "[STORAGE]")
757  {
758  INFO("Reading storages...");
759  if (!readNodeData(in, nodes, name_id_map, max_depth, true))
760  return false;
761  }
762  else if (line == "[CONDUITS]")
763  {
764  INFO("Reading conduits...");
765  if (!readLineElements(in, elements, nodes, name_id_map))
766  return false;
767  n_elem_types[0] = elements.size();
768  }
769  else if (line == "[PUMPS]")
770  {
771  INFO("Reading pumps...");
772  if (!readLineElements(in, elements, nodes, name_id_map))
773  return false;
774  n_elem_types[1] = elements.size();
775  }
776  else if (line == "[WEIRS]")
777  {
778  INFO("Reading weirs...");
779  if (!readLineElements(in, elements, nodes, name_id_map))
780  return false;
781  n_elem_types[2] = elements.size();
782  }
783  else if (line == "[POLLUTANTS]")
784  {
785  if (!readPollutants(in))
786  return false;
787  }
788  else if (line == "[Polygons]")
789  {
790  INFO("Reading subcatchments...");
791  std::vector<GeoLib::Polyline*> lines;
792  std::vector<std::string> line_names;
793  std::vector<std::string>
794  tmp_names; // polygon points are nameless but the method
795  // requires a vector
796  if (!readPolygons(in, lines, line_names, _subcatchment_points,
797  tmp_names))
798  return false;
799 
800  if (!matchSubcatchmentsWithPolygons(lines, line_names))
801  return false;
802  }
803  }
804 
805  if (elements.empty())
806  {
807  for (MeshLib::Node* node : nodes)
808  delete node;
809  return false;
810  }
811 
812  MeshLib::Properties props;
813  auto* const mat_ids = props.createNewPropertyVector<int>(
814  "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
815  mat_ids->resize(elements.size(), 0);
816  for (std::size_t i = 1; i < n_types; ++i)
817  {
818  if (n_elem_types[i] > 0)
819  std::fill(mat_ids->begin() + n_elem_types[i - 1],
820  mat_ids->begin() + n_elem_types[i], i);
821  }
822 
823  if (nodes.size() == max_depth.size())
824  {
825  auto* const depth = props.createNewPropertyVector<double>(
826  "Max Depth", MeshLib::MeshItemType::Node, 1);
827  depth->reserve(max_depth.size());
828  std::copy(max_depth.cbegin(), max_depth.cend(),
829  std::back_inserter(*depth));
830  }
831  else
832  ERR("Size of max depth array does not fit number of elements. Skipping "
833  "array.");
834 
835  _mesh.reset(new MeshLib::Mesh(_base_name, nodes, elements, props));
836  return true;
837 }
838 
840  std::vector<GeoLib::Polyline*> const& lines,
841  std::vector<std::string> const& names)
842 {
843  std::size_t const n_lines(lines.size());
844  std::size_t const n_subcatchments(_subcatchments.size());
845 
846  if (n_lines != n_subcatchments)
847  {
848  ERR("Number of subcatchments does not match number of outlines.");
849  return false;
850  }
851  for (std::size_t i = 0; i < n_lines; ++i)
852  {
853  bool found = false;
854  for (std::size_t j = 0; j < n_subcatchments; ++j)
855  {
856  if (names[i] == _subcatchments[j].name)
857  {
858  _subcatchments[j].outline = lines[i];
859  found = true;
860  break;
861  }
862  }
863  if (found == false)
864  {
865  ERR("No match in subcatcments for outline '{:s}'.", names[i]);
866  return false;
867  }
868  }
869  return true;
870 }
871 
872 std::vector<std::string> SwmmInterface::getSubcatchmentNameMap() const
873 {
874  std::vector<std::string> names;
875  names.reserve(_subcatchments.size());
876  std::transform(_subcatchments.begin(), _subcatchments.end(),
877  std::back_inserter(names),
878  [](auto const& sc) { return sc.name; });
879  return names;
880 }
881 
882 std::vector<std::string> SwmmInterface::getNames(SwmmObject obj_type) const
883 {
884  switch (obj_type)
885  {
886  case SwmmObject::NODE:
887  return _id_nodename_map;
888  case SwmmObject::LINK:
889  return _id_linkname_map;
891  return getSubcatchmentNameMap();
892  case SwmmObject::SYSTEM:
893  std::vector<std::string> system_name{"System"};
894  return system_name;
895  }
896  ERR("Object type has no name map");
897  std::vector<std::string> empty_vec;
898  return empty_vec;
899 }
900 
901 std::string SwmmInterface::getName(SwmmObject obj_type, std::size_t idx) const
902 {
903  switch (obj_type)
904  {
905  case SwmmObject::NODE:
906  if (idx < _id_nodename_map.size())
907  return _id_nodename_map[idx];
908  case SwmmObject::LINK:
909  if (idx < _id_linkname_map.size())
910  return _id_linkname_map[idx];
912  if (idx < _subcatchments.size())
913  return _subcatchments[idx].name;
914  case SwmmObject::SYSTEM:
915  if (idx == 0)
916  return std::string("System");
917  }
918  ERR("Index out of bounds.");
919  return std::string("");
920 }
921 
923 {
924  std::string const outfile(_base_name + ".out");
925  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
926  return 0;
927 
928  switch (obj_type)
929  {
931  return SWMM_Nsubcatch;
932  case SwmmObject::NODE:
933  return SWMM_Nnodes;
934  case SwmmObject::LINK:
935  return SWMM_Nlinks;
936  case SwmmObject::SYSTEM:
937  return 1;
938  default:
939  ERR("Object type not recognised.");
940  }
941  CloseSwmmOutFile();
942  return 0;
943 }
944 
946 {
947  std::string const outfile(_base_name + ".out");
948  std::size_t n_time_steps(std::numeric_limits<std::size_t>::max());
949  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
950  return 0;
951 
952  std::size_t n_params(0);
953  switch (obj_type)
954  {
956  n_params = n_obj_params[0] + SWMM_Npolluts;
957  break;
958  case SwmmObject::NODE:
959  n_params = n_obj_params[1] + SWMM_Npolluts;
960  break;
961  case SwmmObject::LINK:
962  n_params = n_obj_params[2] + SWMM_Npolluts;
963  break;
964  case SwmmObject::SYSTEM:
965  n_params = n_obj_params[3];
966  break;
967  default:
968  ERR("Object type not recognised.");
969  }
970  CloseSwmmOutFile();
971  return n_params;
972 }
973 
975 {
976  std::string const outfile(_base_name + ".out");
977  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
978  return std::numeric_limits<std::size_t>::max();
979  std::size_t const n_time_steps(static_cast<std::size_t>(SWMM_Nperiods));
980  CloseSwmmOutFile();
981  return n_time_steps;
982 }
983 
985  SwmmObject const swmm_type,
986  std::string const& vec_name,
987  std::vector<double> const& data)
988 {
989  if (!(swmm_type == SwmmObject::NODE || swmm_type == SwmmObject::LINK))
990  {
991  ERR("Information of this object type cannot be added to mesh.");
992  return false;
993  }
994 
995  if (data.empty())
996  {
997  ERR("Data array is empty and cannot be added to mesh.");
998  return false;
999  }
1000 
1001  if (swmm_type == SwmmObject::NODE && data.size() != mesh.getNumberOfNodes())
1002  {
1003  ERR("Number of mesh nodes ({:d}) does not match length of array "
1004  "({:d}).",
1005  mesh.getNumberOfNodes(), data.size());
1006  return false;
1007  }
1008 
1009  if (swmm_type == SwmmObject::LINK &&
1010  data.size() != mesh.getNumberOfElements())
1011  {
1012  ERR("Number of mesh elements ({:d}) does not match length of array "
1013  "({:d}).",
1014  mesh.getNumberOfElements(), data.size());
1015  return false;
1016  }
1017 
1018  MeshLib::MeshItemType const item_type = (swmm_type == SwmmObject::NODE)
1022  MeshLib::getOrCreateMeshProperty<double>(mesh, vec_name, item_type, 1);
1023  if (!prop)
1024  {
1025  ERR("Error fetching array '{:s}'.", vec_name);
1026  return false;
1027  }
1028  std::copy(data.cbegin(), data.cend(), prop->begin());
1029  return true;
1030 }
1031 
1032 std::vector<double> SwmmInterface::getArrayAtTimeStep(SwmmObject obj_type,
1033  std::size_t time_step,
1034  std::size_t var_idx) const
1035 {
1036  std::vector<double> data;
1037  std::string const outfile(_base_name + ".out");
1038  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1039  return data;
1040 
1041  if (time_step >= SWMM_Nperiods)
1042  {
1043  ERR("Time step {:d} not available, file contains only {:d} periods.",
1044  time_step, SWMM_Nperiods);
1045  return data;
1046  }
1047 
1048  bool is_var_idx_okay = true;
1049  int obj_type_id;
1050  std::size_t n_objects;
1051  switch (obj_type)
1052  {
1054  obj_type_id = 0;
1055  n_objects = SWMM_Nsubcatch;
1056  if (var_idx > (n_obj_params[obj_type_id] - 1 + SWMM_Npolluts))
1057  is_var_idx_okay = false;
1058  break;
1059  case SwmmObject::NODE:
1060  obj_type_id = 1;
1061  n_objects = SWMM_Nnodes;
1062  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1063  is_var_idx_okay = false;
1064  break;
1065  case SwmmObject::LINK:
1066  obj_type_id = 2;
1067  n_objects = SWMM_Nlinks;
1068  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1069  is_var_idx_okay = false;
1070  break;
1071  case SwmmObject::SYSTEM:
1072  obj_type_id = 3;
1073  n_objects = 1;
1074  if (var_idx > n_obj_params[obj_type_id])
1075  is_var_idx_okay = false;
1076  break;
1077  default:
1078  ERR("Object type not recognised.");
1079  CloseSwmmOutFile();
1080  return data;
1081  }
1082 
1083  if (!is_var_idx_okay)
1084  {
1085  ERR("Requested variable does not exist.");
1086  CloseSwmmOutFile();
1087  return data;
1088  }
1089 
1090  INFO("Fetching '{:s}'-data for time step {:d}...",
1091  getArrayName(obj_type, var_idx, SWMM_Npolluts), time_step);
1092 
1093  for (std::size_t i = 0; i < n_objects; ++i)
1094  {
1095  float val;
1096  GetSwmmResult(obj_type_id, i, var_idx, time_step, &val);
1097  data.push_back(static_cast<double>(val));
1098  }
1099 
1100  CloseSwmmOutFile();
1101  return data;
1102 }
1103 
1104 std::vector<double> SwmmInterface::getArrayForObject(SwmmObject obj_type,
1105  std::size_t obj_idx,
1106  std::size_t var_idx) const
1107 {
1108  std::vector<double> data;
1109  std::string const outfile(_base_name + ".out");
1110  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1111  return data;
1112 
1113  bool is_var_idx_okay = true;
1114  bool is_obj_idx_okay = true;
1115  int obj_type_id;
1116  switch (obj_type)
1117  {
1119  obj_type_id = 0;
1120  if (obj_idx >= SWMM_Nsubcatch)
1121  is_obj_idx_okay = false;
1122  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1123  is_var_idx_okay = false;
1124  break;
1125  case SwmmObject::NODE:
1126  obj_type_id = 1;
1127  if (obj_idx >= SWMM_Nnodes)
1128  is_obj_idx_okay = false;
1129  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1130  is_var_idx_okay = false;
1131  break;
1132  case SwmmObject::LINK:
1133  obj_type_id = 2;
1134  if (obj_idx >= SWMM_Nlinks)
1135  is_obj_idx_okay = false;
1136  if (var_idx > (n_obj_params[obj_type_id] + SWMM_Npolluts))
1137  is_var_idx_okay = false;
1138  break;
1139  case SwmmObject::SYSTEM:
1140  obj_type_id = 3;
1141  if (obj_idx >= 1)
1142  is_obj_idx_okay = false;
1143  if (var_idx > n_obj_params[obj_type_id])
1144  is_var_idx_okay = false;
1145  break;
1146  default:
1147  ERR("Object type not recognised.");
1148  CloseSwmmOutFile();
1149  return data;
1150  }
1151 
1152  if (!is_obj_idx_okay)
1153  {
1154  ERR("Requested object index does not exist.");
1155  CloseSwmmOutFile();
1156  return data;
1157  }
1158 
1159  if (!is_var_idx_okay)
1160  {
1161  ERR("Requested variable does not exist.");
1162  CloseSwmmOutFile();
1163  return data;
1164  }
1165 
1166  std::size_t const n_time_steps(static_cast<std::size_t>(SWMM_Nperiods));
1167  for (std::size_t i = 0; i < n_time_steps; ++i)
1168  {
1169  float val;
1170  GetSwmmResult(obj_type_id, obj_idx, var_idx, i, &val);
1171  data.push_back(static_cast<double>(val));
1172  }
1173 
1174  CloseSwmmOutFile();
1175  return data;
1176 }
1177 
1179  std::size_t var_idx) const
1180 {
1181  std::string const outfile(_base_name + ".out");
1182  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
1183  return std::string("");
1184 
1185  std::string const name = getArrayName(obj_type, var_idx, SWMM_Npolluts);
1186  CloseSwmmOutFile();
1187  return name;
1188 }
1189 
1191  std::size_t var_idx,
1192  std::size_t n_pollutants) const
1193 {
1194  if (obj_type == SwmmObject::SUBCATCHMENT)
1195  {
1196  if (var_idx < n_obj_params[0])
1197  return subcatchment_vars[var_idx];
1198  if (var_idx < n_obj_params[0] + n_pollutants)
1199  return _pollutant_names[var_idx - n_obj_params[0]];
1200  }
1201  if (obj_type == SwmmObject::NODE)
1202  {
1203  if (var_idx < n_obj_params[1])
1204  return node_vars[var_idx];
1205  if (var_idx < n_obj_params[1] + n_pollutants)
1206  return std::string("Node_" +
1207  _pollutant_names[var_idx - n_obj_params[1]]);
1208  }
1209  if (obj_type == SwmmObject::LINK)
1210  {
1211  if (var_idx < n_obj_params[2])
1212  return link_vars[var_idx];
1213  if (var_idx < n_obj_params[2] + n_pollutants)
1214  return std::string("Link_" +
1215  _pollutant_names[var_idx - n_obj_params[2]]);
1216  }
1217  if (obj_type == SwmmObject::SYSTEM && var_idx < n_obj_params[3])
1218  {
1219  return system_vars[var_idx];
1220  }
1221  ERR("SwmmInterface::getArrayName() - Index error, no name found.");
1222  return std::string("");
1223 }
1224 
1226 {
1227  std::string line;
1228  while (getline(in, line))
1229  {
1230  if (isSectionFinished(line))
1231  break;
1232 
1233  if (isCommentLine(line))
1234  continue;
1235 
1236  std::vector<std::string> const split_str(BaseLib::splitString(line));
1237  if (split_str.size() < 6)
1238  {
1239  ERR("Rain gauge parameter format not recognised.");
1240  return false;
1241  }
1242 
1243  for (auto& stn : _rain_gauges)
1244  {
1245  if (stn.first.getName() == split_str[0] && split_str[4] == "FILE")
1246  stn.second = split_str[5].substr(1, split_str[5].size() - 2);
1247  }
1248  }
1249 
1250  for (auto const& stn : _rain_gauges)
1251  if (stn.second.empty())
1252  WARN("No associated time series found for rain gauge '{:s}'.",
1253  stn.first.getName());
1254  return true;
1255 }
1256 
1257 bool SwmmInterface::readPollutants(std::ifstream& in)
1258 {
1259  std::string line;
1260  while (getline(in, line))
1261  {
1262  if (isSectionFinished(line))
1263  return true;
1264 
1265  if (isCommentLine(line))
1266  continue;
1267 
1268  std::vector<std::string> split_str(BaseLib::splitString(line));
1269  if (split_str.size() < 6)
1270  {
1271  ERR("Parameter format for pollutants not recognised.");
1272  return false;
1273  }
1274  _pollutant_names.push_back(split_str[0]);
1275  }
1276  return true;
1277 }
1278 
1279 bool SwmmInterface::isSectionFinished(std::string const& str)
1280 {
1281  if (str.empty())
1282  return true;
1283 
1284  std::size_t const pos_beg = str.find_first_not_of(' ', 0);
1285  if (pos_beg == str.find_first_of(" \n", pos_beg))
1286  return true;
1287 
1288  return false;
1289 }
1290 
1291 bool SwmmInterface::isCommentLine(std::string const& str)
1292 {
1293  return (str.compare(str.find_first_not_of(' ', 0), 1, ";") == 0);
1294 }
1295 
1296 bool SwmmInterface::getNodeCoordinateVectors(std::vector<double>& x,
1297  std::vector<double>& y,
1298  std::vector<double>& z) const
1299 {
1300  std::vector<MeshLib::Node*> const& nodes(_mesh->getNodes());
1301  for (MeshLib::Node const* const node : nodes)
1302  {
1303  x.push_back((*node)[0]);
1304  y.push_back((*node)[1]);
1305  z.push_back((*node)[2]);
1306  }
1307  return true;
1308 }
1309 
1310 bool SwmmInterface::getLinkPointIds(std::vector<std::size_t>& inlets,
1311  std::vector<std::size_t>& outlets) const
1312 {
1313  std::vector<MeshLib::Element*> const& elements(_mesh->getElements());
1314  for (MeshLib::Element const* const elem : elements)
1315  {
1316  if (elem->getGeomType() != MeshLib::MeshElemType::LINE)
1317  {
1318  ERR("Non line-element found in mesh.");
1319  return false;
1320  }
1321  inlets.push_back(getNodeIndex(*elem, 0));
1322  outlets.push_back(getNodeIndex(*elem, 1));
1323  }
1324  return true;
1325 }
1326 
1328 {
1329  if (obj_type == SwmmObject::NODE)
1330  return "node";
1331  if (obj_type == SwmmObject::LINK)
1332  return "link";
1333  if (obj_type == SwmmObject::SUBCATCHMENT)
1334  return "subcatchment";
1335  if (obj_type == SwmmObject::SYSTEM)
1336  return "system";
1337  return "undefined";
1338 }
1339 
1340 bool SwmmInterface::writeCsvForTimestep(std::string const& file_name,
1341  SwmmObject obj_type,
1342  std::size_t time_step) const
1343 {
1346  csv.addVectorForWriting("Name", getNames(obj_type));
1347  std::size_t const n_params(getNumberOfParameters(obj_type));
1348  for (std::size_t i = 0; i < n_params; ++i)
1349  {
1350  std::vector<double> data = getArrayAtTimeStep(obj_type, time_step, i);
1351  if (!data.empty())
1352  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1353  }
1354  if (csv.getNArrays() < 2)
1355  {
1356  ERR("No data to write");
1357  return false;
1358  }
1360  return true;
1361 }
1362 
1363 bool SwmmInterface::writeCsvForObject(std::string const& file_name,
1364  SwmmObject obj_type,
1365  std::size_t obj_idx) const
1366 {
1368  INFO("Writing data for {:s} {:d}.", swmmObjectTypeToString(obj_type),
1369  obj_idx);
1371  std::size_t const n_params(getNumberOfParameters(obj_type));
1372  for (std::size_t i = 0; i < n_params; ++i)
1373  {
1374  std::vector<double> data = getArrayForObject(obj_type, obj_idx, i);
1375  if (!data.empty())
1376  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1377  }
1378  if (csv.getNArrays() < 2)
1379  {
1380  ERR("No data to write");
1381  return false;
1382  }
1384  return true;
1385 }
1386 
1387 } // namespace FileIO
Definition of the CsvInterface class.
Filename manipulation routines.
Definition of the GEOObjects class.
Definition of the Point class.
Definition of the Line class.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
Definition of the class Properties that implements a container of properties.
Definition of the Mesh class.
Definition of the Node class.
Definition of the PointVec class.
Definition of the Polygon class.
Definition of the PolyLine class.
Definition of string helper functions.
std::string writeToString()
Writes the object to a string.
Definition: Writer.cpp:31
bool addVectorForWriting(std::string const &vec_name, std::vector< T > const &vec)
Definition: CsvInterface.h:64
void addIndexVectorForWriting(std::size_t s)
Adds an index vector of size s to the CSV file.
std::size_t getNArrays() const
Returns the number of vectors currently staged for writing.
Definition: CsvInterface.h:47
~SwmmInterface()
Destructor.
std::unique_ptr< MeshLib::Mesh > _mesh
Mesh generated from SWMM input (+ optional output data)
std::vector< std::string > _id_nodename_map
Vector storing the names of all nodes/junctions.
std::size_t getNumberOfObjects(SwmmObject obj_type) const
Returns the number of objects of the given type.
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 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.
std::vector< std::string > getSubcatchmentNameMap() const
Creates a temporary string vector containing all subcatchment names in correct order.
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).
static bool isCommentLine(std::string const &str)
Checks if the given line string is a comment line.
std::string const _base_name
All files for a given SWMM simulation have the same base name.
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 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...
SwmmInterface(std::string const &swmm_base_name)
Constructor.
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)
bool addRainGaugeTimeSeriesLocations(std::ifstream &in)
Reads the location of external rain gauge time series files.
std::vector< GeoLib::Point * > _subcatchment_points
Separate node vector containing points for defining subcatchment outlines.
static bool isSwmmInputFile(std::string const &inp_file_name)
Checks if file is a SWMM input file.
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 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.
std::vector< std::pair< GeoLib::Station, std::string > > _rain_gauges
Vector containing rain gauge information as well the position of external time series files.
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.
std::vector< std::string > _id_linkname_map
Vector storing the names of all links/conduits.
static std::unique_ptr< SwmmInterface > create(std::string const &file_name)
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::size_t getNumberOfTimeSteps() const
Returns the number of time steps for the simulation results.
static bool readCoordinates(std::ifstream &in, std::vector< T * > &points, std::vector< std::string > &names)
static bool addResultsToMesh(MeshLib::Mesh &mesh, SwmmObject const type, std::string const &vec_name, std::vector< double > const &data)
bool existsSwmmOutputFile() const
Checks if a SWMM output file exists for the current input.
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.
static std::string swmmObjectTypeToString(SwmmObject const obj_type)
Returns a string with the name of the object type.
bool readSwmmInputToLineMesh()
Reading a SWMM input file and creating an OGS line mesh. This is automatically called when the object...
std::size_t getNumberOfParameters(SwmmObject obj_type) const
Returns the number of parameters (incl. pollutants) of the given type.
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.
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.)
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< Subcatchment > _subcatchments
Vector storing information about all subcatchments.
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< 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...
std::vector< std::string > getNames(SwmmObject obj_type) const
Get all the object names for a given object type.
std::vector< std::string > _pollutant_names
Vector storing the names of all pollutants.
Container class for geometric objects.
Definition: GEOObjects.h:61
const PointVec * getPointVecObj(const std::string &name) const
Definition: GEOObjects.cpp:84
bool removePointVec(const std::string &name)
Definition: GEOObjects.cpp:97
void addPointVec(std::unique_ptr< std::vector< Point * >> points, std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> pnt_id_name_map=nullptr, double eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Definition: GEOObjects.cpp:51
void addPolylineVec(std::unique_ptr< std::vector< Polyline * >> lines, const std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> ply_names=nullptr)
Definition: GEOObjects.cpp:150
const std::vector< std::size_t > & getIDMap() const
Definition: PointVec.h:97
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition: Polyline.h:51
virtual bool addPoint(std::size_t pnt_id)
Definition: Polyline.cpp:34
A Station (observation site) is basically a Point with some additional information.
Definition: Station.h:37
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition: Mesh.h:89
std::size_t getNumberOfElements() const
Get the number of elements.
Definition: Mesh.h:86
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
Definition: Properties.h:36
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)
int writeStringToFile(std::string content, std::filesystem::path const &file_path)
Definition: Writer.cpp:45
std::string getFileExtension(const std::string &path)
Definition: FileTools.cpp:186
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
std::vector< std::string > splitString(std::string const &str)
Definition: StringTools.cpp:28
void cleanupVectorElements(std::vector< T1 * > const &items, std::vector< T2 * > const &dependent_items)
Definition: Algorithm.h:300
SwmmObject
SWMM object types.
Definition: SWMMInterface.h:35
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.
std::array< std::size_t, 4 > const n_obj_params
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
MeshItemType
Definition: Location.h:21
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition: Element.cpp:225