Program Listing for File HostEnvironmentDirectedGraph.cuh
↰ Return to documentation for file (include/flamegpu/runtime/environment/HostEnvironmentDirectedGraph.cuh
)
#ifndef INCLUDE_FLAMEGPU_RUNTIME_ENVIRONMENT_HOSTENVIRONMENTDIRECTEDGRAPH_CUH_
#define INCLUDE_FLAMEGPU_RUNTIME_ENVIRONMENT_HOSTENVIRONMENTDIRECTEDGRAPH_CUH_
#include <utility>
#include <string>
#include <vector>
#include <memory>
#include <array>
#include "flamegpu/simulation/detail/CUDAEnvironmentDirectedGraphBuffers.cuh"
#include "flamegpu/defines.h"
namespace flamegpu {
class HostEnvironmentDirectedGraph {
// Windows/Python edge case, if an exception is thrown this object is destructed super late
// So be extra safe with weak ptr
std::weak_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
const cudaStream_t stream;
#ifdef FLAMEGPU_ADVANCED_API
detail::CUDAScatter &scatter;
const unsigned int streamID;
#endif
public:
class VertexMap;
class EdgeMap;
HostEnvironmentDirectedGraph(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers>& _directed_graph, cudaStream_t _stream, detail::CUDAScatter& _scatter, unsigned int _streamID);
// Graph Structure Modifiers
void importGraph(const std::string &in_file);
void exportGraph(const std::string &out_file);
void setVertexCount(flamegpu::size_type count);
size_type getVertexCount();
void setEdgeCount(flamegpu::size_type count);
size_type getEdgeCount();
VertexMap vertices();
EdgeMap edges();
#ifdef FLAMEGPU_ADVANCED_API
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> getCUDABuffers();
void rebuild() {
if (const auto dg = directed_graph.lock()) {
dg->markForRebuild();
dg->syncDevice_async(scatter, streamID, stream);
} else {
THROW exception::ExpiredWeakPtr("Graph nolonger exists, weak pointer could not be locked, in HostEnvironmentDirectedGraph::rebuild()\n");
}
}
#endif
class VertexMap {
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
const cudaStream_t stream;
friend VertexMap HostEnvironmentDirectedGraph::vertices();
VertexMap(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph, cudaStream_t stream);
public:
class Vertex;
struct Iterator;
size_type size() const;
size_type allocated_size() const;
Vertex operator[](id_t vertex_id);
Vertex atIndex(unsigned int index);
class Vertex {
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
const cudaStream_t stream;
unsigned int vertex_index;
friend Vertex VertexMap::operator[](id_t);
friend struct Iterator;
public:
Vertex(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, cudaStream_t _stream, id_t _vertex_id, bool is_index = false);
void setID(id_t vertex_id);
template<typename T>
void setProperty(const std::string& property_name, T property_value);
template<typename T, flamegpu::size_type N = 0>
void setProperty(const std::string& property_name, flamegpu::size_type element_index, T property_value);
template<typename T, flamegpu::size_type N>
void setProperty(const std::string& property_name, const std::array<T, N>& property_value);
id_t getID() const;
template<typename T>
T getProperty(const std::string& property_name) const;
template<typename T, flamegpu::size_type N = 0>
T getProperty(const std::string& property_name, unsigned int element_index) const;
template<typename T, flamegpu::size_type N>
std::array<T, N> getProperty(const std::string& property_name) const;
#ifdef SWIG
template<typename T>
void setPropertyArray(const std::string& property_name, const std::vector<T>& property_value) const;
template<typename T>
std::vector<T> getPropertyArray(const std::string& property_name) const;
#endif
};
struct Iterator {
using iterator_category = std::forward_iterator_tag;
using difference_type = unsigned int;
using value_type = Vertex;
using pointer = Vertex*;
using reference = Vertex&;
Iterator(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, const cudaStream_t _stream, difference_type _index)
: directed_graph(std::move(_directed_graph))
, stream(_stream)
, vertex(directed_graph, _stream, _index, true) {}
reference operator*() const { return vertex; }
pointer operator->() const { return &vertex; }
Iterator& operator++() { vertex.vertex_index++; return *this; }
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
bool operator==(const Iterator& other) const { return vertex.vertex_index == other.vertex.vertex_index; }
bool operator!=(const Iterator& other) const { return vertex.vertex_index != other.vertex.vertex_index; }
Iterator begin() { return { directed_graph, stream, 0 }; }
Iterator end() { return { directed_graph, stream, directed_graph->getVertexCount() }; }
private:
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
cudaStream_t stream;
mutable Vertex vertex;
};
Iterator begin() { return {directed_graph, stream, 0}; }
Iterator end() { return { directed_graph, stream, directed_graph->getVertexCount() }; }
};
class EdgeMap {
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
const cudaStream_t stream;
friend EdgeMap HostEnvironmentDirectedGraph::edges();
EdgeMap(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph, cudaStream_t stream);
typedef std::pair<id_t, id_t> SrcDestPair;
public:
struct Iterator;
class Edge;
size_type size() const;
size_type allocated_size() const;
Edge operator[](SrcDestPair source_dest_vertex_ids);
Edge atIndex(unsigned int index);
class Edge {
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
const cudaStream_t stream;
unsigned int edge_index;
friend Edge EdgeMap::operator[](SrcDestPair);
friend struct Iterator;
public:
Edge(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, cudaStream_t _stream, id_t _source_vertex_id, id_t _dest_vertex_id);
Edge(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, cudaStream_t _stream, unsigned int edge_index);
void setSourceVertexID(id_t source_vertex_id);
void setDestinationVertexID(id_t dest_vertex_id);
void setSourceDestinationVertexID(id_t source_vertex_id, id_t dest_vertex_id);
template<typename T>
void setProperty(const std::string& property_name, T property_value);
template<typename T, flamegpu::size_type N = 0>
void setProperty(const std::string& property_name, flamegpu::size_type element_index, T property_value);
template<typename T, flamegpu::size_type N>
void setProperty(const std::string& property_name, const std::array<T, N>& property_value);
id_t getSourceVertexID() const;
id_t getDestinationVertexID() const;
template<typename T>
T getProperty(const std::string& property_name) const;
template<typename T, flamegpu::size_type N = 0>
T getProperty(const std::string& property_name, unsigned int element_index) const;
template<typename T, flamegpu::size_type N>
std::array<T, N> getProperty(const std::string& property_name) const;
#ifdef SWIG
template<typename T>
void setPropertyArray(const std::string& property_name, const std::vector<T>& property_value) const;
template<typename T>
std::vector<T> getPropertyArray(const std::string& property_name) const;
#endif
};
struct Iterator {
using iterator_category = std::forward_iterator_tag;
using difference_type = unsigned int;
using value_type = Edge;
using pointer = Edge*;
using reference = Edge&;
Iterator(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, const cudaStream_t _stream, difference_type _index)
: directed_graph(std::move(_directed_graph))
, stream(_stream)
, edge(directed_graph, _stream, _index) {}
reference operator*() const { return edge; }
pointer operator->() const { return &edge; }
Iterator& operator++() { edge.edge_index++; return *this; }
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
bool operator==(const Iterator& other) const { return edge.edge_index == other.edge.edge_index; }
bool operator!=(const Iterator& other) const { return edge.edge_index != other.edge.edge_index; }
Iterator begin() { return { directed_graph, stream, 0 }; }
Iterator end() { return { directed_graph, stream, directed_graph->getEdgeCount() }; }
private:
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
cudaStream_t stream;
mutable Edge edge;
};
Iterator begin() { return {directed_graph, stream, 0}; }
Iterator end() { return { directed_graph, stream, directed_graph->getEdgeCount() }; }
};
};
#ifdef SWIG
template<typename T>
void HostEnvironmentDirectedGraph::VertexMap::Vertex::setPropertyArray(const std::string& property_name, const std::vector<T>& property_value) const {
size_type n = property_value.size();
T* val = directed_graph->getVertexPropertyBuffer<T>(property_name, n, stream);
if (!property_value.size()) {
THROW exception::InvalidGraphProperty("Vertex property with name '%s' length mismatch '%u' != '%u', in HostEnvironmentDirectedGraph::VertexMap::Vertex::setPropertyArray()",
property_name.c_str(), n, static_cast<unsigned int>(property_value.size()));
}
const size_type vertex_count = directed_graph->getVertexCount();
memcpy(val + vertex_index * property_value.size(), property_value.data(), sizeof(T) * property_value.size());
}
template<typename T>
std::vector<T> HostEnvironmentDirectedGraph::VertexMap::Vertex::getPropertyArray(const std::string& property_name) const {
return directed_graph->getVertexPropertyArray<T>(property_name, vertex_index, stream);
}
template<typename T>
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setPropertyArray(const std::string& property_name, const std::vector<T>& property_value) const {
size_type n = property_value.size();
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, n, stream);
if (!property_value.size()) {
THROW exception::InvalidGraphProperty("Edge property with name '%s' length mismatch '%u' != '%u', in HostEnvironmentDirectedGraph::EdgeMap::Edge::setPropertyArray()",
property_name.c_str(), n, static_cast<unsigned int>(property_value.size()));
}
memcpy(val + edge_index * property_value.size(), property_value.data(), sizeof(T) * property_value.size());
}
template<typename T>
std::vector<T> HostEnvironmentDirectedGraph::EdgeMap::Edge::getPropertyArray(const std::string& property_name) const {
return directed_graph->getEdgePropertyArray<T>(property_name, edge_index, stream);
}
#endif
template<typename T>
void HostEnvironmentDirectedGraph::VertexMap::Vertex::setProperty(const std::string& property_name, T property_value) {
size_type element_ct = 1;
T* rtn = directed_graph->getVertexPropertyBuffer<T>(property_name, element_ct, stream);
rtn[vertex_index] = property_value;
}
template<typename T, flamegpu::size_type N>
void HostEnvironmentDirectedGraph::VertexMap::Vertex::setProperty(const std::string& property_name, flamegpu::size_type element_index, T property_value) {
size_type element_ct = N;
T* rtn = directed_graph->getVertexPropertyBuffer<T>(property_name, element_ct, stream);
if (element_index > element_ct) {
THROW exception::OutOfBoundsException("Element index %u is out of range %u, in VertexMap::Vertex::setProperty()\n",
element_index, element_ct);
}
rtn[vertex_index * element_ct + element_index] = property_value;
}
template<typename T, flamegpu::size_type N>
void HostEnvironmentDirectedGraph::VertexMap::Vertex::setProperty(const std::string& property_name, const std::array<T, N>& property_value) {
size_type element_ct = N;
T* rtn = directed_graph->getVertexPropertyBuffer<T>(property_name, element_ct, stream);
std::array<T, N>* rtn2 = reinterpret_cast<std::array<T, N>*>(rtn);
rtn2[vertex_index] = property_value;
}
template<typename T>
T HostEnvironmentDirectedGraph::VertexMap::Vertex::getProperty(const std::string& property_name) const {
size_type element_ct = 1;
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers *>(directed_graph.get())->getVertexPropertyBuffer<T>(property_name, element_ct, stream);
return rtn[vertex_index];
}
template<typename T, size_type N>
T HostEnvironmentDirectedGraph::VertexMap::Vertex::getProperty(const std::string& property_name, unsigned int element_index) const {
size_type element_ct = N;
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getVertexPropertyBuffer<T>(property_name, element_ct, stream);
if (element_index > element_ct) {
THROW exception::OutOfBoundsException("Element index %u is out of range %u, in VertexMap::Vertex::getProperty()\n",
element_index, element_ct);
}
return rtn[vertex_index * element_ct + element_index];
}
template<typename T, size_type N>
std::array<T, N> HostEnvironmentDirectedGraph::VertexMap::Vertex::getProperty(const std::string& property_name) const {
size_type element_ct = N;
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getVertexPropertyBuffer<T>(property_name, element_ct, stream);
const std::array<T, N>* rtn2 = reinterpret_cast<const std::array<T, N>*>(rtn);
return rtn2[vertex_index];
}
template<typename T>
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string& property_name, const T property_value) {
size_type element_ct = 1;
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
val[edge_index] = property_value;
}
template<typename T, flamegpu::size_type N>
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string& property_name, const size_type element_index, const T property_value) {
size_type element_ct = N;
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
if (element_index >= element_ct) {
THROW exception::OutOfBoundsException("Element index %u is out of range %u, in HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty()\n",
element_index, element_ct);
}
val[edge_index * element_ct + element_index] = property_value;
}
template<typename T, flamegpu::size_type N>
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string& property_name, const std::array<T, N>& property_value) {
size_type element_ct = N;
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
std::array<T, N>* val2 = reinterpret_cast<std::array<T, N>*>(val);
val2[edge_index] = property_value;
}
template<typename T>
T HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& property_name) const {
size_type element_ct = 1;
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
return rtn[edge_index];
}
template<typename T, flamegpu::size_type N>
T HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& property_name, const size_type element_index) const {
size_type element_ct = N;
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
if (element_index >= element_ct) {
THROW exception::OutOfBoundsException("Element index %u is out of range %u, in HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty()\n",
element_index, element_ct);
}
return rtn[edge_index * element_ct + element_index];
}
template<typename T, flamegpu::size_type N>
std::array<T, N> HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& property_name) const {
size_type element_ct = N;
const T *rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
const std::array<T, N>* rtn2 = reinterpret_cast<const std::array<T, N>*>(rtn);
return rtn2[edge_index];
}
} // namespace flamegpu
#endif // INCLUDE_FLAMEGPU_RUNTIME_ENVIRONMENT_HOSTENVIRONMENTDIRECTEDGRAPH_CUH_