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  std::vector<GeoLib::Point*> points;
366  std::vector<GeoLib::Polyline*> lines;
367  std::vector<std::string> pnt_names;
368  std::vector<std::string> line_names;
369 
370  std::string geo_name =
372  std::string line;
373  while (std::getline(in, line))
374  {
375  if (line == "[COORDINATES]" || line == "[VERTICES]" ||
376  line == "[SYMBOLS]")
377  {
378  if (!readCoordinates<GeoLib::Point>(in, points, pnt_names))
379  {
380  BaseLib::cleanupVectorElements(points, lines);
381  return false;
382  }
383  }
384  if (line == "[Polygons]" && add_subcatchments)
385  {
386  if (!readPolygons(in, lines, line_names, points, pnt_names))
387  {
388  BaseLib::cleanupVectorElements(points, lines);
389  return false;
390  }
391  }
392  }
393 
394  if (points.empty())
395  {
396  ERR("No points found in file");
397  return false;
398  }
399  if (points.size() != pnt_names.size())
400  {
401  ERR("Length of point vector and point name vector do not match.");
402  BaseLib::cleanupVectorElements(points, lines);
403  return false;
404  }
405 
406  GeoLib::PointVec::NameIdMap name_id_map;
407  {
408  std::size_t const n_names(pnt_names.size());
409  for (std::size_t i = 0; i < n_names; ++i)
410  {
411  if (!pnt_names[i].empty())
412  name_id_map.insert(std::make_pair(pnt_names[i], i));
413  }
414  }
415 
416  // rewind stream and read links between junctions
417  in.clear();
418  in.seekg(0, in.beg);
419 
420  while (std::getline(in, line))
421  {
422  if (line == "[JUNCTIONS]")
423  {
424  INFO("Reading point elevation...");
425  if (!addPointElevation(in, points, name_id_map))
426  {
427  BaseLib::cleanupVectorElements(points, lines);
428  return false;
429  }
430  }
431  if (line == "[CONDUITS]")
432  {
433  INFO("Reading conduits...");
434  if (!readLinksAsPolylines(in, lines, line_names, points,
435  name_id_map))
436  {
437  BaseLib::cleanupVectorElements(points, lines);
438  return false;
439  }
440  }
441  else if (line == "[PUMPS]")
442  {
443  INFO("Reading pumps...");
444  if (!readLinksAsPolylines(in, lines, line_names, points,
445  name_id_map))
446  {
447  BaseLib::cleanupVectorElements(points, lines);
448  return false;
449  }
450  }
451  else if (line == "[WEIRS]")
452  {
453  INFO("Reading weirs...");
454  if (!readLinksAsPolylines(in, lines, line_names, points,
455  name_id_map))
456  {
457  BaseLib::cleanupVectorElements(points, lines);
458  return false;
459  }
460  }
461  }
462 
463  geo_objects.addPointVec(std::move(points), geo_name,
464  std::move(name_id_map));
465  if (!lines.empty())
466  {
467  if (lines.size() != line_names.size())
468  {
469  ERR("Length of line vector and line name vector do not match.");
470  geo_objects.removePointVec(geo_name);
471  for (auto ply : lines)
472  delete ply;
473  return false;
474  }
475  GeoLib::PolylineVec::NameIdMap line_id_map;
476  {
477  std::size_t const n_names(line_names.size());
478  for (std::size_t i = 0; i < n_names; ++i)
479  {
480  line_id_map.insert(std::make_pair(line_names[i], i));
481  }
482  }
483  std::vector<std::size_t> const& pnt_id_map(
484  geo_objects.getPointVecObj(geo_name)->getIDMap());
485  for (GeoLib::Polyline* polyline : lines)
486  {
487  for (std::size_t i = 0; i < polyline->getNumberOfPoints(); ++i)
488  {
489  polyline->setPointID(i, pnt_id_map[polyline->getPointID(i)]);
490  if (i > 0 &&
491  polyline->getPointID(i - 1) == polyline->getPointID(i))
492  {
493  polyline->removePoint(i);
494  i--;
495  }
496  }
497  if (polyline->getPointID(0) ==
498  polyline->getPointID(polyline->getNumberOfPoints() - 1))
499  {
500  polyline->removePoint(polyline->getNumberOfPoints() - 1);
501  polyline->addPoint(polyline->getPointID(0));
502  }
503  }
504  geo_objects.addPolylineVec(std::move(lines), geo_name,
505  std::move(line_id_map));
506  }
507  return true;
508 }
509 
511  std::ifstream& in, std::vector<MeshLib::Node*>& nodes,
512  std::map<std::string, std::size_t> const& name_id_map,
513  std::vector<double>& max_depth, bool read_max_depth)
514 {
515  std::string line;
516  while (std::getline(in, line))
517  {
518  if (isSectionFinished(line))
519  return true;
520 
521  if (isCommentLine(line))
522  continue;
523 
524  std::vector<std::string> const split_str(BaseLib::splitString(line));
525  // Junctions = 6, Outfalls = 4, Storage = 8
526  if (split_str.size() < 3)
527  {
528  ERR("Format not recognised.");
529  return false;
530  }
531  std::string const current_name(split_str[0]);
532  auto const it = name_id_map.find(current_name);
533  if (it == name_id_map.end())
534  {
535  ERR("SwmmInterface::readNodeData(): Name {:s} not found in "
536  "coordinates map.",
537  current_name);
538  return false;
539  }
540  std::size_t const id = it->second;
541  (*nodes[id])[2] = BaseLib::str2number<double>(split_str[1]);
542 
543  if (read_max_depth)
544  max_depth[id] = BaseLib::str2number<double>(split_str[2]);
545  else
546  max_depth[id] = 0;
547  }
548  return true;
549 }
550 
552  std::ifstream& in, std::vector<MeshLib::Element*>& elements,
553  std::vector<MeshLib::Node*> const& nodes,
554  std::map<std::string, std::size_t> const& name_id_map)
555 {
556  std::string line;
557  while (std::getline(in, line))
558  {
559  if (isSectionFinished(line))
560  return true;
561 
562  if (isCommentLine(line))
563  continue;
564 
565  std::vector<std::string> const split_str(BaseLib::splitString(line));
566  // Conduits = 9, Pumps = 7, Weirs = 8
567  if (split_str.size() < 7)
568  {
569  ERR("Conduit format not recognised.");
570  return false;
571  }
572 
573  std::string const inlet(split_str[1]);
574  auto const i_it = name_id_map.find(inlet);
575  if (i_it == name_id_map.end())
576  {
577  ERR("SwmmInterface::readLineElements(): Inlet node {:s} not found "
578  "in coordinates map.",
579  inlet);
580  return false;
581  }
582 
583  std::string const outlet(split_str[2]);
584  auto const o_it = name_id_map.find(outlet);
585  if (o_it == name_id_map.end())
586  {
587  ERR("SwmmInterface::readLineElements(): Outlet node {:s} not found "
588  "in coordinates map.",
589  outlet);
590  return false;
591  }
592 
593  std::array<MeshLib::Node*, 2> const line_nodes = {nodes[i_it->second],
594  nodes[o_it->second]};
595  elements.push_back(new MeshLib::Line(line_nodes));
596  _id_linkname_map.push_back(split_str[0]);
597  }
598  return true;
599 }
600 
602  std::ifstream& in, std::map<std::string, std::size_t> const& name_id_map)
603 {
604  std::string line;
605  while (getline(in, line))
606  {
607  if (isSectionFinished(line))
608  return true;
609 
610  if (isCommentLine(line))
611  continue;
612 
613  std::vector<std::string> const split_str(BaseLib::splitString(line));
614  if (split_str.size() < 8)
615  {
616  ERR("Subcatchment format not recognised.");
617  return false;
618  }
619 
620  Subcatchment sc;
621  sc.name = split_str[0];
622  sc.rain_gauge = std::numeric_limits<std::size_t>::max();
623  std::size_t const n_gauges(_rain_gauges.size());
624  for (std::size_t i = 0; i < n_gauges; ++i)
625  {
626  if (_rain_gauges[i].first.getName() == split_str[1])
627  {
628  sc.rain_gauge = i;
629  break;
630  }
631  }
632  if (sc.rain_gauge == std::numeric_limits<std::size_t>::max())
633  {
634  ERR("Rain gauge for subcatchment '{:s}' not found.", split_str[0]);
635  return false;
636  }
637 
638  auto const it = name_id_map.find(split_str[2]);
639  if (it == name_id_map.end())
640  {
641  ERR("Outlet node for subcatchment '{:s}' not found.", split_str[0]);
642  return false;
643  }
644  sc.outlet = it->second;
645  sc.area = BaseLib::str2number<double>(split_str[3]);
646  _subcatchments.push_back(sc);
647  }
648 
649  return true;
650 }
651 
653 {
654  if (_mesh != nullptr)
655  {
656  ERR("Mesh already exists.");
657  return false;
658  }
659 
660  std::string const inp_file_name(_base_name + ".inp");
661  if (!isSwmmInputFile(inp_file_name))
662  return false;
663 
664  std::ifstream in(inp_file_name.c_str());
665  if (!in.is_open())
666  {
667  ERR("SWMMInterface: Could not open input file {:s}.", inp_file_name);
668  return false;
669  }
670 
671  _id_nodename_map.clear();
672  std::vector<MeshLib::Node*> nodes;
673  std::string line;
674  while (getline(in, line))
675  {
676  if (line == "[COORDINATES]")
677  {
678  INFO("Reading coordinates...");
679  if (!readCoordinates<MeshLib::Node>(in, nodes, _id_nodename_map))
680  return false;
681  }
682  /* TODO: check if needed
683  else if (line == "[VERTICES]")
684  {
685  INFO ("Reading vertices...");
686  if (!readCoordinates(in, nodes, _id_nodename_map))
687  return false;
688  }
689  */
690  else if (line == "[SYMBOLS]")
691  {
692  INFO("Reading symbols...");
693  std::vector<GeoLib::Point*> points;
694  std::vector<std::string> names;
695  if (!readCoordinates(in, points, names))
696  return false;
697  for (std::size_t i = 0; i < points.size(); ++i)
698  {
699  GeoLib::Station stn(points[i], names[i]);
700  _rain_gauges.push_back(
701  std::pair<GeoLib::Station, std::string>(stn, ""));
702  }
703  }
704  }
705 
706  if (nodes.empty())
707  return false;
708 
709  // After end of file is reached, create name-id-map and
710  // start reading again to get line elements and node data.
711  std::map<std::string, std::size_t> name_id_map;
712  std::size_t const n_nodes(nodes.size());
713  for (std::size_t i = 0; i < n_nodes; ++i)
714  name_id_map[_id_nodename_map[i]] = i;
715  in.clear();
716  in.seekg(0, in.beg);
717 
718  std::vector<MeshLib::Element*> elements;
719  std::vector<double> max_depth(n_nodes);
720  std::size_t const n_types = 3;
721  std::array<std::size_t, n_types> n_elem_types{{0, 0, 0}};
722  while (getline(in, line))
723  {
724  if (line == "[RAINGAGES]")
725  {
726  if (!_rain_gauges.empty())
728  }
729  else if (line == "[SUBCATCHMENTS]")
730  {
731  INFO("Reading subcatchment information...");
732  if (!readSubcatchments(in, name_id_map))
733  return false;
734  }
735  else if (line == "[SUBAREAS]")
736  {
737  // more subcatchment variables, not yet implemented
738  }
739  else if (line == "[INFILTRATION]")
740  {
741  // more subcatchment variables, not yet implemented
742  }
743  else if (line == "[JUNCTIONS]")
744  {
745  INFO("Reading junctions...");
746  if (!readNodeData(in, nodes, name_id_map, max_depth, true))
747  return false;
748  }
749  else if (line == "[OUTFALLS]")
750  {
751  INFO("Reading outfalls...");
752  if (!readNodeData(in, nodes, name_id_map, max_depth, false))
753  return false;
754  }
755  else if (line == "[STORAGE]")
756  {
757  INFO("Reading storages...");
758  if (!readNodeData(in, nodes, name_id_map, max_depth, true))
759  return false;
760  }
761  else if (line == "[CONDUITS]")
762  {
763  INFO("Reading conduits...");
764  if (!readLineElements(in, elements, nodes, name_id_map))
765  return false;
766  n_elem_types[0] = elements.size();
767  }
768  else if (line == "[PUMPS]")
769  {
770  INFO("Reading pumps...");
771  if (!readLineElements(in, elements, nodes, name_id_map))
772  return false;
773  n_elem_types[1] = elements.size();
774  }
775  else if (line == "[WEIRS]")
776  {
777  INFO("Reading weirs...");
778  if (!readLineElements(in, elements, nodes, name_id_map))
779  return false;
780  n_elem_types[2] = elements.size();
781  }
782  else if (line == "[POLLUTANTS]")
783  {
784  if (!readPollutants(in))
785  return false;
786  }
787  else if (line == "[Polygons]")
788  {
789  INFO("Reading subcatchments...");
790  std::vector<GeoLib::Polyline*> lines;
791  std::vector<std::string> line_names;
792  std::vector<std::string>
793  tmp_names; // polygon points are nameless but the method
794  // requires a vector
795  if (!readPolygons(in, lines, line_names, _subcatchment_points,
796  tmp_names))
797  return false;
798 
799  if (!matchSubcatchmentsWithPolygons(lines, line_names))
800  return false;
801  }
802  }
803 
804  if (elements.empty())
805  {
806  for (MeshLib::Node* node : nodes)
807  delete node;
808  return false;
809  }
810 
811  MeshLib::Properties props;
812  auto* const mat_ids = props.createNewPropertyVector<int>(
813  "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
814  mat_ids->resize(elements.size(), 0);
815  for (std::size_t i = 1; i < n_types; ++i)
816  {
817  if (n_elem_types[i] > 0)
818  std::fill(mat_ids->begin() + n_elem_types[i - 1],
819  mat_ids->begin() + n_elem_types[i], i);
820  }
821 
822  if (nodes.size() == max_depth.size())
823  {
824  auto* const depth = props.createNewPropertyVector<double>(
825  "Max Depth", MeshLib::MeshItemType::Node, 1);
826  depth->reserve(max_depth.size());
827  std::copy(max_depth.cbegin(), max_depth.cend(),
828  std::back_inserter(*depth));
829  }
830  else
831  ERR("Size of max depth array does not fit number of elements. Skipping "
832  "array.");
833 
834  _mesh.reset(new MeshLib::Mesh(_base_name, nodes, elements, props));
835  return true;
836 }
837 
839  std::vector<GeoLib::Polyline*> const& lines,
840  std::vector<std::string> const& names)
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 }
870 
871 std::vector<std::string> SwmmInterface::getSubcatchmentNameMap() const
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 }
880 
881 std::vector<std::string> SwmmInterface::getNames(SwmmObject obj_type) const
882 {
883  switch (obj_type)
884  {
885  case SwmmObject::NODE:
886  return _id_nodename_map;
887  case SwmmObject::LINK:
888  return _id_linkname_map;
890  return getSubcatchmentNameMap();
891  case SwmmObject::SYSTEM:
892  std::vector<std::string> system_name{"System"};
893  return system_name;
894  }
895  ERR("Object type has no name map");
896  std::vector<std::string> empty_vec;
897  return empty_vec;
898 }
899 
900 std::string SwmmInterface::getName(SwmmObject obj_type, std::size_t idx) const
901 {
902  switch (obj_type)
903  {
904  case SwmmObject::NODE:
905  if (idx < _id_nodename_map.size())
906  return _id_nodename_map[idx];
907  case SwmmObject::LINK:
908  if (idx < _id_linkname_map.size())
909  return _id_linkname_map[idx];
911  if (idx < _subcatchments.size())
912  return _subcatchments[idx].name;
913  case SwmmObject::SYSTEM:
914  if (idx == 0)
915  return std::string("System");
916  }
917  ERR("Index out of bounds.");
918  return std::string("");
919 }
920 
922 {
923  std::string const outfile(_base_name + ".out");
924  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
925  return 0;
926 
927  switch (obj_type)
928  {
930  return SWMM_Nsubcatch;
931  case SwmmObject::NODE:
932  return SWMM_Nnodes;
933  case SwmmObject::LINK:
934  return SWMM_Nlinks;
935  case SwmmObject::SYSTEM:
936  return 1;
937  default:
938  ERR("Object type not recognised.");
939  }
940  CloseSwmmOutFile();
941  return 0;
942 }
943 
945 {
946  std::string const outfile(_base_name + ".out");
947  std::size_t n_time_steps(std::numeric_limits<std::size_t>::max());
948  if (OpenSwmmOutFile(const_cast<char*>(outfile.c_str())) != 0)
949  return 0;
950 
951  std::size_t n_params(0);
952  switch (obj_type)
953  {
955  n_params = n_obj_params[0] + SWMM_Npolluts;
956  break;
957  case SwmmObject::NODE:
958  n_params = n_obj_params[1] + SWMM_Npolluts;
959  break;
960  case SwmmObject::LINK:
961  n_params = n_obj_params[2] + SWMM_Npolluts;
962  break;
963  case SwmmObject::SYSTEM:
964  n_params = n_obj_params[3];
965  break;
966  default:
967  ERR("Object type not recognised.");
968  }
969  CloseSwmmOutFile();
970  return n_params;
971 }
972 
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 }
982 
984  SwmmObject const swmm_type,
985  std::string const& vec_name,
986  std::vector<double> const& data)
987 {
988  if (!(swmm_type == SwmmObject::NODE || swmm_type == SwmmObject::LINK))
989  {
990  ERR("Information of this object type cannot be added to mesh.");
991  return false;
992  }
993 
994  if (data.empty())
995  {
996  ERR("Data array is empty and cannot be added to mesh.");
997  return false;
998  }
999 
1000  if (swmm_type == SwmmObject::NODE && data.size() != mesh.getNumberOfNodes())
1001  {
1002  ERR("Number of mesh nodes ({:d}) does not match length of array "
1003  "({:d}).",
1004  mesh.getNumberOfNodes(), data.size());
1005  return false;
1006  }
1007 
1008  if (swmm_type == SwmmObject::LINK &&
1009  data.size() != mesh.getNumberOfElements())
1010  {
1011  ERR("Number of mesh elements ({:d}) does not match length of array "
1012  "({:d}).",
1013  mesh.getNumberOfElements(), data.size());
1014  return false;
1015  }
1016 
1017  MeshLib::MeshItemType const item_type = (swmm_type == SwmmObject::NODE)
1021  MeshLib::getOrCreateMeshProperty<double>(mesh, vec_name, item_type, 1);
1022  if (!prop)
1023  {
1024  ERR("Error fetching array '{:s}'.", vec_name);
1025  return false;
1026  }
1027  std::copy(data.cbegin(), data.cend(), prop->begin());
1028  return true;
1029 }
1030 
1031 std::vector<double> SwmmInterface::getArrayAtTimeStep(SwmmObject obj_type,
1032  std::size_t time_step,
1033  std::size_t var_idx) const
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 }
1102 
1103 std::vector<double> SwmmInterface::getArrayForObject(SwmmObject obj_type,
1104  std::size_t obj_idx,
1105  std::size_t var_idx) const
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 }
1176 
1178  std::size_t var_idx) const
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 }
1188 
1190  std::size_t var_idx,
1191  std::size_t n_pollutants) const
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 }
1223 
1225 {
1226  std::string line;
1227  while (getline(in, line))
1228  {
1229  if (isSectionFinished(line))
1230  break;
1231 
1232  if (isCommentLine(line))
1233  continue;
1234 
1235  std::vector<std::string> const split_str(BaseLib::splitString(line));
1236  if (split_str.size() < 6)
1237  {
1238  ERR("Rain gauge parameter format not recognised.");
1239  return false;
1240  }
1241 
1242  for (auto& stn : _rain_gauges)
1243  {
1244  if (stn.first.getName() == split_str[0] && split_str[4] == "FILE")
1245  stn.second = split_str[5].substr(1, split_str[5].size() - 2);
1246  }
1247  }
1248 
1249  for (auto const& stn : _rain_gauges)
1250  if (stn.second.empty())
1251  WARN("No associated time series found for rain gauge '{:s}'.",
1252  stn.first.getName());
1253  return true;
1254 }
1255 
1256 bool SwmmInterface::readPollutants(std::ifstream& in)
1257 {
1258  std::string line;
1259  while (getline(in, line))
1260  {
1261  if (isSectionFinished(line))
1262  return true;
1263 
1264  if (isCommentLine(line))
1265  continue;
1266 
1267  std::vector<std::string> split_str(BaseLib::splitString(line));
1268  if (split_str.size() < 6)
1269  {
1270  ERR("Parameter format for pollutants not recognised.");
1271  return false;
1272  }
1273  _pollutant_names.push_back(split_str[0]);
1274  }
1275  return true;
1276 }
1277 
1278 bool SwmmInterface::isSectionFinished(std::string const& str)
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 }
1289 
1290 bool SwmmInterface::isCommentLine(std::string const& str)
1291 {
1292  return (str.compare(str.find_first_not_of(' ', 0), 1, ";") == 0);
1293 }
1294 
1295 bool SwmmInterface::getNodeCoordinateVectors(std::vector<double>& x,
1296  std::vector<double>& y,
1297  std::vector<double>& z) const
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 }
1308 
1309 bool SwmmInterface::getLinkPointIds(std::vector<std::size_t>& inlets,
1310  std::vector<std::size_t>& outlets) const
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 }
1325 
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 }
1338 
1339 bool SwmmInterface::writeCsvForTimestep(std::string const& file_name,
1340  SwmmObject obj_type,
1341  std::size_t time_step) const
1342 {
1345  csv.addVectorForWriting("Name", getNames(obj_type));
1346  std::size_t const n_params(getNumberOfParameters(obj_type));
1347  for (std::size_t i = 0; i < n_params; ++i)
1348  {
1349  std::vector<double> data = getArrayAtTimeStep(obj_type, time_step, i);
1350  if (!data.empty())
1351  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1352  }
1353  if (csv.getNArrays() < 2)
1354  {
1355  ERR("No data to write");
1356  return false;
1357  }
1359  return true;
1360 }
1361 
1362 bool SwmmInterface::writeCsvForObject(std::string const& file_name,
1363  SwmmObject obj_type,
1364  std::size_t obj_idx) const
1365 {
1367  INFO("Writing data for {:s} {:d}.", swmmObjectTypeToString(obj_type),
1368  obj_idx);
1370  std::size_t const n_params(getNumberOfParameters(obj_type));
1371  for (std::size_t i = 0; i < n_params; ++i)
1372  {
1373  std::vector<double> data = getArrayForObject(obj_type, obj_idx, i);
1374  if (!data.empty())
1375  csv.addVectorForWriting<double>(getArrayName(obj_type, i), data);
1376  }
1377  if (csv.getNArrays() < 2)
1378  {
1379  ERR("No data to write");
1380  return false;
1381  }
1383  return true;
1384 }
1385 
1386 } // 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
void addPolylineVec(std::vector< Polyline * > &&lines, std::string const &name, PolylineVec::NameIdMap &&ply_names)
Definition: GEOObjects.cpp:152
void addPointVec(std::vector< Point * > &&points, std::string &name, PointVec::NameIdMap &&pnt_id_name_map, double const eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Definition: GEOObjects.cpp:47
const PointVec * getPointVecObj(const std::string &name) const
Definition: GEOObjects.cpp:85
bool removePointVec(const std::string &name)
Definition: GEOObjects.cpp:98
const std::vector< std::size_t > & getIDMap() const
Definition: PointVec.h:96
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition: Polyline.h:53
virtual bool addPoint(std::size_t pnt_id)
Definition: Polyline.cpp:35
A Station (observation site) is basically a Point with some additional information.
Definition: Station.h:37
std::map< std::string, std::size_t > NameIdMap
Definition: TemplateVec.h:44
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
void cleanupVectorElements(std::vector< T * > &items)
Definition: Algorithm.h:300
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
std::vector< std::string > splitString(std::string const &str)
Definition: StringTools.cpp:28
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