diff --git a/Simulation.cpp b/Simulation.cpp
index f4979881d4780e193b2d291ab6014db96ece296e..fe6d6fd2f314490662f20886df93e3c352ea1bad 100644
--- a/Simulation.cpp
+++ b/Simulation.cpp
@@ -420,7 +420,6 @@ void Simulation::RunHeader(long nPed)
 
     //first initialisation needed by the linked-cells
     UpdateRoutesAndLocations();
-    _routingEngine.get()->PrepareForSimulation(_building.get());
     ProcessAgentsQueue();
 }
 
diff --git a/math/GradientModel.cpp b/math/GradientModel.cpp
index 1aa8411513ad96d26b2c74b8dd455b5169e496a6..8c4d186288251f388a4e7eae2454ce7d404c7513 100644
--- a/math/GradientModel.cpp
+++ b/math/GradientModel.cpp
@@ -120,6 +120,7 @@ bool GradientModel::Init (Building* building)
 
      std::set<std::pair<int, int>> roomsDoorsSet;
      roomsDoorsSet.clear();
+     // @todo f.mack parallelize? yes, using pedsToRemove should be fine
     for(unsigned int p=0;p<allPeds.size();p++) {
          Pedestrian* ped = allPeds[p];
          double cosPhi, sinPhi;
@@ -165,16 +166,23 @@ bool GradientModel::Init (Building* building)
           std::map<int, std::vector<int>> doorsInRoom;
           doorsInRoom.clear();
           Log->Write("####### The GradientModel is using DirectionLocalFloorfield");
-          // parallelize
-          for (size_t i = 0; i < roomsDoorsSet.size(); ++i) {
-               auto rdIt = roomsDoorsSet.begin();
-               // suboptimal, because a set doesn't provide random-access iterators
-               std::advance(rdIt, i);
-               dirLocff->CalcFloorfield(rdIt->first, rdIt->second);
-               doorsInRoom[rdIt->first].push_back(rdIt->second);
-          }
-          for (auto roomIt : doorsInRoom) {
-               dirLocff->writeFF(roomIt.first, roomIt.second);
+#pragma omp parallel
+          {
+#pragma omp for
+               for (size_t i = 0; i < roomsDoorsSet.size(); ++i) {
+                    auto rdIt = roomsDoorsSet.begin();
+                    // suboptimal, because a set doesn't provide random-access iterators
+                    std::advance(rdIt, i);
+                    dirLocff->CalcFloorfield(rdIt->first, rdIt->second);
+#pragma omp critical(doorsInRoom)
+                    doorsInRoom[rdIt->first].push_back(rdIt->second);
+               }
+#pragma omp for
+               for (size_t i = 0; i < doorsInRoom.size(); ++i) {
+                   auto roomIt = doorsInRoom.begin();
+                   std::advance(roomIt, i);
+                   dirLocff->writeFF(roomIt->first, roomIt->second);
+               }
           }
      }
     return true;
diff --git a/routing/CognitiveMapRouter.cpp b/routing/CognitiveMapRouter.cpp
index 42896c94d16423153eaec97be1b4d59cf1bbafba..dab55db51378e1175c41ab96a3bcbd12b5f37705 100644
--- a/routing/CognitiveMapRouter.cpp
+++ b/routing/CognitiveMapRouter.cpp
@@ -165,10 +165,6 @@ bool CognitiveMapRouter::Init(Building * b)
      return true;
 }
 
-void CognitiveMapRouter::PrepareForSimulation(Building *b) {
-    (void) b;
-}
-
 const optStorage &CognitiveMapRouter::getOptions() const
 {
     return options;
diff --git a/routing/CognitiveMapRouter.h b/routing/CognitiveMapRouter.h
index 942f28cf8dadb27ae93e63f399993cee18528cce..dc4a029430fc743c85ed69a2f434d185106b2fc5 100644
--- a/routing/CognitiveMapRouter.h
+++ b/routing/CognitiveMapRouter.h
@@ -60,7 +60,6 @@ public:
 
      virtual int FindExit(Pedestrian* p);
      virtual bool Init(Building* b);
-     virtual void PrepareForSimulation(Building* b);
 
      /**
       * @return options involved in the routing algorithm
diff --git a/routing/DirectionStrategy.cpp b/routing/DirectionStrategy.cpp
index c3112e8cb53f1c9963fd2d6d409a6a14ae41ed23..9ef574b7a7fff4120e99d60c1c6a43e3f650a798 100644
--- a/routing/DirectionStrategy.cpp
+++ b/routing/DirectionStrategy.cpp
@@ -484,7 +484,12 @@ void DirectionLocalFloorfield::CalcFloorfield(int room, int destUID) {
 
 void DirectionLocalFloorfield::writeFF(int room, std::vector<int> targets) {
      std::string lfilename = "floorfield" + std::to_string(room) + ".vtk";
+    std::chrono::time_point<std::chrono::system_clock> start, end;
+    start = std::chrono::system_clock::now();
      locffviafm[room]->writeFF(lfilename, targets);
+    end = std::chrono::system_clock::now();
+    std::chrono::duration<double> elapsed_seconds = end-start;
+    Log->Write("INFO: \twriting %s took %f s ", lfilename.c_str(), elapsed_seconds.count());
 }
 
 DirectionLocalFloorfield::DirectionLocalFloorfield() {
diff --git a/routing/DummyRouter.cpp b/routing/DummyRouter.cpp
index 8bdd7dc0ce5388d8971f3a6e8e431dfc9f7c5f69..2d3a01f34c2bdda6752ef6765932921843280714 100644
--- a/routing/DummyRouter.cpp
+++ b/routing/DummyRouter.cpp
@@ -75,6 +75,3 @@ bool DummyRouter::Init(Building* b)
      return true;
 }
 
-void DummyRouter::PrepareForSimulation(Building* b) {
-     (void) b;
-}
diff --git a/routing/DummyRouter.h b/routing/DummyRouter.h
index 1e5767afb013f9ccd99c7518479e23469b66cc2f..407d54962491d35b16979748e6272edc006f6c8c 100644
--- a/routing/DummyRouter.h
+++ b/routing/DummyRouter.h
@@ -44,7 +44,6 @@ public:
 
      virtual int FindExit(Pedestrian* p);
      virtual bool Init(Building* b);
-     virtual void PrepareForSimulation(Building* b);
 
 };
 
diff --git a/routing/GlobalRouter.cpp b/routing/GlobalRouter.cpp
index 61d848d26bb4fff868e74657493ca35e947fef52..444d49b7e54bc84c157e757f3c0a52c5f7cbef4e 100644
--- a/routing/GlobalRouter.cpp
+++ b/routing/GlobalRouter.cpp
@@ -547,9 +547,6 @@ void GlobalRouter::Reset(){
      _mapIdToFinalDestination.clear();
 }
 
-void GlobalRouter::PrepareForSimulation(Building* b) {
-     (void) b;
-}
 
 void GlobalRouter::SetEdgeCost(double cost)
 {
diff --git a/routing/GlobalRouter.h b/routing/GlobalRouter.h
index 0109283a2704a1832fd78774ee1242b3904e228f..f2c9f9f65694c276a028b1e2788dbe7838d47b1b 100644
--- a/routing/GlobalRouter.h
+++ b/routing/GlobalRouter.h
@@ -65,8 +65,6 @@ public:
 
      virtual bool Init(Building* building);
 
-     virtual void PrepareForSimulation(Building* b);
-
      virtual int FindExit(Pedestrian* p);
 
      /**
diff --git a/routing/MeshRouter.cpp b/routing/MeshRouter.cpp
index dacf7fbacd73207d40b5324eb4790521f482edc5..d391b11543a644855b71229974ce505d164426c0 100644
--- a/routing/MeshRouter.cpp
+++ b/routing/MeshRouter.cpp
@@ -968,9 +968,6 @@ bool MeshRouter::Init(Building* b)
      return true;
 }
 
-void MeshRouter::PrepareForSimulation(Building* b) {
-     (void) b;
-}
 
 void MeshRouter::WriteMeshToFile(const string& filename)
 {
diff --git a/routing/MeshRouter.h b/routing/MeshRouter.h
index c83f3e083b6278aad50e5002d1d14401a7ffc830..18ff19c1298a211344be0194e949d845919fd03d 100644
--- a/routing/MeshRouter.h
+++ b/routing/MeshRouter.h
@@ -53,7 +53,6 @@ public:
 
      virtual int FindExit(Pedestrian* p);
      virtual bool Init(Building* b);
-     virtual void PrepareForSimulation(Building* b);
 
 };
 
diff --git a/routing/Router.h b/routing/Router.h
index 53a2c26dd0986ef8d74f086527598ae211b5e2e5..23667eec9ecd39992c6cfb5c48e3fd26fce05eab 100644
--- a/routing/Router.h
+++ b/routing/Router.h
@@ -133,13 +133,6 @@ public:
       */
      virtual bool ParseAdditionalParameters(){return true;};
 
-     /**
-      * Each implementation can do some pre-simulation calculation. When calling this
-      * function, the exit route for each pedestrian (present at the beginning of the
-      * simulation) is already known.
-      */
-     virtual void PrepareForSimulation(Building* b) = 0;
-
 };
 
 #endif  /* _ROUTING_H */
diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp
index 38768f57e8f9107e82c99c5d200d1ba6f7ec2415..d00252fc60675682ed689933551380b4edf98ed3 100644
--- a/routing/RoutingEngine.cpp
+++ b/routing/RoutingEngine.cpp
@@ -125,8 +125,3 @@ bool RoutingEngine::Init(Building* building)
      return status;
 }
 
-void RoutingEngine::PrepareForSimulation(Building *building) {
-     for (auto router: _routersCollection) {
-          router->PrepareForSimulation(building);
-     }
-}
diff --git a/routing/RoutingEngine.h b/routing/RoutingEngine.h
index bf81f74b015acb1f5281f2e828bf2aedd24d937d..3b39d723c5ffc8ec59463f286ea5f5e28bbbb7b3 100644
--- a/routing/RoutingEngine.h
+++ b/routing/RoutingEngine.h
@@ -106,11 +106,6 @@ public:
       */
      bool Init(Building* building);
 
-     /**
-      * Allow the routers to do some preparation
-      * @param building
-      */
-     void PrepareForSimulation(Building* building);
 
 private:
      /// collections of all routers used
diff --git a/routing/ffRouter.cpp b/routing/ffRouter.cpp
index 65688e871903ae573ecc0e13331c0d3da4551e57..4b78909fcc325b7e08d42a151ed8d04820e7035f 100644
--- a/routing/ffRouter.cpp
+++ b/routing/ffRouter.cpp
@@ -562,94 +562,58 @@ bool FFRouter::ReInit()
      return true;
 }
 
-// @todo f.mack remove building from the argument list
-void FFRouter::PrepareForSimulation(Building* building) {}
-
 std::set<std::pair<int, int>> FFRouter::GetPresumableExitRoute(Pedestrian* p) {
-     std::set<std::pair<int, int>> roomsDoorsVector;
-     roomsDoorsVector.clear();
-     // @todo f.mack parallelize
-#pragma omp single
-     {
-          // collects all <room, door> pairs needed using _pathsMatrix
-//          for (auto ped : building->GetAllPedestrians()) {
-               int finalDoor = _finalDoors.at(p->GetID());
-               int finalDoorID = _CroTrByUID.at(finalDoor)->GetID();
-               Log->Write("ped %d: final door is UID %d, ID %d", p->GetID(), finalDoor, finalDoorID);
-               /*
-               if (ped->GetFinalDestination() == -1) {
-                    for (auto lastdoor : validFinalDoorToOutside) {
-
-                    }
-               } else {
-                    finalDoor = goalToLineUIDmap.at(ped->GetFinalDestination());
-               }*/
-               int roomID = p->GetRoomID();
-               auto room = _building->GetRoom(roomID);
-               int doorUID = p->GetNextDestination();
-               do {
-                    Log->Write("PrepareForSimulation: ped %d needs ff in roomID %d to doorUID %d (ID %d)",
+    std::set<std::pair<int, int>> roomsDoorsVector;
+    roomsDoorsVector.clear();
+    int finalDoor = _finalDoors.at(p->GetID());
+    int finalDoorID = _CroTrByUID.at(finalDoor)->GetID();
+    Log->Write("ped %d: final door is UID %d, ID %d", p->GetID(), finalDoor, finalDoorID);
+
+    int roomID = p->GetRoomID();
+    auto room = _building->GetRoom(roomID);
+    int doorUID = p->GetNextDestination();
+    do {
+        Log->Write("GetPresumableExitRoute: ped %d needs ff in roomID %d to doorUID %d (ID %d)",
+              p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
+        if (_CroTrByUID[doorUID]->GetRoom1() &&
+            _CroTrByUID[doorUID]->GetRoom1()->GetID() != room->GetID()) {
+             if (auto tr = dynamic_cast<Transition*>(_CroTrByUID[doorUID])) {
+                  if (tr->GetRoom2() && tr->GetRoom2()->GetID() != room->GetID()) {
+                       Log->Write(
+                               "ERROR in GetPresumableExitRoute: ped %d want to leave roomID %d through doorUID %d (ID %d), but this room does not belong to this door.",
+                               p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
+                  }
+             }
+        }
+        roomsDoorsVector.insert(std::make_pair(room->GetID(), doorUID));
+        auto nextDoorUID = _pathsMatrix.at(std::make_pair(doorUID, finalDoor));
+        // _pathsMatrix sometimes returns a door in the same room we are already in
+        if (!_CroTrByUID[nextDoorUID]->IsInRoom(room->GetID())) {
+             if (Transition* tr = dynamic_cast<Transition*>(_CroTrByUID[doorUID])) {
+                  auto oldRoomID = room->GetID();
+                  room = tr->GetOtherRoom(room->GetID());
+                  if (!tr->IsInRoom(room->GetID())) {
+                       Log->Write("ERROR in GetPresumableExitRoute: ped %d wants to walk through doorUID %d (ID %d), but neither roomID %d nor %d are adjacent.",
+                                  p->GetID(), nextDoorUID, _CroTrByUID[nextDoorUID]->GetID(), oldRoomID, room->GetID());
+                  }
+             }
+        }
+        doorUID = nextDoorUID;
+    } while (doorUID != finalDoor);
+    Log->Write("GetPresumableExitRoute: ped %d needs ff in roomID %d to doorUID %d (ID %d) (final exit)",
+              p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
+    if (_CroTrByUID[doorUID]->GetRoom1() &&
+       _CroTrByUID[doorUID]->GetRoom1()->GetID() != room->GetID()) {
+        if (auto tr = dynamic_cast<Transition*>(_CroTrByUID[doorUID])) {
+             if (tr->GetRoom2() && tr->GetRoom2()->GetID() != room->GetID()) {
+                  Log->Write(
+                          "ERROR in GetPresumableExitRoute: ped %d want to leave roomID %d through doorUID %d (ID %d) (final exit), but this room does not belong to this door.",
                           p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
-                    if (_CroTrByUID[doorUID]->GetRoom1() &&
-                        _CroTrByUID[doorUID]->GetRoom1()->GetID() != room->GetID()) {
-                         if (auto tr = dynamic_cast<Transition*>(_CroTrByUID[doorUID])) {
-                              if (tr->GetRoom2() && tr->GetRoom2()->GetID() != room->GetID()) {
-                                   Log->Write(
-                                           "ERROR in PrepareForSimulation: ped %d want to leave roomID %d through doorUID %d (ID %d), but this room does not belong to this door.",
-                                           p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
-                              }
-                         }
-                    }
-                    roomsDoorsVector.insert(std::make_pair(room->GetID(), doorUID));
-                    auto nextDoorUID = _pathsMatrix.at(std::make_pair(doorUID, finalDoor));
-                    // _pathsMatrix sometimes returns a door in the same room we are already in
-                    if (!_CroTrByUID[nextDoorUID]->IsInRoom(room->GetID())) {
-                         if (Transition* tr = dynamic_cast<Transition*>(_CroTrByUID[doorUID])) {
-                              auto oldRoomID = room->GetID();
-                              room = tr->GetOtherRoom(room->GetID());
-                              if (!tr->IsInRoom(room->GetID())) {
-                                   Log->Write("ERROR in PrepareForSimulation: ped %d wants to walk through doorUID %d (ID %d), but neither roomID %d nor %d are adjacent.",
-                                              p->GetID(), nextDoorUID, _CroTrByUID[nextDoorUID]->GetID(), oldRoomID, room->GetID());
-                              }
-                         }
-                    }
-                    doorUID = nextDoorUID;
-               } while (doorUID != finalDoor);
-               Log->Write("PrepareForSimulation: ped %d needs ff in roomID %d to doorUID %d (ID %d) (final exit)",
-                          p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
-               if (_CroTrByUID[doorUID]->GetRoom1() &&
-                   _CroTrByUID[doorUID]->GetRoom1()->GetID() != room->GetID()) {
-                    if (auto tr = dynamic_cast<Transition*>(_CroTrByUID[doorUID])) {
-                         if (tr->GetRoom2() && tr->GetRoom2()->GetID() != room->GetID()) {
-                              Log->Write(
-                                      "ERROR in PrepareForSimulation: ped %d want to leave roomID %d through doorUID %d (ID %d) (final exit), but this room does not belong to this door.",
-                                      p->GetID(), room->GetID(), doorUID, _CroTrByUID[doorUID]->GetID());
-                         }
-                    }
-               }
-               roomsDoorsVector.insert(std::make_pair(room->GetID(), doorUID));
-//          }
-//
-//          // make entries unique // @todo f.mack maybe using a set is more efficient
-////#pragma omp single
-//          std::sort(roomsDoorsVector.begin(), roomsDoorsVector.end());
-////#pragma omp single
-//          roomsDoorsVector.erase(std::unique(roomsDoorsVector.begin(), roomsDoorsVector.end()), roomsDoorsVector.end());
-//
-//          for (auto sdIt : roomsDoorsVector) {
-//               Log->Write("need ff in roomID %d for doorUID %d (ID %d)",
-//                          sdIt.first, building->GetRoom(sdIt.first)->GetID(), sdIt.second, _CroTrByUID[sdIt.second]->GetID());
-//          }
-//
-//
-//          // calculate the ff in a parallelized way
-//          for (auto rdIt = roomsDoorsVector.begin(); rdIt < roomsDoorsVector.end(); ++rdIt) {
-//               auto newLocFloorfield = new LocalFloorfieldViaFM(building->GetRoom(rdIt->first), building, 0,0,0,true);
-//#pragma omp critical
-//               //_locffviafm.insert();
-//          }
-     } // omp single (is going to become omp parallel)
-     return roomsDoorsVector;
+             }
+        }
+    }
+    roomsDoorsVector.insert(std::make_pair(room->GetID(), doorUID));
+    return roomsDoorsVector;
 }
 
 int FFRouter::FindExit(Pedestrian* p)
diff --git a/routing/ffRouter.h b/routing/ffRouter.h
index 685971c082ccdf465d3fa01f1c1a85a0e0b143ae..094e2c4c72f6d3db328565ff09859445ec13aadc 100644
--- a/routing/ffRouter.h
+++ b/routing/ffRouter.h
@@ -153,14 +153,6 @@ public:
       */
      virtual bool ReInit();
 
-     /*!
-      * \brief Calculates some needed floorfields
-      *
-      * PrepareForSimulation() will look up the exit route of each pedestrian (which is not yet
-      * known in Init()) and calculate the floorfields needed for these routes.
-      */
-     virtual void PrepareForSimulation(Building* building);
-
      /*!
       * \brief interface used by __Pedestrian__, sets (*p).exitline/.exitindex
       *