Program Listing for File SubEnvironmentDescription.cpp
↰ Return to documentation for file (src/flamegpu/model/SubEnvironmentDescription.cpp
)
#include "flamegpu/model/SubEnvironmentDescription.h"
#include "flamegpu/model/ModelData.h"
#include "flamegpu/model/SubModelData.h"
#include "flamegpu/model/SubEnvironmentData.h"
#include "flamegpu/model/EnvironmentDescription.h"
#include "flamegpu/model/EnvironmentDirectedGraphData.cuh"
namespace flamegpu {
CSubEnvironmentDescription::CSubEnvironmentDescription(std::shared_ptr<SubEnvironmentData> data)
: subenvironment(std::move(data)) { }
CSubEnvironmentDescription::CSubEnvironmentDescription(std::shared_ptr<const SubEnvironmentData> data)
: subenvironment(std::move(std::const_pointer_cast<SubEnvironmentData>(data))) { }
bool CSubEnvironmentDescription::operator==(const CSubEnvironmentDescription& rhs) const {
return *this->subenvironment == *rhs.subenvironment; // Compare content is functionally the same
}
bool CSubEnvironmentDescription::operator!=(const CSubEnvironmentDescription& rhs) const {
return !(*this == rhs);
}
std::string CSubEnvironmentDescription::getPropertyMapping(const std::string& sub_property_name) const {
const auto v = subenvironment->properties.find(sub_property_name);
if (v != subenvironment->properties.end())
return v->second;
THROW exception::InvalidAgentState("SubEnvironment property '%s', either does not exist or has not been mapped yet, "
"in SubEnvironmentDescription::getPropertyMapping()\n", sub_property_name.c_str());
}
std::string CSubEnvironmentDescription::getMacroPropertyMapping(const std::string& sub_property_name) const {
const auto v = subenvironment->macro_properties.find(sub_property_name);
if (v != subenvironment->properties.end())
return v->second;
THROW exception::InvalidAgentState("SubEnvironment macro property '%s', either does not exist or has not been mapped yet, "
"in SubEnvironmentDescription::getMacroPropertyMapping()\n", sub_property_name.c_str());
}
std::string CSubEnvironmentDescription::getDirectedGraphMapping(const std::string& sub_graph_name) const {
const auto v = subenvironment->directed_graphs.find(sub_graph_name);
if (v != subenvironment->directed_graphs.end())
return v->second;
THROW exception::InvalidEnvGraph("SubEnvironment directed graph '%s', either does not exist or has not been mapped yet, "
"in SubEnvironmentDescription::getDirectedGraphMapping()\n", sub_graph_name.c_str());
}
SubEnvironmentDescription::SubEnvironmentDescription(std::shared_ptr<SubEnvironmentData> data)
: CSubEnvironmentDescription(std::move(data)) { }
void SubEnvironmentDescription::mapProperty(const std::string &sub_property_name, const std::string &master_property_name) {
// Neither are reserved properties
if (!sub_property_name.empty() && sub_property_name[0] == '_') {
THROW exception::ReservedName("Sub-model environment property '%s is internal and cannot be mapped, "
"in SubEnvironmentDescription::mapProperty()\n", sub_property_name.c_str());
}
if (!master_property_name.empty() && master_property_name[0] == '_') {
THROW exception::ReservedName("Master-model environment property '%s is internal and cannot be mapped, "
"in SubEnvironmentDescription::mapProperty()\n", master_property_name.c_str());
}
// Sub property exists
auto subEnv = subenvironment->subEnvironment.lock();
if (!subEnv) {
THROW exception::InvalidParent("SubEnvironment pointer has expired, "
"in SubEnvironmentDescription::mapProperty()\n");
}
const auto subProp = subEnv->properties.find(sub_property_name);
if (subProp == subEnv->properties.end()) {
const auto parent = subenvironment->parent.lock();
THROW exception::InvalidEnvProperty("SubModel '%s's Environment does not contain property '%s', "
"in SubEnvironmentDescription::mapProperty()\n", parent ? parent->submodel->name.c_str() : "?", sub_property_name.c_str());
}
// Master property exists
auto masterEnv = subenvironment->masterEnvironment.lock();
if (!masterEnv) {
THROW exception::InvalidParent("MasterEnvironment pointer has expired, "
"in SubEnvironmentDescription::mapProperty()\n");
}
const auto masterProp = masterEnv->properties.find(master_property_name);
if (masterProp == masterEnv->properties.end()) {
THROW exception::InvalidEnvProperty("MasterEnvironment does not contain property '%s', "
"in SubEnvironmentDescription::mapProperty()\n", master_property_name.c_str());
}
// Sub property has not been bound yet
if (subenvironment->properties.find(sub_property_name) != subenvironment->properties.end()) {
const auto parent = subenvironment->parent.lock();
THROW exception::InvalidEnvProperty("SubModel '%s's Environment property '%s' has already been mapped, "
"in SubEnvironmentDescription::mapProperty()\n", parent ? parent->submodel->name.c_str() : "?", sub_property_name.c_str());
}
// Master property has already been bound
for (auto &v : subenvironment->properties) {
if (v.second == master_property_name) {
THROW exception::InvalidEnvProperty("MasterEnvironment property '%s' has already been mapped, "
"in SubEnvironmentDescription::mapProperty()\n", master_property_name.c_str());
}
}
// Check properties are the same
if (subProp->second.data.type != masterProp->second.data.type) {
THROW exception::InvalidEnvProperty("Property types do not match, '%s' != '%s', "
"in SubEnvironmentDescription::mapProperty()\n", subProp->second.data.type.name(), masterProp->second.data.type.name());
}
if (subProp->second.data.elements != masterProp->second.data.elements) {
THROW exception::InvalidEnvProperty("Property lengths do not match, '%u' != '%u'",
"in SubEnvironmentDescription::mapProperty()\n", subProp->second.data.elements, masterProp->second.data.elements);
}
if (masterProp->second.isConst && !subProp->second.isConst) {
THROW exception::InvalidEnvProperty("SubEnvironment property '%s' must be const, if mapped to const MasterEnvironment property '%s', "
"in SubEnvironmentDescription::mapProperty()\n", sub_property_name.c_str(), master_property_name.c_str());
}
// Properties match, create mapping
subenvironment->properties.emplace(sub_property_name, master_property_name);
}
void SubEnvironmentDescription::mapMacroProperty(const std::string& sub_property_name, const std::string& master_property_name) {
// Neither are reserved properties
if (!sub_property_name.empty() && sub_property_name[0] == '_') {
THROW exception::ReservedName("Sub-model environment macro property '%s is internal and cannot be mapped, "
"in SubEnvironmentDescription::mapMacroProperty()\n", sub_property_name.c_str());
}
if (!master_property_name.empty() && master_property_name[0] == '_') {
THROW exception::ReservedName("Master-model environment macro property '%s is internal and cannot be mapped, "
"in SubEnvironmentDescription::mapMacroProperty()\n", master_property_name.c_str());
}
// Sub macro property exists
auto subEnv = subenvironment->subEnvironment.lock();
if (!subEnv) {
THROW exception::InvalidParent("SubEnvironment pointer has expired, "
"in SubEnvironmentDescription::mapMacroProperty()\n");
}
const auto subProp = subEnv->macro_properties.find(sub_property_name);
if (subProp == subEnv->macro_properties.end()) {
const auto parent = subenvironment->parent.lock();
THROW exception::InvalidEnvProperty("SubModel '%s's Environment does not contain macro property '%s', "
"in SubEnvironmentDescription::mapMacroProperty()\n", parent ? parent->submodel->name.c_str() : "?", sub_property_name.c_str());
}
// Master macro property exists
auto masterEnv = subenvironment->masterEnvironment.lock();
if (!masterEnv) {
THROW exception::InvalidParent("MasterEnvironment pointer has expired, "
"in SubEnvironmentDescription::mapMacroProperty()\n");
}
const auto masterProp = masterEnv->macro_properties.find(master_property_name);
if (masterProp == masterEnv->macro_properties.end()) {
THROW exception::InvalidEnvProperty("MasterEnvironment does not contain macro property '%s', "
"in SubEnvironmentDescription::mapMacroProperty()\n", master_property_name.c_str());
}
// Sub macro property has not been bound yet
if (subenvironment->macro_properties.find(sub_property_name) != subenvironment->macro_properties.end()) {
const auto parent = subenvironment->parent.lock();
THROW exception::InvalidEnvProperty("SubModel '%s's Environment macro property '%s' has already been mapped, "
"in SubEnvironmentDescription::mapMacroProperty()\n", parent ? parent->submodel->name.c_str() : "?", sub_property_name.c_str());
}
// Master macro property has already been bound
for (auto& v : subenvironment->macro_properties) {
if (v.second == master_property_name) {
THROW exception::InvalidEnvProperty("MasterEnvironment macro property '%s' has already been mapped, "
"in SubEnvironmentDescription::mapMacroProperty()\n", master_property_name.c_str());
}
}
// Check macro properties are the same
if (subProp->second.type != masterProp->second.type) {
THROW exception::InvalidEnvProperty("Macro property types do not match, '%s' != '%s', "
"in SubEnvironmentDescription::mapMacroProperty()\n", subProp->second.type.name(), masterProp->second.type.name());
}
if (subProp->second.elements != masterProp->second.elements) {
THROW exception::InvalidEnvProperty("Macro property dimensions do not match, (%u, %u, %u, %u) != (%u, %u, %u, %u)",
"in SubEnvironmentDescription::mapMacroProperty()\n",
subProp->second.elements[0], subProp->second.elements[1], subProp->second.elements[2], subProp->second.elements[3],
masterProp->second.elements[0], masterProp->second.elements[1], masterProp->second.elements[2], masterProp->second.elements[3]);
}
// Macro properties match, create mapping
subenvironment->macro_properties.emplace(sub_property_name, master_property_name);
}
void SubEnvironmentDescription::mapDirectedGraph(const std::string& sub_graph_name, const std::string& master_graph_name) {
// Neither are reserved properties
if (!sub_graph_name.empty() && sub_graph_name[0] == '_') {
THROW exception::ReservedName("Sub-model environment directed graph '%s is internal and cannot be mapped, "
"in SubEnvironmentDescription::mapDirectedGraph()\n", sub_graph_name.c_str());
}
if (!master_graph_name.empty() && master_graph_name[0] == '_') {
THROW exception::ReservedName("Master-model environment directed graph '%s is internal and cannot be mapped, "
"in SubEnvironmentDescription::mapDirectedGraph()\n", master_graph_name.c_str());
}
// Sub directed graph exists
auto subEnv = subenvironment->subEnvironment.lock();
if (!subEnv) {
THROW exception::InvalidParent("SubEnvironment pointer has expired, "
"in SubEnvironmentDescription::mapDirectedGraph()\n");
}
const auto subProp = subEnv->directed_graphs.find(sub_graph_name);
if (subProp == subEnv->directed_graphs.end()) {
const auto parent = subenvironment->parent.lock();
THROW exception::InvalidEnvProperty("SubModel '%s's Environment does not contain directed graph '%s', "
"in SubEnvironmentDescription::mapDirectedGraph()\n", parent ? parent->submodel->name.c_str() : "?", sub_graph_name.c_str());
}
// Master macro property exists
auto masterEnv = subenvironment->masterEnvironment.lock();
if (!masterEnv) {
THROW exception::InvalidParent("MasterEnvironment pointer has expired, "
"in SubEnvironmentDescription::mapDirectedGraph()\n");
}
const auto masterProp = masterEnv->directed_graphs.find(master_graph_name);
if (masterProp == masterEnv->directed_graphs.end()) {
THROW exception::InvalidEnvGraph("MasterEnvironment does not contain directed graph '%s', "
"in SubEnvironmentDescription::mapDirectedGraph()\n", sub_graph_name.c_str());
}
// Sub macro property has not been bound yet
if (subenvironment->directed_graphs.find(sub_graph_name) != subenvironment->directed_graphs.end()) {
const auto parent = subenvironment->parent.lock();
THROW exception::InvalidEnvGraph("SubModel '%s's Environment directed graph '%s' has already been mapped, "
"in SubEnvironmentDescription::mapDirectedGraph()\n", parent ? parent->submodel->name.c_str() : "?", sub_graph_name.c_str());
}
// Master macro property has already been bound
for (auto& v : subenvironment->directed_graphs) {
if (v.second == master_graph_name) {
THROW exception::InvalidEnvGraph("MasterEnvironment directed graph '%s' has already been mapped, "
"in SubEnvironmentDescription::mapDirectedGraph()\n", master_graph_name.c_str());
}
}
// Check macro properties are the same
if (*subProp->second != *masterProp->second) {
THROW exception::InvalidEnvGraph("Directed graphs are not identical, '%s' != '%s', "
"in SubEnvironmentDescription::mapMacroProperty()\n", master_graph_name.c_str(), sub_graph_name.c_str());
}
// Directed graphs match, create mapping
subenvironment->directed_graphs.emplace(sub_graph_name, master_graph_name);
}
void SubEnvironmentDescription::autoMap() {
autoMapProperties();
autoMapMacroProperties();
autoMapDirectedGraphs();
}
void SubEnvironmentDescription::autoMapProperties() {
// Sub env exists
auto subEnv = subenvironment->subEnvironment.lock();
if (!subEnv) {
THROW exception::InvalidParent("SubEnvironment pointer has expired, "
"in SubEnvironmentDescription::autoMapProperties()\n");
}
// Master env exists
auto masterEnv = subenvironment->masterEnvironment.lock();
if (!masterEnv) {
THROW exception::InvalidParent("MasterEnvironment pointer has expired, "
"in SubEnvironmentDescription::autoMapProperties()\n");
}
for (auto &subProp : subEnv->properties) {
// If it's a reserved environment property, don't map it
// (Previously, there was a bug where _stepCount was being mixed between parent and child models)
if (subProp.first[0] == '_')
continue;
auto masterProp = masterEnv->properties.find(subProp.first);
// If there exists variable with same name in both environments
if (masterProp != masterEnv->properties.end()) {
// Check properties are the same
if ((subProp.second.data.type == masterProp->second.data.type) &&
(subProp.second.data.elements == masterProp->second.data.elements) &&
!(masterProp->second.isConst && !subProp.second.isConst)) {
subenvironment->properties.emplace(subProp.first, masterProp->first); // Doesn't actually matter, both strings are equal
}
}
}
}
void SubEnvironmentDescription::autoMapMacroProperties() {
// Sub env exists
auto subEnv = subenvironment->subEnvironment.lock();
if (!subEnv) {
THROW exception::InvalidParent("SubEnvironment pointer has expired, "
"in SubEnvironmentDescription::autoMapMacroProperties()\n");
}
// Master env exists
auto masterEnv = subenvironment->masterEnvironment.lock();
if (!masterEnv) {
THROW exception::InvalidParent("MasterEnvironment pointer has expired, "
"in SubEnvironmentDescription::autoMapMacroProperties()\n");
}
for (auto& subProp : subEnv->macro_properties) {
// If it's a reserved environment property, don't map it
if (subProp.first[0] == '_')
continue;
auto masterProp = masterEnv->macro_properties.find(subProp.first);
// If there exists variable with same name in both environments
if (masterProp != masterEnv->macro_properties.end()) {
// Check properties are the same
if ((subProp.second.type == masterProp->second.type) &&
(subProp.second.elements == masterProp->second.elements)) {
subenvironment->macro_properties.emplace(subProp.first, masterProp->first); // Doesn't actually matter, both strings are equal
}
}
}
}
void SubEnvironmentDescription::autoMapDirectedGraphs() {
// Sub env exists
auto subEnv = subenvironment->subEnvironment.lock();
if (!subEnv) {
THROW exception::InvalidParent("SubEnvironment pointer has expired, "
"in SubEnvironmentDescription::autoMapDirectedGraphs()\n");
}
// Master env exists
auto masterEnv = subenvironment->masterEnvironment.lock();
if (!masterEnv) {
THROW exception::InvalidParent("MasterEnvironment pointer has expired, "
"in SubEnvironmentDescription::autoMapDirectedGraphs()\n");
}
for (auto& subGraph : subEnv->directed_graphs) {
// If it's a reserved environment property, don't map it
if (subGraph.first[0] == '_')
continue;
auto masterGraph = masterEnv->directed_graphs.find(subGraph.first);
// If there exists variable with same name in both environments
if (masterGraph != masterEnv->directed_graphs.end()) {
// Check properties are the same
if (*subGraph.second == *masterGraph->second) {
subenvironment->directed_graphs.emplace(subGraph.first, masterGraph->first); // Doesn't actually matter, both strings are equal
}
}
}
}
} // namespace flamegpu