@@ -310,6 +310,23 @@ namespace dsm {
310310 // / @param filename The name of the file
311311 // / @param reset If true, the travel speeds are cleared after the computation
312312 void saveTravelSpeeds (const std::string& filename, bool reset = false );
313+ // / @brief Save the main macroscopic observables in csv format
314+ // / @param filename The name of the file
315+ // / @param separator The separator character (default is ';')
316+ // / @details The file contains the following columns:
317+ // / - time: the time of the simulation
318+ // / - n_agents: the number of agents currently in the simulation
319+ // / - mean_speed - mean_speed_std: the mean speed of the agents
320+ // / - mean_density - mean_density_std: the (normalized) mean density of the streets
321+ // / - mean_flow - mean_flow_std: the mean flow of the streets
322+ // / - mean_flow_spires - mean_flow_spires_std: the mean flow of the spires
323+ // / - mean_traveltime - mean_traveltime_std: the mean travel time of the agents
324+ // / - mean_traveldistance - mean_traveldistance_err: the mean travel distance of the agents
325+ // / - mean_travelspeed - mean_travelspeed_std: the mean travel speed of the agents
326+ // /
327+ // / NOTE: the mean density is normalized in [0, 1] and reset is true for all observables which have such parameter
328+ void saveMacroscopicObservables (const std::string& filename,
329+ char const separator = ' ;' );
313330 };
314331
315332 template <typename delay_t >
@@ -1567,4 +1584,70 @@ namespace dsm {
15671584 m_travelDTs.clear ();
15681585 }
15691586 }
1587+ template <typename delay_t >
1588+ requires (is_numeric_v<delay_t >)
1589+ void RoadDynamics<delay_t >::saveMacroscopicObservables(const std::string& filename,
1590+ char const separator) {
1591+ bool bEmptyFile{false };
1592+ {
1593+ std::ifstream file (filename);
1594+ bEmptyFile = file.peek () == std::ifstream::traits_type::eof ();
1595+ }
1596+ std::ofstream file (filename, std::ios::app);
1597+ if (!file.is_open ()) {
1598+ Logger::error (std::format (" Error opening file \" {}\" for writing." , filename));
1599+ }
1600+ if (bEmptyFile) {
1601+ file << " time;n_agents;mean_speed;mean_speed_std;mean_density;mean_density_std;"
1602+ " mean_flow;mean_flow_std;mean_flow_spires;mean_flow_spires_std;mean_"
1603+ " traveltime;mean_traveltime_std;mean_traveldistance;mean_traveldistance_"
1604+ " err;mean_travelspeed;mean_travelspeed_std\n " ;
1605+ }
1606+ file << this ->time () << separator;
1607+ file << m_agents.size () << separator;
1608+ file << std::scientific << std::setprecision (2 );
1609+ {
1610+ std::vector<double > speeds, densities, flows, spireFlows;
1611+ speeds.reserve (this ->graph ().nEdges ());
1612+ densities.reserve (this ->graph ().nEdges ());
1613+ flows.reserve (this ->graph ().nEdges ());
1614+ spireFlows.reserve (this ->graph ().nEdges ());
1615+ for (auto const & [streetId, street] : this ->graph ().edges ()) {
1616+ speeds.push_back (this ->streetMeanSpeed (streetId));
1617+ densities.push_back (street->density (true ));
1618+ flows.push_back (street->density (true ) * speeds.back ());
1619+ if (street->isSpire ()) {
1620+ auto & spire = dynamic_cast <SpireStreet&>(*street);
1621+ spireFlows.push_back (static_cast <double >(spire.inputCounts (true )) /
1622+ (this ->time () - m_previousSpireTime));
1623+ }
1624+ }
1625+ auto speed{Measurement<double >(speeds)};
1626+ auto density{Measurement<double >(densities)};
1627+ auto flow{Measurement<double >(flows)};
1628+ auto spireFlow{Measurement<double >(spireFlows)};
1629+ file << speed.mean << separator << speed.std << separator;
1630+ file << density.mean << separator << density.std << separator;
1631+ file << flow.mean << separator << flow.std << separator;
1632+ file << spireFlow.mean << separator << spireFlow.std << separator;
1633+ }
1634+ {
1635+ std::vector<double > distances, times, speeds;
1636+ distances.reserve (m_travelDTs.size ());
1637+ times.reserve (m_travelDTs.size ());
1638+ speeds.reserve (m_travelDTs.size ());
1639+ for (auto const & [distance, time] : m_travelDTs) {
1640+ distances.push_back (distance);
1641+ times.push_back (time);
1642+ speeds.push_back (distance / time);
1643+ }
1644+ auto distance{Measurement<double >(distances)};
1645+ auto time{Measurement<double >(times)};
1646+ auto speed{Measurement<double >(speeds)};
1647+ file << distance.mean << separator << distance.std << separator;
1648+ file << time.mean << separator << time.std << separator;
1649+ file << speed.mean << separator << speed.std << std::endl;
1650+ }
1651+ file.close ();
1652+ }
15701653}; // namespace dsm
0 commit comments