.. _program_listing_file_include_flamegpu_simulation_RunPlan.h: Program Listing for File RunPlan.h ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/flamegpu/simulation/RunPlan.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef INCLUDE_FLAMEGPU_SIMULATION_RUNPLAN_H_ #define INCLUDE_FLAMEGPU_SIMULATION_RUNPLAN_H_ #include #include #include #include #include #include "flamegpu/model/EnvironmentDescription.h" #include "flamegpu/detail/Any.h" #include "flamegpu/detail/type_decode.h" #include "flamegpu/simulation/CUDAEnsemble.h" namespace flamegpu { namespace detail { class AbstractSimRunner; } class ModelDescription; class RunPlanVector; class CUDASimulation; namespace io { class JSONLogger; class XMLLogger; } // namespace io class RunPlan { friend class RunPlanVector; friend class detail::AbstractSimRunner; friend class CUDASimulation; friend class io::JSONLogger; friend class io::XMLLogger; public: explicit RunPlan(const ModelDescription &environment); RunPlan& operator=(const RunPlan& other); void setRandomSimulationSeed(uint64_t random_seed); void setSteps(unsigned int steps); void setOutputSubdirectory(const std::string &subdir); template void setProperty(const std::string &name, T value); template void setProperty(const std::string &name, const std::array &value); template void setProperty(const std::string &name, flamegpu::size_type index, T value); #ifdef SWIG template void setPropertyArray(const std::string &name, const std::vector &value); #endif uint64_t getRandomSimulationSeed() const; unsigned int getSteps() const; std::string getOutputSubdirectory() 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); #endif RunPlanVector operator+(const RunPlan& rhs) const; RunPlanVector operator+(const RunPlanVector& rhs) const; RunPlanVector operator*(unsigned int rhs) const; bool operator==(const RunPlan& rhs) const; bool operator!=(const RunPlan& rhs) const; private: explicit RunPlan(const std::shared_ptr> &environment, bool allow_0); uint64_t random_seed; unsigned int steps; std::string output_subdirectory; std::unordered_map property_overrides; // This needs to be shared_ptr, reference goes out of scope, otherwise have a copy of the map per RunPlan std::shared_ptr> environment; bool allow_0_steps; }; template void RunPlan::setProperty(const std::string &name, T value) { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::setProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::setProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (it->second.data.elements != detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Environment property '%s' is an array with %u elements, array method should be used, " "in RunPlan::setProperty()\n", name.c_str(), it->second.data.elements); } // Store property property_overrides.erase(name); property_overrides.emplace(name, detail::Any(&value, sizeof(T), typeid(typename detail::type_decode::type_t), detail::type_decode::len_t)); } template void RunPlan::setProperty(const std::string &name, const std::array &value) { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::setProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::setProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (it->second.data.elements != N * detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Environment property array '%s' length mismatch %u != %u " "in RunPlan::setProperty()\n", name.c_str(), it->second.data.elements, N * detail::type_decode::len_t); } // Store property property_overrides.erase(name); property_overrides.emplace(name, detail::Any(value.data(), sizeof(T) * N, typeid(typename detail::type_decode::type_t), detail::type_decode::len_t * N)); } template void RunPlan::setProperty(const std::string &name, const flamegpu::size_type index, T value) { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::setProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::setProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (N && N != it->second.data.elements) { THROW exception::OutOfBoundsException("Environment property '%s' length mismatch '%u' != '%u', " "in RunPlan::setProperty()\n", name.c_str(), N, it->second.data.elements); } const unsigned int t_index = detail::type_decode::len_t * index + detail::type_decode::len_t; if (it->second.data.elements < t_index || t_index < index) { THROW exception::OutOfBoundsException("Environment property array index out of bounds " "in RunPlan::setProperty()\n"); } // Check whether array already exists in property overrides auto it2 = property_overrides.find(name); if (it2 == property_overrides.end()) { // Clone default property first it2 = property_overrides.emplace(name, it->second.data).first; } // Store property memcpy(static_cast(it2->second.ptr) + index, &value, sizeof(T)); } #ifdef SWIG template void RunPlan::setPropertyArray(const std::string &name, const std::vector &value) { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::setPropertyArray()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::setPropertyArray()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (detail::type_decode::len_t * value.size() != it->second.data.elements) { THROW exception::InvalidEnvPropertyType("Environment property array length does not match the value provided, %u != %llu," "in RunPlan::setPropertyArray()\n", name.c_str(), detail::type_decode::len_t * value.size(), it->second.data.elements); } // Store property property_overrides.erase(name); property_overrides.emplace(name, detail::Any(value.data(), sizeof(T) * value.size(), typeid(typename detail::type_decode::type_t), detail::type_decode::len_t * value.size())); } #endif template T RunPlan::getProperty(const std::string &name) const { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::getProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::getProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (it->second.data.elements != detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Environment property '%s' is an array with %u elements, array method should be used, " "in RunPlan::getProperty()\n", name.c_str(), it->second.data.elements); } // Check whether property already exists in property overrides const auto it2 = property_overrides.find(name); if (it2 != property_overrides.end()) { // The property has been overridden, return the value from the override. return *static_cast(it2->second.ptr); } else { // The property has not been overridden, so return the value from the environment return *static_cast(it->second.data.ptr); } } template std::array RunPlan::getProperty(const std::string &name) const { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::getProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::getProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (it->second.data.elements != N * detail::type_decode::len_t) { THROW exception::InvalidEnvPropertyType("Environment property array '%s' length mismatch %u != %u " "in RunPlan::getProperty()\n", name.c_str(), it->second.data.elements, N); } // Check whether array already exists in property overrides const auto it2 = property_overrides.find(name); std::array rtn; if (it2 != property_overrides.end()) { // The property has been overridden, return the override memcpy(rtn.data(), it2->second.ptr, it2->second.length); } else { // The property has not been overridden, return the environment property memcpy(rtn.data(), it->second.data.ptr, it->second.data.length); } return rtn; } template T RunPlan::getProperty(const std::string &name, const flamegpu::size_type index) const { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::getProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::getProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (N && N != it->second.data.elements) { THROW exception::OutOfBoundsException("Environment property '%s' length mismatch '%u' != '%u', " "in RunPlan::getProperty()\n", name.c_str(), N, it->second.data.elements); } const unsigned int t_index = detail::type_decode::len_t * index + detail::type_decode::len_t; if (it->second.data.elements < t_index || t_index < index) { THROW exception::OutOfBoundsException("Environment property array index out of bounds " "in RunPlan::getProperty()\n"); } // Check whether property already exists in property overrides const auto it2 = property_overrides.find(name); if (it2 != property_overrides.end()) { // The property has been overridden, return the override return static_cast(it2->second.ptr)[index]; } else { // The property has not been overridden, return the environment property return static_cast(it->second.data.ptr)[index]; } } #ifdef SWIG template std::vector RunPlan::getPropertyArray(const std::string &name) { // Validation const auto it = environment->find(name); if (it == environment->end()) { THROW exception::InvalidEnvProperty("Environment description does not contain property '%s', " "in RunPlan::getProperty()\n", name.c_str()); } if (it->second.data.type != std::type_index(typeid(typename detail::type_decode::type_t))) { THROW exception::InvalidEnvPropertyType("Environment property '%s' type mismatch '%s' != '%s', " "in RunPlan::getProperty()\n", name.c_str(), it->second.data.type.name(), std::type_index(typeid(typename detail::type_decode::type_t)).name()); } if (it->second.data.elements % detail::type_decode::len_t != 0) { THROW exception::InvalidEnvPropertyType("Environmental property array '%s' length (%u) is not a multiple of vector length (%u), " "in RunPlan::getPropertyArray().", name.c_str(), detail::type_decode::len_t, it->second.data.elements, detail::type_decode::len_t); } // Check whether array already exists in property overrides const auto it2 = property_overrides.find(name); std::vector rtn(it->second.data.elements / detail::type_decode::len_t); if (it2 != property_overrides.end()) { // The property has been overridden, return the override memcpy(rtn.data(), it2->second.ptr, it2->second.length); } else { // The property has not been overridden, return the environment property memcpy(rtn.data(), it->second.data.ptr, it->second.data.length); } return rtn; } #endif } // namespace flamegpu #endif // INCLUDE_FLAMEGPU_SIMULATION_RUNPLAN_H_