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;
        Vertex operator[](id_t vertex_id);
         class Vertex {
             std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
             const cudaStream_t stream;
             id_t vertex_id;
             friend Vertex VertexMap::operator[](id_t);

          public:
             Vertex(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, cudaStream_t _stream, id_t _vertex_id);
             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
         };
    };
    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:
        class Edge;
        Edge operator[](SrcDestPair source_dest_vertex_ids);
        class Edge {
            std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
            const cudaStream_t stream;
            id_t source_vertex_id, destination_vertex_id;
            friend Edge EdgeMap::operator[](SrcDestPair);

         public:
            Edge(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, cudaStream_t _stream, id_t _source_vertex_id, id_t _dest_vertex_id);
            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
        };
    };
};

#ifdef SWIG
template<typename T>
void HostEnvironmentDirectedGraph::VertexMap::Vertex::setPropertyArray(const std::string& property_name, const std::vector<T>& property_value) const {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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 {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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 {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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 {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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) {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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) {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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) {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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 {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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 {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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 {
    // Get index
    const unsigned int vertex_index = directed_graph->getVertexIndex(vertex_id);
    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) {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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) {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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) {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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 {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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 {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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 {
    // Get index
    const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
    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_