Program Listing for File AgentDescription.h
↰ Return to documentation for file (include/flamegpu/model/AgentDescription.h
)
#ifndef INCLUDE_FLAMEGPU_MODEL_AGENTDESCRIPTION_H_
#define INCLUDE_FLAMEGPU_MODEL_AGENTDESCRIPTION_H_
#include <string>
#include <map>
#include <typeinfo>
#include <memory>
#include <vector>
#include <set>
#include "flamegpu/model/Variable.h"
#include "flamegpu/model/ModelDescription.h"
#include "flamegpu/simulation/AgentVector.h"
#include "flamegpu/runtime/agent/AgentInstance.h"
#include "flamegpu/model/AgentData.h"
#include "flamegpu/detail/type_decode.h"
namespace flamegpu {
class CAgentFunctionDescription;
class AgentFunctionDescription;
class AgentDescription;
namespace visualiser {
struct AgentVisData;
}
class CAgentDescription {
friend struct AgentData;
friend AgentVector::AgentVector(const CAgentDescription& agent_desc, flamegpu::size_type);
friend AgentInstance::AgentInstance(const CAgentDescription& agent_desc);
friend bool AgentVector::matchesAgentType(const CAgentDescription& other) const;
friend struct visualiser::AgentVisData;
public:
explicit CAgentDescription(std::shared_ptr<AgentData> data);
explicit CAgentDescription(std::shared_ptr<const AgentData> data);
CAgentDescription(const CAgentDescription& other_agent) = default;
CAgentDescription(CAgentDescription&& other_agent) = default;
CAgentDescription& operator=(const CAgentDescription& other_agent) = default;
CAgentDescription& operator=(CAgentDescription&& other_agent) = default;
bool operator==(const CAgentDescription& rhs) const;
bool operator!=(const CAgentDescription& rhs) const;
std::string getName() const;
flamegpu::size_type getStatesCount() const;
std::string getInitialState() const;
const std::type_index& getVariableType(const std::string& variable_name) const;
size_t getVariableSize(const std::string& variable_name) const;
flamegpu::size_type getVariableLength(const std::string& variable_name) const;
flamegpu::size_type getVariablesCount() const;
CAgentFunctionDescription getFunction(const std::string& function_name) const;
flamegpu::size_type getFunctionsCount() const;
flamegpu::size_type getAgentOutputsCount() const;
bool hasState(const std::string& state_name) const;
bool hasVariable(const std::string& variable_name) const;
bool hasFunction(const std::string& function_name) const;
bool isOutputOnDevice() const;
const std::set<std::string>& getStates() const;
protected:
std::shared_ptr<AgentData> agent;
};
class AgentDescription : public CAgentDescription {
friend struct AgentFunctionData;
friend class DependencyGraph;
friend class AgentFunctionDescription;
public:
explicit AgentDescription(std::shared_ptr<AgentData> data);
AgentDescription(const AgentDescription& other_agent) = default;
AgentDescription(AgentDescription&& other_agent) = default;
AgentDescription& operator=(const AgentDescription& other_agent) = default;
AgentDescription& operator=(AgentDescription&& other_agent) = default;
void newState(const std::string &state_name);
void setInitialState(const std::string &initial_state);
template<typename T, flamegpu::size_type N>
void newVariable(const std::string &variable_name, const std::array<T, N> &default_value = {});
#ifndef SWIG
template<typename T>
void newVariable(const std::string& variable_name, T default_value = {});
#else
template<typename T>
void newVariable(const std::string& variable_name, T default_value = 0);
template<typename T>
void newVariableArray(const std::string &variable_name, const flamegpu::size_type &length, const std::vector<T>&default_value = {});
#endif
template<typename AgentFunction>
AgentFunctionDescription newFunction(const std::string &function_name, AgentFunction a = AgentFunction());
AgentFunctionDescription newRTCFunction(const std::string& function_name, const std::string& func_src);
AgentFunctionDescription newRTCFunctionFile(const std::string& function_name, const std::string& file_path);
AgentFunctionDescription Function(const std::string &function_name);
void setSortPeriod(const unsigned int sortPeriod);
};
template <typename T, flamegpu::size_type N>
void AgentDescription::newVariable(const std::string &variable_name, const std::array<T, N> &default_value) {
if (!variable_name.empty() && variable_name[0] == '_') {
THROW exception::ReservedName("Agent variable names cannot begin with '_', this is reserved for internal usage, "
"in AgentDescription::newVariable().");
}
std::string lower_variable_name = variable_name;
for (auto& c : lower_variable_name)
c = static_cast<char>(tolower(c));
if (lower_variable_name == "name" || lower_variable_name == "state") {
THROW exception::ReservedName("Agent variables cannot be named 'name' or 'state', these are reserved for backwards compatibility reasons, "
"in AgentDescription::newVariable().");
}
if (lower_variable_name == "_auto_sort_bin_index") {
THROW exception::ReservedName("The variable name '_auto_sort_bin_index' is reserved for internal usage, "
"in AgentDescription::newVariable().");
}
// Array length 0 makes no sense
static_assert(detail::type_decode<T>::len_t * N > 0, "A variable cannot have 0 elements.");
if (agent->variables.find(variable_name) == agent->variables.end()) {
const std::array<typename detail::type_decode<T>::type_t, detail::type_decode<T>::len_t * N> *casted_default =
reinterpret_cast<const std::array<typename detail::type_decode<T>::type_t, detail::type_decode<T>::len_t* N>*>(&default_value);
agent->variables.emplace(variable_name, Variable(*casted_default));
return;
}
THROW exception::InvalidAgentVar("Agent ('%s') already contains variable '%s', "
"in AgentDescription::newVariable().",
agent->name.c_str(), variable_name.c_str());
}
template <typename T>
void AgentDescription::newVariable(const std::string &variable_name, const T default_value) {
newVariable<T, 1>(variable_name, { default_value });
}
#ifdef SWIG
template<typename T>
void AgentDescription::newVariableArray(const std::string& variable_name, const flamegpu::size_type& length, const std::vector<T>& default_value) {
if (!variable_name.empty() && variable_name[0] == '_') {
THROW exception::ReservedName("Agent variable names cannot begin with '_', this is reserved for internal usage, "
"in AgentDescription::newVariable().");
}
std::string lower_variable_name = variable_name;
for (auto& c : lower_variable_name)
c = static_cast<char>(tolower(c));
if (lower_variable_name == "name" || lower_variable_name == "state") {
THROW exception::ReservedName("Agent variables cannot be named 'name' or 'state', these are reserved for backwards compatibility reasons, "
"in AgentDescription::newVariable().");
}
if (length == 0) {
THROW exception::InvalidAgentVar("Agent variable arrays must have a length greater than 0."
"in AgentDescription::newVariable().");
}
if (default_value.size() && default_value.size() != length) {
THROW exception::InvalidAgentVar("Agent variable array length specified as %d, but default value provided with %llu elements, "
"in AgentDescription::newVariable().",
length, static_cast<unsigned int>(default_value.size()));
}
if (agent->variables.find(variable_name) == agent->variables.end()) {
std::vector<typename detail::type_decode<T>::type_t> temp(static_cast<size_t>(detail::type_decode<T>::len_t * length));
if (default_value.size()) {
memcpy(temp.data(), default_value.data(), sizeof(typename detail::type_decode<T>::type_t) * detail::type_decode<T>::len_t * length);
}
agent->variables.emplace(variable_name, Variable(detail::type_decode<T>::len_t* length, temp));
return;
}
THROW exception::InvalidAgentVar("Agent ('%s') already contains variable '%s', "
"in AgentDescription::newVariable().",
agent->name.c_str(), variable_name.c_str());
}
#endif
// Found in "flamegpu/model/AgentFunctionDescription.h"
// template<typename AgentFunction>
// AgentFunctionDescription &AgentDescription::newFunction(const std::string &function_name, AgentFunction)
} // namespace flamegpu
#endif // INCLUDE_FLAMEGPU_MODEL_AGENTDESCRIPTION_H_