/**
* \file FDSMeshStorage.h
* \date Jan 1, 2014
* \version v0.7
* \copyright <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved.
*
* \section License
* This file is part of JuPedSim.
*
* JuPedSim is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JuPedSim is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JuPedSim. If not, see .
*
* \section Description
* Container to store all FDSMeshs. Sorted first by coordinates of the corresponding door,
* secondly by simulation's global time
*
*
**/
#include "FDSMeshStorage.h"
//#include
//#include
// #include
#include
namespace fs = boost::filesystem;
//namespace fs = std::experimental::filesystem;
FDSMeshStorage::FDSMeshStorage()
{
}
FDSMeshStorage::FDSMeshStorage(const std::string &filepath, const double &finalTime, const double &updateIntervall, const std::string &study, const std::string &irritant) :
_filepath(filepath), _finalTime(finalTime),
_updateIntervall(updateIntervall), _study(study),
_elevationlist(), _timelist(), _irritant(irritant)
{
///Check if _filepath exists
fs::path p(_filepath);
p = fs::canonical(p).make_preferred(); //remove ..
_filepath = p.string(); // TODO: refactor this class. Use path instead of string
std::cout << "\nFDSMeshStorage: <" << p << ">\n";
if (fs::exists(p) )
{
std::cout << "\nCreating QuantityList..." << std::endl;
CreateQuantityList();
std::cout << "Success!" << std::endl;
std::cout << "\nCreating ElevationList..." << std::endl;
CreateElevationList();
std::cout << "Success!" << std::endl;
std::cout << "\nCreating DoorList..." << std::endl;
CreateDoorList();
std::cout << "Success!" << std::endl;
std::cout << "\nCreating TimeList..." << std::endl;
CreateTimeList();
std::cout << "Success!" << std::endl;
std::cout << "\nCreating FDSMeshes..." << std::endl;
CreateFDSMeshes();
std::cout << "Success!" << std::endl;
}
else {
Log->Write("ERROR:\tCould not find directory <%s>\n", _filepath.c_str());
exit(EXIT_FAILURE);
}
}
FDSMeshStorage::~FDSMeshStorage()
{
}
bool FDSMeshStorage::CreateQuantityList()
{
/// Create quantity list
_quantitylist.clear();
fs::directory_iterator end ;
for( fs::directory_iterator iter(_filepath) ; iter != end ; ++iter ) {
if ( fs::is_directory( *iter ) )
{
std::string quant_dir = iter->path().string();
quant_dir = quant_dir.substr( quant_dir.find_last_of("/\\") + 1 );
//std::cout << quant_dir << std::endl;
_quantitylist.push_back(quant_dir);
}
}
if (_quantitylist.size() == 0) {
Log->Write("ERROR:\tCould not find suitable quantities in %s", _filepath.c_str());
exit(EXIT_FAILURE);
return false;
}
std::cout << "_quantitylist.size(): " << _quantitylist.size() << "\n";
return true;
}
bool FDSMeshStorage::CreateElevationList()
{
/// Create elevation list out of the available Z_* dirs for each quantity
_elevationlist.clear();
fs::directory_iterator end ;
fs::path q(_filepath);
q /= fs::path(_quantitylist[0]);
for( fs::directory_iterator iter(q) ; iter != end ; ++iter ) {
if ( fs::is_directory( *iter ) )
{
std::string elev_dir = iter->path().string();
double elev = std::stod(elev_dir.substr( elev_dir.rfind("_") + 1 ));
//std::cout << elev << std::endl;
_elevationlist.push_back(elev);
}
}
if (_elevationlist.size() == 0) {
Log->Write("ERROR:\tCould not find suitable grid elevations in %s", _filepath.c_str());
exit(EXIT_FAILURE);
return false;
}
std::cout << "_elevationlist.size(): " << _elevationlist.size() << "\n";
return true;
}
void FDSMeshStorage::CreateDoorList()
{
/// Create door list only neceassry if smoke sensor is active
_doorlist.clear();
fs::directory_iterator end ;
fs::path q(_filepath);
q /= fs::path(_quantitylist[0]);
for( auto &elv:_elevationlist){
std::string elvAsString = std::to_string(elv);
for( fs::directory_iterator iter(q) ; iter != end ; ++iter ) {
if ( !fs::is_directory( *iter ) )
continue;
// skip directories not starting with Z_
if (iter->path().string().find("Z_") == std::string::npos)
continue;
// Skip if different elevation
double this_elev = std::stod(elvAsString.substr( elvAsString.rfind("_") + 1 ));
if(this_elev != elv) continue;
// iterate over "Z_/" directories
for( fs::directory_iterator i(iter->path() ) ; i != end ; ++i ) {
if ( ! fs::is_directory( *i ) ) continue;
std::string tempString = i->path().string();
tempString = tempString.substr(0, tempString.find_last_of("/\\"));
unsigned long startChar = tempString.find_last_of("/\\") + 1;
tempString = i->path().string();
tempString = tempString.substr(startChar);
std::replace(tempString.begin(), tempString.end(), '\\', '/'); // fox for windows Z_1\Door_X_2_Y_6 -> Z_1/Door_X_2_Y_6
_doorlist.push_back(tempString);
}
}
}
std::cout << "_doorlist.size(): " << _doorlist.size() << "\n";
}
void FDSMeshStorage::CreateTimeList()
{
/// Create time list for mesh refreshment
_timelist.clear();
double i=0;
while (i<=_finalTime)
{
_timelist.push_back(i);
i+=_updateIntervall;
}
///Check if specified final and update times are compliant with available data
for(auto elem : _timelist) {
fs::path npz_file(_filepath);
if (_doorlist.size() > 0) { // Smoke sensor active
npz_file = npz_file / _quantitylist[0] / _doorlist[0] / ("t_" + std::to_string(elem) + ".npz");
}
else if (_doorlist.size() == 0) { // Smoke sensor not active
npz_file = npz_file / _quantitylist[0] / ("Z_" + std::to_string(_elevationlist[0])) / ("t_" + std::to_string(elem) + ".npz");
}
if (fs::exists(npz_file) == false)
{
Log->Write("ERROR:\tSpecified times are not compliant with JPSfire data " + npz_file.string());
std::cout << "\n\nCreateTimeList(): File not found: " << npz_file.string() << std::endl;
exit(EXIT_FAILURE);
}
//std::cout << "LEAVING \n" ;
}
std::cout << "_timelist.size(): " << _timelist.size() << "\n";
}
void FDSMeshStorage::CreateFDSMeshes()
{
std::cout << "Enter CreateFDSMeshes\n";
_fMContainer.clear();
if (_doorlist.size() > 0) { // Smoke sensor active
for (auto &h:_quantitylist) //list of quantities
{
for (auto &j:_doorlist) //list of doors
{
//std::cout << "door " << j << std::endl;
for (auto &k:_timelist) //list of times
{
fs::path npz_file(_filepath);
npz_file = npz_file / h / j / ("t_" + std::to_string(k) + ".npz");
npz_file = fs::canonical(npz_file).make_preferred(); // correct sep and remove ..
FDSMesh mesh(npz_file.string());
_fMContainer.insert(std::make_pair(npz_file.string(), mesh));
}
}
}
}
else if (_doorlist.size() == 0) { // Smoke sensor not active
for (auto &h:_quantitylist) //list of quantities
{
for (auto &i:_elevationlist) //list of elevations
{
//std::cout << "i " << i << std::endl;
for (auto &k:_timelist) //list of times
{
fs::path npz_file(_filepath);
npz_file = npz_file / h / ("Z_" + std::to_string(i)) / ("t_" + std::to_string(k) + ".npz");
npz_file = fs::canonical(npz_file).make_preferred(); // correct sep and remove ..
FDSMesh mesh(npz_file.string());
_fMContainer.insert(std::make_pair(npz_file.string(), mesh));
}
}
}
}
std::cout << "_fdcontainer.size(): " << _fMContainer.size() << "\n";
}
const FDSMesh &FDSMeshStorage::GetFDSMesh(const double &simTime, const double &pedElev, const std::string &quantity) throw (int)
{
//Smoke Sensor NOT active
int simT=simTime/_updateIntervall;
simT*=_updateIntervall;
_PedEyeHeight = pedElev + 1.8;
GetNearestHeight(_PedEyeHeight);
if (simT>=_finalTime)
simT=_finalTime;
//std::cout << "\t" << quantity << std::endl;
fs::path Ztime(quantity);
Ztime = Ztime / ("Z_" + std::to_string(_NearestHeight)) / ("t_" + std::to_string(simT) + ".000000.npz");
Ztime = _filepath / Ztime;
Ztime = fs::canonical(Ztime).make_preferred();
if (_fMContainer.count(Ztime.string()) == 0) {
//std::cout << str << std::endl;
std::cout << "\n time ERROR: requested grid not available: " << Ztime.string() << std::endl;
throw -1;
}
return _fMContainer.at(Ztime.string());
// TODO
// if(_fMContainer.??(str) ) {
// return _fMContainer.at(str);
// }
// else {
// Log->Write("ERROR:\tCould find no appropriate FDS mesh: ", quantity.string(), pedElev, simT);
// exit(EXIT_FAILURE);
// }
}
const FDSMesh &FDSMeshStorage::GetFDSMesh(const double &pedElev, const Point &doorCentre, const double &simTime) throw (int)
{
//Smoke Sensor active
std::string quantity = "EXTINCTION_COEFFICIENT";
_PedEyeHeight = pedElev + 1.8;
GetNearestHeight(_PedEyeHeight);
int simT=simTime/_updateIntervall;
simT*=_updateIntervall;
if (simT>=_finalTime)
simT=_finalTime;
// @todo: what if the files have the format Z_%.2f ?
fs::path door_xy(quantity);
door_xy = door_xy / ("Z_" + std::to_string(_NearestHeight)) /
("Door_X_" + std::to_string(doorCentre._x) + "_Y_" + std::to_string(doorCentre._y)) /
("t_" + std::to_string(simT) + ".000000.npz");
door_xy = _filepath / door_xy;
door_xy = fs::canonical(door_xy).make_preferred();
if (_fMContainer.count(door_xy.string()) == 0) {
std::cout << "\n > ERROR: requested sfgrid not available: " << door_xy.string() << std::endl;
throw -1;
}
// if (_fMContainer.count(str) == 1) {
// std::cout << "INFO: requested sfgrid: " << str << std::endl;
// }
return _fMContainer.at(door_xy.string());
}
double FDSMeshStorage::GetNearestHeight(double PedEyeHeight)
{
///find the nearest height in the JPSfire data related to the ped elevation
double min_val = FLT_MAX;// std::numeric_limits::max();
int index = 0;
for(unsigned int i=0;i < _elevationlist.size() ;++i) {
double diff = std::abs(_elevationlist[i] - PedEyeHeight);
if(diff < min_val) {
min_val = diff;
index = i;
}
}
_NearestHeight = _elevationlist[index];
//std::cout << "NEAREST: " << _NearestHeight << std::endl;
return _NearestHeight;
}
std::string FDSMeshStorage::GetStudy() const
{
return _study;
}
std::string FDSMeshStorage::IrritantOrNot() const
{
return _irritant;
}