Program Listing for File AgentLoggingConfig.h

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

#ifndef INCLUDE_FLAMEGPU_SIMULATION_AGENTLOGGINGCONFIG_H_
#define INCLUDE_FLAMEGPU_SIMULATION_AGENTLOGGINGCONFIG_H_

#include <string>
#include <memory>
#include <set>
#include <mutex>
#include <utility>

#include "flamegpu/simulation/LoggingConfig.h"
#include "flamegpu/simulation/AgentLoggingConfig_Reductions.cuh"
#include "flamegpu/simulation/AgentLoggingConfig_SumReturn.h"
#include "flamegpu/runtime/agent/HostAgentAPI.cuh"

namespace flamegpu {

struct ModelData;

class AgentLoggingConfig {
    friend AgentLoggingConfig LoggingConfig::agent(const std::string &, const std::string &);
    AgentLoggingConfig(std::shared_ptr<const AgentData> agent,
                       std::pair<std::shared_ptr<std::set<LoggingConfig::NameReductionFn>>, bool> &agent_set);

 public:
    void logCount() { log_count = true; }
    template<typename T>
    void logMean(const std::string &variable_name);
    template<typename T>
    void logStandardDev(const std::string &variable_name);
    template<typename T>
    void logMin(const std::string &variable_name);
    template<typename T>
    void logMax(const std::string &variable_name);
    template<typename T>
    void logSum(const std::string &variable_name);

 private:
    void log(const LoggingConfig::NameReductionFn &name, const std::type_index &variable_type, const std::string &method_name);
    const std::shared_ptr<const AgentData> agent;
    const std::shared_ptr<std::set<LoggingConfig::NameReductionFn>> agent_set;
    bool &log_count;
};

template<typename T>
detail::Any getAgentVariableMeanFunc(HostAgentAPI &ai, const std::string &variable_name) {
    if (ai.count() > 0)
        return detail::Any(ai.sum<T, typename sum_input_t<T>::result_t>(variable_name) / static_cast<double>(ai.count()));
    return detail::Any(static_cast<double>(0));
}
template<typename T>
detail::Any getAgentVariableSumFunc(HostAgentAPI &ai, const std::string &variable_name) {
    return detail::Any(ai.sum<T, typename sum_input_t<T>::result_t>(variable_name));
}
template<typename T>
detail::Any getAgentVariableMinFunc(HostAgentAPI &ai, const std::string &variable_name) {
    return detail::Any(ai.min<T>(variable_name));
}
template<typename T>
detail::Any getAgentVariableMaxFunc(HostAgentAPI &ai, const std::string &variable_name) {
    return detail::Any(ai.max<T>(variable_name));
}

template<typename T>
detail::Any getAgentVariableStandardDevFunc(HostAgentAPI &ai, const std::string &variable_name) {
    // Todo, workout how to make this more multi-thread/deviceable.
    // Todo, streams for the memcpy?
    if (ai.count() == 0)
        return detail::Any(0.0);
    // Work out the Mean
    const double mean = ai.sum<T, typename sum_input_t<T>::result_t>(variable_name) / static_cast<double>(ai.count());
    // Then for each number: subtract the Mean and square the result
    // Then work out the mean of those squared differences.
    auto lock = std::unique_lock<std::mutex>(detail::STANDARD_DEVIATION_MEAN_mutex);
    gpuErrchk(cudaMemcpyToSymbol(detail::STANDARD_DEVIATION_MEAN, &mean, sizeof(double)));
    const double variance = ai.transformReduce<T, double>(variable_name, detail::standard_deviation_subtract_mean, detail::standard_deviation_add, 0) / static_cast<double>(ai.count());
    lock.unlock();
    // Take the square root of that and we are done!
    return detail::Any(sqrt(variance));
}

template<typename T>
void AgentLoggingConfig::logMean(const std::string &variable_name) {
    // Instantiate the template function for calculating the mean
    LoggingConfig::ReductionFn *fn = getAgentVariableMeanFunc<T>;
    // Log the property (validation occurs in this common log method)
    log({variable_name, LoggingConfig::Mean, fn}, std::type_index(typeid(T)), "Mean");
}
template<typename T>
void AgentLoggingConfig::logStandardDev(const std::string &variable_name) {
    // Instantiate the template function for calculating the mean
    LoggingConfig::ReductionFn *fn = getAgentVariableStandardDevFunc<T>;
    // Log the property (validation occurs in this common log method)
    log({variable_name, LoggingConfig::StandardDev, fn}, std::type_index(typeid(T)), "StandardDev");
}
template<typename T>
void AgentLoggingConfig::logMin(const std::string &variable_name) {
    // Instantiate the template function for calculating the mean
    LoggingConfig::ReductionFn *fn = getAgentVariableMinFunc<T>;
    // Log the property (validation occurs in this common log method)
    log({variable_name, LoggingConfig::Min, fn}, std::type_index(typeid(T)), "Min");
}
template<typename T>
void AgentLoggingConfig::logMax(const std::string &variable_name) {
    // Instantiate the template function for calculating the mean
    LoggingConfig::ReductionFn *fn = getAgentVariableMaxFunc<T>;
    // Log the property (validation occurs in this common log method)
    log({variable_name, LoggingConfig::Max, fn}, std::type_index(typeid(T)), "Max");
}
template<typename T>
void AgentLoggingConfig::logSum(const std::string &variable_name) {
    // Instantiate the template function for calculating the mean
    LoggingConfig::ReductionFn *fn = getAgentVariableSumFunc<T>;
    // Log the property (validation occurs in this common log method)
    log({variable_name, LoggingConfig::Sum, fn}, std::type_index(typeid(T)), "Sum");
}

}  // namespace flamegpu

#endif  // INCLUDE_FLAMEGPU_SIMULATION_AGENTLOGGINGCONFIG_H_