21 package org.matsim.core.mobsim.qsim.qnetsimengine;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
62 private NetsimInternalInterface ii =
new NetsimInternalInterface(){
63 @Override
public QNetwork getNetsimNetwork() {
66 @Override
public void arrangeNextAgentState(MobsimAgent driver) {
67 AbstractQNetsimEngine.this.arrangeNextAgentState(driver);
69 @Override
public void letVehicleArrive(QVehicle veh) {
70 AbstractQNetsimEngine.this.letVehicleArrive( veh ) ;
74 private static final Logger log = LogManager.getLogger(AbstractQNetsimEngine.class);
75 private static final int INFO_PERIOD = 3600;
78 public static int numObservedTimeSteps = 24*3600;
79 public static boolean printRunTimesPerTimeStep =
false;
81 private final Map<Id<Vehicle>, QVehicle> vehicles =
new HashMap<>();
82 private final QSim qsim;
85 protected final int numOfThreads;
86 protected final QNetwork qNetwork;
88 private double infoTime = 0;
89 private List<A> engines;
90 private InternalInterface internalInterface = null;
92 AbstractQNetsimEngine(
final QSim sim, QNetworkFactory netsimNetworkFactory, NetworkModeDepartureHandler dpHandler) {
93 if ( netsimNetworkFactory==null ) {
94 throw new RuntimeException(
"this execution path is no longer allowed; network factory needs to come from elsewhere (in general via injection). kai, jun'23" );
99 final Config config = sim.getScenario().getConfig();
100 final QSimConfigGroup qSimConfigGroup = config.qsim();
113 if(qSimConfigGroup.getLinkDynamics().equals(LinkDynamics.SeepageQ)) {
114 log.info(
"Seepage is allowed. Seep mode(s) is(are) " + qSimConfigGroup.getSeepModes() +
".");
115 if(qSimConfigGroup.isSeepModeStorageFree()) {
116 log.warn(
"Seep mode(s) " + qSimConfigGroup.getSeepModes() +
" does not take storage space thus only considered for flow capacities.");
120 qNetwork =
new QNetwork( sim.getScenario().getNetwork(), netsimNetworkFactory ) ;
122 qNetwork.initialize(
this, sim.getAgentCounter(), sim.getSimTimer() );
125 this.numOfThreads = sim.getScenario().getConfig().qsim().getNumberOfThreads();
128 static AbstractAgentSnapshotInfoBuilder createAgentSnapshotInfoBuilder(Scenario scenario, SnapshotLinkWidthCalculator linkWidthCalculator) {
129 final SnapshotStyle snapshotStyle = scenario.getConfig().qsim().getSnapshotStyle();
130 switch(snapshotStyle) {
132 return new QueueAgentSnapshotInfoBuilder(scenario, linkWidthCalculator);
134 case withHolesAndShowHoles:
137 return new QueueAgentSnapshotInfoBuilder(scenario, linkWidthCalculator);
139 log.warn(
"The snapshotStyle \"" + snapshotStyle +
"\" is not explicitly supported. Using \""+SnapshotStyle.withHoles+
"\" instead.");
140 return new QueueAgentSnapshotInfoBuilder(scenario, linkWidthCalculator);
142 return new EquiDistAgentSnapshotInfoBuilder(scenario, linkWidthCalculator);
144 log.warn(
"The snapshotStyle \"" + snapshotStyle +
"\" is not supported. Using equiDist");
145 return new EquiDistAgentSnapshotInfoBuilder(scenario, linkWidthCalculator);
150 public final void onPrepareSim() {
151 this.infoTime = Math.floor(internalInterface.getMobsim().getSimTimer().getSimStartTime() / INFO_PERIOD) * INFO_PERIOD;
154 this.engines = initQSimEngineRunners();
155 assignNetElementActivators();
156 initMultiThreading();
162 protected abstract void initMultiThreading();
166 public final void afterSim() {
176 finishMultiThreading();
183 for (QLinkI link : qNetwork.getNetsimLinks().values()) {
184 link.clearVehicles();
191 protected abstract void finishMultiThreading();
199 protected abstract void run(
double time);
206 protected abstract List<A> initQSimEngineRunners() ;
213 public final void doSimStep(
final double time) {
216 this.printSimLog(time);
221 public final void setInternalInterface( InternalInterface internalInterface) {
222 this.internalInterface = internalInterface;
225 private static int wrnCnt = 0;
227 public final void addParkedVehicle(MobsimVehicle veh, Id<Link> startLinkId) {
228 if (this.vehicles.put(veh.getId(), (QVehicle) veh) != null) {
231 log.warn(
"existing vehicle in mobsim was just overwritten by other vehicle with same ID. Not clear what this means. Continuing anyways ...") ;
232 log.warn(Gbl.ONLYONCE);
235 QLinkI qlink = qNetwork.getNetsimLinks().get(startLinkId );
237 throw new RuntimeException(
"requested link with id=" + startLinkId +
" does not exist in network. Possible vehicles " 238 +
"or activities or facilities are registered to a different network.") ;
240 qlink.addParkedVehicle(veh);
243 public final int getNumberOfSimulatedLinks() {
248 numLinks = numLinks + engine.getNumberOfSimulatedLinks();
254 public final int getNumberOfSimulatedNodes() {
259 numNodes = numNodes + engine.getNumberOfSimulatedNodes();
265 public final NetsimNetwork getNetsimNetwork() {
267 return this.qNetwork;
275 public final Map<Id<Vehicle>, QVehicle> getVehicles() {
276 return Collections.unmodifiableMap(this.vehicles);
279 public final void registerAdditionalAgentOnLink(
final MobsimAgent planAgent) {
280 Id<Link> linkId = planAgent.getCurrentLinkId();
281 if (linkId != null) {
282 QLinkI qLink = this.qNetwork.getNetsimLink(linkId );
284 throw new RuntimeException(
"netsim link lookup failed; agentId=" + planAgent.getId() +
"; linkId=" + linkId ) ;
286 qLink.registerAdditionalAgentOnLink(planAgent);
290 public final MobsimAgent unregisterAdditionalAgentOnLink(Id<Person> agentId, Id<Link> linkId) {
291 if (linkId == null) {
294 QLinkI qLink = this.qNetwork.getNetsimLink(linkId );
295 return qLink.unregisterAdditionalAgentOnLink(agentId);
298 public final void printEngineRunTimes() {
299 if (!QSim.analyzeRunTimes)
return;
301 if (printRunTimesPerTimeStep) log.info(
"detailed QNetsimEngineRunner run times per time step:");
303 StringBuffer sb =
new StringBuffer();
306 for (
int i = 0; i < this.engines.size(); i++) {
308 sb.append(
"thread_");
309 sb.append(Integer.toString(i));
315 if (printRunTimesPerTimeStep) log.info(sb.toString());
320 for (
int i = 0; i < numObservedTimeSteps; i++) {
321 StringBuffer sb =
new StringBuffer();
323 long min = Long.MAX_VALUE;
324 long max = Long.MIN_VALUE;
326 long runTime = runner.runTimes[i];
328 if (runTime < min) min = runTime;
329 if (runTime > max) max = runTime;
331 sb.append(Long.toString(runTime));
334 sb.append(Long.toString(min));
336 sb.append(Long.toString(max));
337 if (printRunTimesPerTimeStep) log.info(sb.toString());
341 log.info(
"sum min run times: " + sumMin);
342 log.info(
"sum max run times: " + sumMax);
343 log.info(
"sum all run times / num threads: " + sum / this.numOfThreads);
347 public final NetsimInternalInterface getNetsimInternalInterface() {
351 private final void printSimLog(
double time) {
352 if (time >= this.infoTime) {
353 this.infoTime += INFO_PERIOD;
354 int nofActiveLinks = this.getNumberOfSimulatedLinks();
355 int nofActiveNodes = this.getNumberOfSimulatedNodes();
356 log.info(
"SIMULATION (QNetsimEngine) AT " + Time.writeTime(time)
357 +
" : #links=" + nofActiveLinks
358 +
" #nodes=" + nofActiveNodes);
362 private void letVehicleArrive(QVehicle veh) {
363 double now = this.qsim.getSimTimer().getTimeOfDay();
364 MobsimDriverAgent driver = veh.getDriver();
365 this.qsim.getEventsManager().processEvent(
new PersonLeavesVehicleEvent(now, driver.getId(), veh.getId()));
368 driver.endLegAndComputeNextState(now);
369 this.internalInterface.arrangeNextAgentState(driver);
377 private void assignNetElementActivators() {
380 int nodes[] =
new int[this.engines.size()];
381 int links[] =
new int[this.engines.size()];
384 for (QNodeI node : qNetwork.getNetsimNodes().values()) {
385 int i = roundRobin % this.engines.size();
386 if( node instanceof AbstractQNode){
387 ((AbstractQNode) node).setNetElementActivationRegistry(this.engines.get(i));
392 for (Link outLink : node.getNode().getOutLinks().values()) {
393 AbstractQLink qLink = (AbstractQLink) qNetwork.getNetsimLink(outLink.getId() );
397 qLink.setNetElementActivationRegistry(this.engines.get(i));
417 for (
int i = 0; i < this.engines.size(); i++) {
418 log.info(
"Assigned " + nodes[i] +
" nodes and " + links[i] +
" links to QSimEngineRunner #" + i);
424 private final void arrangeNextAgentState(MobsimAgent pp) {
425 internalInterface.arrangeNextAgentState(pp);
431 protected List<A> getQnetsimEngineRunner(){