.. _program_listing_file_include_flamegpu_model_EnvironmentDescription.h: Program Listing for File EnvironmentDescription.h ================================================= |exhale_lsh| :ref:`Return to documentation for file ` (``include/flamegpu/model/EnvironmentDescription.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef INCLUDE_FLAMEGPU_MODEL_ENVIRONMENTDESCRIPTION_H_ #define INCLUDE_FLAMEGPU_MODEL_ENVIRONMENTDESCRIPTION_H_ #include #include #include #include #include #include #include "flamegpu/exception/FLAMEGPUException.h" #include "flamegpu/runtime/environment/HostEnvironment.cuh" #include "flamegpu/detail/Any.h" #include "flamegpu/model/EnvironmentData.h" #include "flamegpu/detail/type_decode.h" #include "flamegpu/simulation/CUDAEnsemble.h" namespace flamegpu { class CEnvironmentDirectedGraphDescription; class EnvironmentDirectedGraphDescription; class CEnvironmentDescription { friend struct EnvironmentData; public: explicit CEnvironmentDescription(std::shared_ptr data); explicit CEnvironmentDescription(std::shared_ptr data); CEnvironmentDescription(const CEnvironmentDescription& other_agent) = default; CEnvironmentDescription(CEnvironmentDescription&& other_agent) = default; CEnvironmentDescription& operator=(const CEnvironmentDescription& other_agent) = default; CEnvironmentDescription& operator=(CEnvironmentDescription&& other_agent) = default; bool operator==(const CEnvironmentDescription& rhs) const; bool operator!=(const CEnvironmentDescription& rhs) const; template T getProperty(const std::string &name) const; template std::array getProperty(const std::string &name) const; template T getProperty(const std::string &name, flamegpu::size_type index) const; #ifdef SWIG template std::vector getPropertyArray(const std::string &name) const; #endif bool getConst(const std::string &name) const; CEnvironmentDirectedGraphDescription getDirectedGraph(const std::string& graph_name) const; protected: std::shared_ptr environment; }; class EnvironmentDescription : public CEnvironmentDescription { public: explicit EnvironmentDescription(std::shared_ptr data); EnvironmentDescription(const EnvironmentDescription& other_env) = default; EnvironmentDescription(EnvironmentDescription&& other_env) = default; EnvironmentDescription& operator=(const EnvironmentDescription& other_env) = default; EnvironmentDescription& operator=(EnvironmentDescription&& other_env) = default; template void newProperty(const std::string &name, T value, bool isConst = false); template void newProperty(const std::string &name, const std::array &value, bool isConst = false); #ifdef SWIG template void newPropertyArray(const std::string &name, const std::vector &value, const bool isConst = false); #endif template void newMacroProperty(const std::string& name); #ifdef SWIG template void newMacroProperty_swig(const std::string& name, flamegpu::size_type I = 1, flamegpu::size_type J = 1, flamegpu::size_type K = 1, flamegpu::size_type W = 1); #endif EnvironmentDirectedGraphDescription newDirectedGraph(const std::string &graph_name); EnvironmentDirectedGraphDescription getDirectedGraph(const std::string& graph_name); template T setProperty(const std::string &name, T value); template std::array setProperty(const std::string &name, const std::array &value); template T setProperty(const std::string &name, flamegpu::size_type index, T value); #ifdef SWIG template std::vector setPropertyArray(const std::string &name, const std::vector &value); #endif private: void newProperty(const std::string &name, const char *ptr, size_t length, bool isConst, flamegpu::size_type elements, const std::type_index &type); }; template void EnvironmentDescription::newProperty(const std::string &name, T value, bool isConst) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::newProperty()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); if (environment->properties.find(name) != environment->properties.end()) { THROW exception::DuplicateEnvProperty("Environmental property with name '%s' already exists, " "in EnvironmentDescription::newProperty().", name.c_str()); } newProperty(name, reinterpret_cast(&value), sizeof(T), isConst, detail::type_decode::len_t, typeid(typename detail::type_decode::type_t)); } template void EnvironmentDescription::newProperty(const std::string &name, const std::array &value, bool isConst) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::newProperty()."); } static_assert(detail::type_decode::len_t * N > 0, "Environment property arrays must have a length greater than 0."); // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); if (environment->properties.find(name) != environment->properties.end()) { THROW exception::DuplicateEnvProperty("Environmental property with name '%s' already exists, " "in EnvironmentDescription::newProperty().", name.c_str()); } newProperty(name, reinterpret_cast(value.data()), N * sizeof(T), isConst, detail::type_decode::len_t * N, typeid(typename detail::type_decode::type_t)); } #ifdef SWIG template void EnvironmentDescription::newPropertyArray(const std::string &name, const std::vector &value, bool isConst) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::newPropertyArray()."); } if (value.size() == 0) { THROW exception::InvalidEnvProperty("Environment property arrays must have a length greater than 0." "in EnvironmentDescription::newPropertyArray()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); if (environment->properties.find(name) != environment->properties.end()) { THROW exception::DuplicateEnvProperty("Environmental property with name '%s' already exists, " "in EnvironmentDescription::newPropertyArray().", name.c_str()); } newProperty(name, reinterpret_cast(value.data()), value.size() * sizeof(T), isConst, detail::type_decode::len_t * value.size(), typeid(typename detail::type_decode::type_t)); } #endif template T CEnvironmentDescription::getProperty(const std::string &name) const { // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::getProperty().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements != detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Length of named environmental property (%u) does not match vector length (%u), " "in EnvironmentDescription::getProperty().", i->second.data.elements, detail::type_decode::len_t); } return *reinterpret_cast(i->second.data.ptr); } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::getProperty().", name.c_str()); } template std::array CEnvironmentDescription::getProperty(const std::string &name) const { // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::getProperty().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements != detail::type_decode::len_t * N) { THROW exception::InvalidEnvPropertyType("Length of named environmental property array (%u) does not match requested length (%u), " "in EnvironmentDescription::getProperty().", i->second.data.elements, detail::type_decode::len_t * N); } // Copy old data to return std::array rtn; memcpy(rtn.data(), reinterpret_cast(i->second.data.ptr), N * sizeof(T)); return rtn; } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::getProperty().", name.c_str()); } template T CEnvironmentDescription::getProperty(const std::string &name, flamegpu::size_type index) const { // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::getProperty().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements % detail::type_decode::len_t != 0) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') length (%u) does not divide by vector length (%u), " "in EnvironmentDescription::getPropertyArray().", name.c_str(), i->second.data.elements, detail::type_decode::len_t); } const unsigned int t_index = detail::type_decode::len_t * index + detail::type_decode::len_t; if (i->second.data.elements < t_index || t_index < index) { THROW exception::OutOfBoundsException("Index (%u) exceeds named environmental property array's length (%u), " "in EnvironmentDescription::getProperty().", index, i->second.data.elements / detail::type_decode::len_t); } // Copy old data to return return *(reinterpret_cast(i->second.data.ptr) + index); } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::getProperty().", name.c_str()); } #ifdef SWIG template std::vector CEnvironmentDescription::getPropertyArray(const std::string& name) const { // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::getPropertyArray().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements % detail::type_decode::len_t != 0) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') length (%u) does not divide by vector length (%d), " "in EnvironmentDescription::getPropertyArray().", name.c_str(), i->second.data.elements, detail::type_decode::len_t); } // Copy old data to return std::vector rtn(i->second.data.elements / detail::type_decode::len_t); memcpy(rtn.data(), reinterpret_cast(i->second.data.ptr), i->second.data.elements * sizeof(typename detail::type_decode::type_t)); return rtn; } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::getPropertyArray().", name.c_str()); } #endif template T EnvironmentDescription::setProperty(const std::string &name, T value) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::setProperty()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::setProperty().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements != detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Length of named environmental property (%u) does not match vector length (%u), " "in EnvironmentDescription::setProperty().", i->second.data.elements, detail::type_decode::len_t); } // Copy old data to return T rtn = *reinterpret_cast(i->second.data.ptr); // Store data memcpy(i->second.data.ptr, &value, sizeof(T)); return rtn; } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::setProperty().", name.c_str()); } template std::array EnvironmentDescription::setProperty(const std::string &name, const std::array &value) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::setProperty()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::setProperty().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements != N * detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Length of named environmental property array (%u) does not match requested length (%u), " "in EnvironmentDescription::setProperty().", i->second.data.elements, N * detail::type_decode::len_t); } // Copy old data to return std::array rtn; memcpy(rtn.data(), reinterpret_cast(i->second.data.ptr), N * sizeof(T)); // Store data memcpy(reinterpret_cast(i->second.data.ptr), value.data(), N * sizeof(T)); return rtn; } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::setProperty().", name.c_str()); } template T EnvironmentDescription::setProperty(const std::string &name, flamegpu::size_type index, T value) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::setProperty()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::setProperty().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements % detail::type_decode::len_t != 0) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') length (%u) does not divide by vector length (%u), " "in EnvironmentDescription::setProperty().", name.c_str(), i->second.data.elements, detail::type_decode::len_t); } const unsigned int t_index = detail::type_decode::len_t * index + detail::type_decode::len_t; if (i->second.data.elements < t_index || t_index < index) { THROW exception::OutOfBoundsException("Index (%u) exceeds named environmental property array's length (%u), " "in EnvironmentDescription::setProperty().", index, i->second.data.elements / detail::type_decode::len_t); } // Copy old data to return T rtn = *(reinterpret_cast(i->second.data.ptr) + index); // Store data memcpy(reinterpret_cast(i->second.data.ptr) + index, &value, sizeof(T)); return rtn; } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::setProperty().", name.c_str()); } #ifdef SWIG template std::vector EnvironmentDescription::setPropertyArray(const std::string& name, const std::vector& value) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::set()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::type_t>::value || std::is_enum::type_t>::value, "Only arithmetic types can be used as environmental properties"); auto &&i = environment->properties.find(name); if (i != environment->properties.end()) { if (i->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') type (%s) does not match template argument T (%s), " "in EnvironmentDescription::setPropertyArray().", name.c_str(), i->second.data.type.name(), typeid(typename detail::type_decode::type_t).name()); } if (i->second.data.elements % detail::type_decode::len_t != 0) { THROW exception::InvalidEnvPropertyType("Environmental property array ('%s') length (%u) does not divide by vector length (%u), " "in EnvironmentDescription::setPropertyArray().", name.c_str(), i->second.data.elements, detail::type_decode::len_t); } if (i->second.data.elements != value.size() * detail::type_decode::len_t) { THROW exception::OutOfBoundsException("Length of named environmental property array (%u) does not match length of provided vector (%llu), " "in EnvironmentDescription::setPropertyArray().", i->second.data.elements / detail::type_decode::len_t, value.size()); } // Copy old data to return std::vector rtn(i->second.data.elements / detail::type_decode::len_t); memcpy(rtn.data(), reinterpret_cast(i->second.data.ptr), i->second.data.elements * sizeof(typename detail::type_decode::type_t)); // Store data memcpy(reinterpret_cast(i->second.data.ptr), value.data(), i->second.data.elements * sizeof(typename detail::type_decode::type_t)); return rtn; } THROW exception::InvalidEnvProperty("Environmental property with name '%s' does not exist, " "in EnvironmentDescription::set().", name.c_str()); } #endif template void EnvironmentDescription::newMacroProperty(const std::string& name) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment macro property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::newMacroProperty()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::value || std::is_enum::value, "Only arithmetic types can be used as environmental macro properties"); static_assert(I > 0, "Environment macro properties must have a length greater than 0 in the first axis."); static_assert(J > 0, "Environment macro properties must have a length greater than 0 in the second axis."); static_assert(K > 0, "Environment macro properties must have a length greater than 0 in the third axis."); static_assert(W > 0, "Environment macro properties must have a length greater than 0 in the fourth axis."); if (environment->macro_properties.find(name) != environment->macro_properties.end()) { THROW exception::DuplicateEnvProperty("Environmental macro property with name '%s' already exists, " "in EnvironmentDescription::newMacroProperty().", name.c_str()); } environment->macro_properties.emplace(name, EnvironmentData::MacroPropData(typeid(T), sizeof(T), { I, J, K, W })); } #ifdef SWIG template void EnvironmentDescription::newMacroProperty_swig(const std::string& name, flamegpu::size_type I, flamegpu::size_type J, flamegpu::size_type K, flamegpu::size_type W) { if (!name.empty() && name[0] == '_') { THROW exception::ReservedName("Environment macro property names cannot begin with '_', this is reserved for internal usage, " "in EnvironmentDescription::newMacroProperty()."); } // Limited to Arithmetic types // Compound types would allow host pointers inside structs to be passed static_assert(std::is_arithmetic::value || std::is_enum::value, "Only arithmetic types can be used as environmental macro properties"); if (I <= 0) { THROW exception::DuplicateEnvProperty("Environmental macro property with name '%s' must have a length greater than 0 in the first axis, " "in EnvironmentDescription::newMacroProperty().", name.c_str()); } else if (J <= 0) { THROW exception::DuplicateEnvProperty("Environmental macro property with name '%s' must have a length greater than 0 in the second axis, " "in EnvironmentDescription::newMacroProperty().", name.c_str()); } else if (K <= 0) { THROW exception::DuplicateEnvProperty("Environmental macro property with name '%s' must have a length greater than 0 in the third axis, " "in EnvironmentDescription::newMacroProperty().", name.c_str()); } else if (W <= 0) { THROW exception::DuplicateEnvProperty("Environmental macro property with name '%s' must have a length greater than 0 in the fourth axis, " "in EnvironmentDescription::newMacroProperty().", name.c_str()); } else if (environment->macro_properties.find(name) != environment->macro_properties.end()) { THROW exception::DuplicateEnvProperty("Environmental macro property with name '%s' already exists, " "in EnvironmentDescription::newMacroProperty().", name.c_str()); } environment->macro_properties.emplace(name, EnvironmentData::MacroPropData(typeid(T), sizeof(T), { I, J, K, W })); } #endif } // namespace flamegpu #endif // INCLUDE_FLAMEGPU_MODEL_ENVIRONMENTDESCRIPTION_H_