Program Listing for File LogFrame.h

Return to documentation for file (include/flamegpu/simulation/LogFrame.h)

#ifndef INCLUDE_FLAMEGPU_SIMULATION_LOGFRAME_H_
#define INCLUDE_FLAMEGPU_SIMULATION_LOGFRAME_H_

#include "AgentLoggingConfig.h"

#include <map>
#include <list>
#include <string>
#include <utility>
#include <vector>

#include "flamegpu/simulation/LoggingConfig.h"
#include "flamegpu/detail/Any.h"
#include "flamegpu/exception/FLAMEGPUException.h"

namespace flamegpu {

struct AgentLogFrame;
struct StepLogFrame;
struct ExitLogFrame;

struct LogFrame {
    friend class CUDASimulation;
    LogFrame();
    LogFrame(const std::map<std::string, detail::Any> &_environment,
    const std::map<util::StringPair, std::pair<std::map<LoggingConfig::NameReductionFn, detail::Any>, unsigned int>> &_agents,
    unsigned int _step_count);
    unsigned int getStepCount() const { return step_count; }
    bool hasEnvironmentProperty(const std::string &property_name) const;
    template<typename T>
    T getEnvironmentProperty(const std::string &property_name) const;
    template<typename T, unsigned int N>
    std::array<T, N> getEnvironmentProperty(const std::string &property_name) const;
#ifdef SWIG
    template<typename T>
    std::vector<T> getEnvironmentPropertyArray(const std::string &property_name) const;
#endif
    AgentLogFrame getAgent(const std::string &agent_name, const std::string &state_name = ModelData::DEFAULT_STATE) const;
    const std::map<std::string, detail::Any> &getEnvironment() const { return environment; }
    const std::map<util::StringPair, std::pair<std::map<LoggingConfig::NameReductionFn, detail::Any>, unsigned int>> &getAgents() const { return agents; }

 private:
    std::map<std::string, detail::Any> environment;
    std::map<util::StringPair, std::pair<std::map<LoggingConfig::NameReductionFn, detail::Any>, unsigned int>> agents;
    unsigned int step_count;
};

struct StepLogFrame : public LogFrame {
    friend class CUDASimulation;
    StepLogFrame();
    StepLogFrame(const std::map<std::string, detail::Any>&& _environment,
        const std::map<util::StringPair, std::pair<std::map<LoggingConfig::NameReductionFn, detail::Any>, unsigned int>>&& _agents,
        unsigned int _step_count);

    double getStepTime() const { return step_time; }

 private:
    double step_time;
};

struct ExitLogFrame : public LogFrame {
    friend class CUDASimulation;
    ExitLogFrame();
    ExitLogFrame(const std::map<std::string, detail::Any>&& _environment,
        const std::map<util::StringPair, std::pair<std::map<LoggingConfig::NameReductionFn, detail::Any>, unsigned int>>&& _agents,
        unsigned int _step_count);

    double getRTCTime() const { return rtc_time; }
    double getInitTime() const { return init_time; }
    double getExitTime() const { return exit_time; }
    double getTotalTime() const { return total_time; }

 private:
    double rtc_time;
    double init_time;
    double exit_time;
    double total_time;
};
struct RunLog {
    struct PerformanceSpecs {
        std::string device_name;
        int device_cc_major;
        int device_cc_minor;
        int cuda_version;
        bool seatbelts;
        std::string flamegpu_version;
    };
    friend class CUDASimulation;
    RunLog() { }
    RunLog(const ExitLogFrame &_exit, const std::list<StepLogFrame> &_step)
        : exit(_exit)
        , step(_step) { }
    const ExitLogFrame &getExitLog() const { return exit; }
    const std::list<StepLogFrame> &getStepLog() const {return step; }
    uint64_t getRandomSeed() const { return random_seed; }
    unsigned int getStepLogFrequency() const { return step_log_frequency; }
    PerformanceSpecs getPerformanceSpecs() const { return performance_specs; }

 private:
    ExitLogFrame exit;
    std::list<StepLogFrame> step;
    uint64_t random_seed = 0;
    unsigned int step_log_frequency = 0;
    PerformanceSpecs performance_specs;
};
struct AgentLogFrame {
    explicit AgentLogFrame(const std::map<LoggingConfig::NameReductionFn, detail::Any> &data, unsigned int count);
    unsigned int getCount() const;
    template<typename T>
    T getMin(const std::string &variable_name) const;
    template<typename T>
    T getMax(const std::string &variable_name) const;
    template<typename T>
    typename sum_input_t<T>::result_t getSum(const std::string &variable_name) const;
    double getMean(const std::string &variable_name) const;
    double getStandardDev(const std::string &variable_name) const;

 private:
    const std::map<LoggingConfig::NameReductionFn, detail::Any> &data;
    const unsigned int count;
};

template<typename T>
T LogFrame::getEnvironmentProperty(const std::string &property_name) const {
    const auto &it = environment.find(property_name);
    if (it == environment.end()) {
      THROW exception::InvalidEnvProperty("Environment property '%s' was not found in the log, "
          "in LogFrame::getEnvironmentProperty()\n",
          property_name.c_str());
    }
    if (it->second.type != std::type_index(typeid(T))) {
      THROW exception::InvalidEnvPropertyType("Environment property '%s' has type %s, but requested type %s, "
          "in LogFrame::getEnvironmentProperty()\n",
          property_name.c_str(), it->second.type.name(), std::type_index(typeid(T)).name());
    }
    if (it->second.elements != 1) {
      THROW exception::InvalidEnvPropertyType("Environment property '%s' is an array, use alternate function with array interface, "
          "in LogFrame::getEnvironmentProperty()\n",
          property_name.c_str(), it->second.type.name(), std::type_index(typeid(T)).name());
    }
    return *static_cast<T*>(it->second.ptr);
}
template<typename T, unsigned int N>
std::array<T, N> LogFrame::getEnvironmentProperty(const std::string &property_name) const {
    const auto &it = environment.find(property_name);
    if (it == environment.end()) {
      THROW exception::InvalidEnvProperty("Environment property '%s' was not found in the log, "
          "in LogFrame::getEnvironmentProperty()\n",
          property_name.c_str());
    }
    if (it->second.type != std::type_index(typeid(T))) {
      THROW exception::InvalidEnvPropertyType("Environment property '%s' has type %s, but requested type %s, "
          "in LogFrame::getEnvironmentProperty()\n",
          property_name.c_str(), it->second.type.name(), std::type_index(typeid(T)).name());
    }
    if (it->second.elements != N) {
      THROW exception::InvalidEnvPropertyType("Environment property array '%s' has %u elements, but requested array with %u, "
          "in LogFrame::getEnvironmentProperty()\n",
          property_name.c_str(), it->second.elements, N);
    }
    std::array<T, N> rtn;
    memcpy(rtn.data(), it->second.ptr, it->second.length);
    return rtn;
}
#ifdef SWIG
template<typename T>
std::vector<T> LogFrame::getEnvironmentPropertyArray(const std::string& property_name) const {
    const auto &it = environment.find(property_name);
    if (it == environment.end()) {
      THROW exception::InvalidEnvProperty("Environment property '%s' was not found in the log, "
          "in LogFrame::getEnvironmentPropertyArray()\n",
          property_name.c_str());
    }
    if (it->second.type != std::type_index(typeid(T))) {
      THROW exception::InvalidEnvPropertyType("Environment property '%s' has type %s, but requested type %s, "
          "in LogFrame::getEnvironmentPropertyArray()\n",
          property_name.c_str(), it->second.type.name(), std::type_index(typeid(T)).name());
    }
    // Copy old data to return
    std::vector<T> rtn(static_cast<size_t>(it->second.elements));
    memcpy(rtn.data(), it->second.ptr, it->second.length);
    return rtn;
}
#endif

template<typename T>
T AgentLogFrame::getMin(const std::string &variable_name) const {
    const auto &it = data.find({variable_name, LoggingConfig::Min});
    if (it == data.end()) {
        THROW exception::InvalidAgentVar("Min of agent variable '%s' was not found in the log, "
            "in AgentLogFrame::getMin()\n",
            variable_name.c_str());
    }
    if (it->second.type != std::type_index(typeid(T))) {
      THROW exception::InvalidVarType("Agent variable '%s' has type %s, but requested type %s, "
          "in AgentLogFrame::getMin()\n",
          variable_name.c_str(), it->second.type.name(), std::type_index(typeid(T)).name());
    }
    return *static_cast<T *>(it->second.ptr);
}
template<typename T>
T AgentLogFrame::getMax(const std::string &variable_name) const {
    const auto &it = data.find({variable_name, LoggingConfig::Max});
    if (it == data.end()) {
        THROW exception::InvalidAgentVar("Max of agent variable '%s' was not found in the log, "
            "in AgentLogFrame::getMax()\n",
            variable_name.c_str());
    }
    if (it->second.type != std::type_index(typeid(T))) {
      THROW exception::InvalidVarType("Agent variable '%s' has type %s, but requested type %s, "
          "in AgentLogFrame::getMax()\n",
          variable_name.c_str(), it->second.type.name(), std::type_index(typeid(T)).name());
    }
    return *static_cast<T *>(it->second.ptr);
}
template<typename T>
typename sum_input_t<T>::result_t AgentLogFrame::getSum(const std::string &variable_name) const {
    const auto &it = data.find({variable_name, LoggingConfig::Sum});
    if (it == data.end()) {
        THROW exception::InvalidAgentVar("Sum of agent variable '%s' was not found in the log, "
            "in AgentLogFrame::getSum()\n",
            variable_name.c_str());
    }
    if (it->second.type != std::type_index(typeid(typename sum_input_t<T>::result_t))) {
      THROW exception::InvalidVarType("Agent variable is not of type '%s', but requested type %s, "
          "in AgentLogFrame::getSum()\n",
          variable_name.c_str(), std::type_index(typeid(T)).name());
    }
    return *static_cast<typename sum_input_t<T>::result_t *>(it->second.ptr);
}

}  // namespace flamegpu

#endif  // INCLUDE_FLAMEGPU_SIMULATION_LOGFRAME_H_