declaring Nodes in Ns3 - ns-3

I am completely new to NS3, i am tasked to set two eNBs and one UE between them to demonstrate x2 handover, i have successfully set the eNBs and UE and also set a mobility model for the UE, now i wanted to generate an XML trace file to run on the NetAnim, when i added the following line to my code
AnimationInterface anim ("x2-handover-animation.xml");
anim.SetMobilityPollInterval (Seconds (0.3));
it also two extra nodes, giving me a total of 5 node instead of the three (2 eNBs and 1 UE) i declared.
Your kind assistance is solicited.
Below is the extract of my source code
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/config-store-module.h"
#include "ns3/csma-module.h"
#include "ns3/wifi-module.h"
#include "ns3/netanim-module.h"
#include "ns3/mobility-helper.h"
#include "ns3/flow-monitor-module.h"
using namespace ns3;
void
NotifyConnectionEstablishedUe (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti)
{
std::cout << context
<< " UE IMSI " << imsi
<< ": connected to CellId " << cellid
<< " with RNTI " << rnti
<< std::endl;
}
void
NotifyHandoverStartUe (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti,
uint16_t targetCellId)
{
std::cout << context
<< " UE IMSI " << imsi
<< ": previously connected to CellId " << cellid
<< " with RNTI " << rnti
<< ", doing handover to CellId " << targetCellId
<< std::endl;
}
void
NotifyHandoverEndOkUe (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti)
{
std::cout << context
<< " UE IMSI " << imsi
<< ": successful handover to CellId " << cellid
<< " with RNTI " << rnti
<< std::endl;
}
void
NotifyConnectionEstablishedEnb (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti)
{
std::cout << context
<< " eNB CellId " << cellid
<< ": successful connection of UE with IMSI " << imsi
<< " RNTI " << rnti
<< std::endl;
}
void
NotifyHandoverStartEnb (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti,
uint16_t targetCellId)
{
std::cout << context
<< " eNB CellId " << cellid
<< ": start handover of UE with IMSI " << imsi
<< " RNTI " << rnti
<< " to CellId " << targetCellId
<< std::endl;
}
void
NotifyHandoverEndOkEnb (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti)
{
std::cout << context
<< " eNB CellId " << cellid
<< ": completed handover of UE with IMSI " << imsi
<< " RNTI " << rnti
<< std::endl;
}
/**
* Sample simulation script for a X2-based handover.
* It instantiates two eNodeB, attaches one UE to the 'source' eNB and
* triggers a handover of the UE towards the 'target' eNB.
*/
NS_LOG_COMPONENT_DEFINE ("EpcX2HandoverExample");
int
main (int argc, char *argv[])
{
uint16_t numberOfUes = 1; // the 1 Ue i declared
uint16_t numberOfEnbs = 2; // the 2 ENBs i declared
uint16_t numBearersPerUe = 0;
double simTime = 10.00;
// change some default attributes so that they are reasonable for
// this scenario, but do this before processing command line
// arguments, so that the user is allowed to override these settings
Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (MilliSeconds(10)));
Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue(1000000));
Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue(false));
// Command line arguments
CommandLine cmd;
cmd.AddValue("numberOfUes", "Number of UEs", numberOfUes);
cmd.AddValue("numberOfEnbs", "Number of eNodeBs", numberOfEnbs);
cmd.AddValue("simTime", "Total duration of the simulation (in seconds)",simTime);
cmd.Parse(argc, argv);
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
Ptr<EpcHelper> epcHelper = CreateObject<EpcHelper> ();
lteHelper->SetEpcHelper (epcHelper);
lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
Ptr<Node> pgw = epcHelper->GetPgwNode ();
// Create a single RemoteHost
NodeContainer remoteHostContainer;
remoteHostContainer.Create (1);
Ptr<Node> remoteHost = remoteHostContainer.Get (0);
InternetStackHelper internet;
internet.Install (remoteHostContainer);
// Create the Internet
PointToPointHelper p2ph;
p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
Ipv4AddressHelper ipv4h;
ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1);
// Routing of the Internet Host (towards the LTE network)
Ipv4StaticRoutingHelper ipv4RoutingHelper;
Ptr<Ipv4StaticRouting> remoteHostStaticRouting =pv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
// interface 0 is localhost, 1 is the p2p device
remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
NodeContainer ueNodes;
NodeContainer enbNodes;
enbNodes.Create(numberOfEnbs);
ueNodes.Create(numberOfUes);
AnimationInterface anim ("x2-handover-animation.xml"); //code i added to generate XML file
anim.SetMobilityPollInterval (Seconds (0.3));
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
mobility.Install (ueNodes);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (enbNodes);
// Install LTE Devices in eNB and UEs
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes);
// Install the IP stack on the UEs
internet.Install (ueNodes);
Ipv4InterfaceContainer ueIpIfaces;
ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevs));
// Assign IP address to UEs, and install applications
for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
{
Ptr<Node> ueNode = ueNodes.Get (u);
// Set the default gateway for the UE
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
}
// Attach all UEs to the first eNodeB
for (uint16_t i = 0; i < numberOfUes; i++)
{
lteHelper->Attach (ueLteDevs.Get(i), enbLteDevs.Get(0));
}
NS_LOG_LOGIC ("setting up applications");
// Install and start applications on UEs and remote host
uint16_t dlPort = 10000;
uint16_t ulPort = 20000;
// randomize a bit start times to avoid simulation artifacts
// (e.g., buffer overflows due to packet transmissions happening
// exactly at the same time)
Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable> ();
startTimeSeconds->SetAttribute ("Min", DoubleValue (0));
startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010));
for (uint32_t u = 0; u < numberOfUes; ++u)
{
Ptr<Node> ue = ueNodes.Get (u);
// Set the default gateway for the UE
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
for (uint32_t b = 0; b < numBearersPerUe; ++b)
{
++dlPort;
++ulPort;
ApplicationContainer clientApps;
ApplicationContainer serverApps;
NS_LOG_LOGIC ("installing UDP DL app for UE " << u);
UdpClientHelper dlClientHelper (ueIpIfaces.GetAddress (u), dlPort);
clientApps.Add (dlClientHelper.Install (remoteHost));
PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), dlPort));
serverApps.Add (dlPacketSinkHelper.Install (ue));
NS_LOG_LOGIC ("installing UDP UL app for UE " << u);
UdpClientHelper ulClientHelper (remoteHostAddr, ulPort);
clientApps.Add (ulClientHelper.Install (ue));
PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), ulPort));
serverApps.Add (ulPacketSinkHelper.Install (remoteHost));
Ptr<EpcTft> tft = Create<EpcTft> ();
EpcTft::PacketFilter dlpf;
dlpf.localPortStart = dlPort;
dlpf.localPortEnd = dlPort;
tft->Add (dlpf);
EpcTft::PacketFilter ulpf;
ulpf.remotePortStart = ulPort;
ulpf.remotePortEnd = ulPort;
tft->Add (ulpf);
EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
lteHelper->ActivateDedicatedEpsBearer (ueLteDevs.Get (u), bearer, tft);
Time startTime = Seconds (startTimeSeconds->GetValue ());
serverApps.Start (startTime);
clientApps.Start (startTime);
} // end for b
}
// Add X2 inteface
lteHelper->AddX2Interface (enbNodes);
// X2-based Handover
lteHelper->HandoverRequest (Seconds (0.100), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
// Uncomment to enable PCAP tracing
p2ph.EnablePcapAll("lena-x2-handover");
lteHelper->EnableMacTraces ();
lteHelper->EnableRlcTraces ();
lteHelper->EnablePdcpTraces ();
Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.05)));
Ptr<RadioBearerStatsCalculator> pdcpStats = lteHelper->GetPdcpStats ();
pdcpStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.05)));
// connect custom trace sinks for RRC connection establishment and handover notification
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/ConnectionEstablished",
MakeCallback (&NotifyConnectionEstablishedEnb));
Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished",
MakeCallback (&NotifyConnectionEstablishedUe));
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart",
MakeCallback (&NotifyHandoverStartEnb));
Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart",
MakeCallback (&NotifyHandoverStartUe));
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverEndOk",
MakeCallback (&NotifyHandoverEndOkEnb));
Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverEndOk",
MakeCallback (&NotifyHandoverEndOkUe));
Simulator::Stop(Seconds(simTime));
Simulator::Run();
// GtkConfigStore config;
// config.ConfigureAttributes();
Simulator::Destroy();
return 0;
}

As I see in this code you have created 5 Nodes not 3.
The First one is pgw node which is and EPC entity
Ptr<Node> pgw = epcHelper->GetPgwNode ();
The Second one is a remote host
remoteHostContainer.Create (1);
These two nodes are connected point to point using the following code
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
The third and fourth nodes are the ENB Nodes "numberOfEnbs = 2;"
enbNodes.Create(numberOfEnbs);
The fifth is the Ue node "numberOfUes = 1;"
ueNodes.Create(numberOfUes);
Thus you should have 5 nodes not three :)
The first two nodes represents the Internet connection that is connected to the LTE network that you created. While the last 3 nodes represents your LTE Network.

Related

Expansion of periodic mesh

I have send this trough the mailing list but it seems not to be fully working at the moment so I am posting it here instead. The issue I am having is that I am trying to expand a periodic mesh and have it returned in a new c3t3 structure instead of having to save a .mesh file and load it afterwards. For this I have tried modifying the File_medit.h found in the Periodic_3_mesh_3/IO folder but am having a few issues. First of all, the tetrahedrals seem to not be properly added when I call the build_triangulation function although the finite_cell vector has all collected values in it. I am having a similar issue with the border_facets, although in this case I am also not sure what data I am supposed to place in surface_patch_id and if perhaps this is causing the issues. I have included the code I am using bellow. Any help is appreciated.
Regards, Kim
/* ==========================================================================
* Based on CGAL's File_medit.h. See CGAL Periodic_3_mesh_3/IO.
* ==========================================================================*/
#ifndef CGAL_PERIODIC_REPLICATOR_H
#define CGAL_PERIODIC_REPLICATOR_H
#include <CGAL/license/Periodic_3_mesh_3.h>
#include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/Mesh_3/tet_soup_to_c3t3.h>
//
#include <CGAL/array.h>
#include <CGAL/assertions.h>
#include <CGAL/IO/File_medit.h>
#include <boost/unordered_map.hpp>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <cstring>
#include <sstream>
#include <cstring>
#include <map>
namespace CGAL {
namespace periodic_replicator {
/**
* \brief expands a periodic mesh to the c3t3 variable
* \param c3t3_periodic the mesh
* \param occurrence_count the number of copies that are printed
* \param distinguish_copies if set to `true`, each copy is assigned a unique color.
* Otherwise, all domains are drawn with subdomain index-based colors.
* \param rebind if set to `true`, labels of cells are rebinded into [1..nb_of_labels]
* \param c3t3 the output mesh
*/
template <class C3T3_Periodic, class C3T3, bool rebind, bool no_patch> ////template <class C3T3_Periodic>
void replicate_periodic_mesh(const C3T3_Periodic& c3t3_periodic,
int occurrence_count[3],
const bool distinguish_copies,
C3T3& c3t3)
{
#ifdef CGAL_MESH_3_IO_VERBOSE
std::cerr << "Output to medit:\n";
#endif
CGAL_precondition(c3t3_periodic.triangulation().is_1_cover());
typedef CGAL::Mesh_3::Medit_pmap_generator<C3T3_Periodic, rebind, no_patch> Generator;
typedef typename Generator::Cell_pmap Cell_pmap;
typedef typename Generator::Facet_pmap Facet_pmap;
typedef typename Generator::Facet_pmap_twice Facet_pmap_twice;
typedef typename Generator::Vertex_pmap Vertex_pmap;
//Generator().print_twice();
Cell_pmap cell_pmap(c3t3_periodic);
Facet_pmap facet_pmap(c3t3_periodic, cell_pmap);
Facet_pmap_twice facet_pmap_twice(c3t3_periodic, cell_pmap);
Vertex_pmap vertex_pmap(c3t3_periodic, cell_pmap, facet_pmap);
// const Facet_index_property_map_twice& facet_twice_pmap = Facet_index_property_map_twice(),
const bool print_each_facet_twice = false;//Generator().print_twice();
CGAL_precondition(occurrence_count[0] >= 1 && occurrence_count[1] >= 1 && occurrence_count[2] >= 1);
// Periodic typedef
typedef typename C3T3_Periodic::Triangulation Triangulation_periodic;
typedef Triangulation_periodic Tr_periodic;
typedef typename Tr_periodic::Bare_point Bare_point;
typedef typename Tr_periodic::Weighted_point Weighted_point;
typedef typename C3T3_Periodic::Vertex_handle Vertex_handle;
typedef typename C3T3_Periodic::Cell_handle Cell_handle;
typedef typename Tr_periodic::Vertex_iterator Vertex_iterator;
typedef typename C3T3_Periodic::Facet_iterator Facet_iterator;
typedef typename C3T3_Periodic::Cell_iterator Cell_iterator;
typedef typename Tr_periodic::Offset Offset;
const Triangulation_periodic& tr_periodic = c3t3_periodic.triangulation();
// Non-periodic typedef
typedef typename C3T3::Triangulation Triangulation;
typedef Triangulation Tr;
typedef typename Tr::Point Point_3;
typedef std::array<int, 3> Facet; // 3 = id
typedef std::array<int, 5> Tet_with_ref; // first 4 = id, fifth = reference
//
std::vector<Point_3> points;
//std::map<Facet, typename Tr::Cell::Surface_patch_index> border_facets_;
std::map<Facet, typename C3T3::Surface_patch_index> border_facets;
std::vector<Tet_with_ref> finite_cells;
//
int number_of_vertices = static_cast<int>(tr_periodic.number_of_vertices());
int number_of_facets = static_cast<int>(c3t3_periodic.number_of_facets());
int number_of_cells = static_cast<int>(c3t3_periodic.number_of_cells());
// number of reproductions over the different axes
int Ox_rn = ceil(occurrence_count[0]);
int Oy_rn = ceil(occurrence_count[1]);
int Oz_rn = ceil(occurrence_count[2]);
int occ_mult = Ox_rn * Oy_rn * Oz_rn;
#ifdef CGAL_PERIODIC_3_MESH_3_VERBOSE
std::cerr << "Expanding periodic mesh... " << std::endl;
std::cerr << "occurrences over each axis: "
<< Ox_rn << " " << Oy_rn << " " << Oz_rn << std::endl;
std::cerr << number_of_vertices << " vertices" << std::endl;
std::cerr << number_of_facets << " facets" << std::endl;
std::cerr << number_of_cells << " cells" << std::endl;
#endif
std::ofstream os("output_control.mesh");
os << std::setprecision(17);
// Vertices
int medit_number_of_vertices = (Ox_rn + 1) * (Oy_rn + 1) * (Oz_rn + 1) * number_of_vertices;
os << "MeshVersionFormatted 1\n"
<< "Dimension 3\n"
<< "Vertices\n" << medit_number_of_vertices << std::endl;
// Build the set of points that is needed to draw all the elements.
// On each axis, we repeat n+1 times the point, where 'n' is the number of
// instances of the mesh that will be printed over that axis. This is because
// a cell 'c' might have point(c,i) that is equal to v with an offset 2
boost::unordered_map<Vertex_handle, int> V;
int inum = 1; // '1' because medit ids start at 1
for(int i=0; i<=Oz_rn; ++i) {
for(int j=0; j<=Oy_rn; ++j) {
for(int k=0; k<=Ox_rn; ++k) {
for(Vertex_iterator vit = tr_periodic.vertices_begin(); vit != tr_periodic.vertices_end(); ++vit) {
if(i == 0 && j == 0 && k == 0)
V[vit] = inum++;
const Offset off(k, j, i);
const Weighted_point& p = tr_periodic.point(vit);
const Bare_point bp = tr_periodic.construct_point(p, off);
int id;
if(i >= 1 || j >= 1 || k >= 1)
id = 7;
else
id = tr_periodic.off_to_int(off);
os << CGAL::to_double(bp.x()) << ' '
<< CGAL::to_double(bp.y()) << ' '
<< CGAL::to_double(bp.z()) << ' ';
if(!distinguish_copies || occ_mult == 1)
os << get(vertex_pmap, vit) << '\n';
else
os << 32 * id + 1 << '\n';
points.push_back(Point_3(CGAL::to_double(bp.x()),
CGAL::to_double(bp.y()),
CGAL::to_double(bp.z())));
}
}
}
}
// Triangles
int medit_number_of_triangles = occ_mult * number_of_facets;
if(print_each_facet_twice)
medit_number_of_triangles *= 2;
os << "Triangles\n" << medit_number_of_triangles << std::endl;
for(int i=0; i<Oz_rn; ++i) {
for(int j=0; j<Oy_rn; ++j) {
for(int k=0; k<Ox_rn; ++k) {
const Offset off(k, j, i);
for(Facet_iterator fit = c3t3_periodic.facets_begin(); fit != c3t3_periodic.facets_end(); ++fit) {
typename Tr::Cell::Surface_patch_index surface_patch_id;
Facet facet;
for(int l=0; l<4; ++l) {
if(l == fit->second)
continue;
Cell_handle c = fit->first;
Vertex_handle v = c->vertex(l);
const Offset combined_off = tr_periodic.combine_offsets(
off, tr_periodic.int_to_off(c->offset(l)));
const int vector_offset = combined_off.x() +
combined_off.y() * (Ox_rn + 1) +
combined_off.z() * (Ox_rn + 1) * (Oy_rn + 1);
const int id = vector_offset * number_of_vertices + V[v];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
os << id << " ";
//facet[l] = id;
int temp_ = id;
facet[l] = temp_;
}
// For multiple copies, color to distinguish copies rather than to distinguish subdomains
//int temptest;
if(!distinguish_copies || occ_mult == 1){
os << get(facet_pmap, *fit) << '\n';
} else {
os << 1 + k + 3*j + 9*i << '\n';
}
surface_patch_id.first = 0;
surface_patch_id.second = 1;
border_facets.insert(std::make_pair(facet, surface_patch_id));
// Print triangle again if needed
if(print_each_facet_twice) {
for(int l=0; l<4; ++l) {
if(l == fit->second)
continue;
Cell_handle c = fit->first;
Vertex_handle v = c->vertex(l);
const Offset combined_off = tr_periodic.combine_offsets(
off, tr_periodic.int_to_off(c->offset(l)));
const int vector_offset = combined_off.x() +
combined_off.y() * (Ox_rn + 1) +
combined_off.z() * (Ox_rn + 1) * (Oy_rn + 1);
const int id = vector_offset * number_of_vertices + V[v];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
os << id << " ";
int temp_ = id;
facet[l] = temp_;
}
if(!distinguish_copies || occ_mult == 1)
os << get(facet_pmap_twice, *fit) << '\n';
else
os << 1 + k + 3*j + 9*i << '\n';
//surface_patch_id = ???;
//border_facets.insert(std::make_pair(facet, surface_patch_id));
}
}
}
}
}
// Tetrahedra
os << "Tetrahedra\n" << occ_mult * number_of_cells << std::endl;
for(int i=0; i<Oz_rn; ++i) {
for(int j=0; j<Oy_rn; ++j) {
for(int k=0; k<Ox_rn; ++k) {
const Offset off(k, j, i);
for(Cell_iterator cit = c3t3_periodic.cells_begin(); cit !=c3t3_periodic.cells_end(); ++cit) {
Tet_with_ref t;
for(int l=0; l<4; ++l) {
const Offset combined_off = tr_periodic.combine_offsets(
off, tr_periodic.int_to_off(cit->offset(l)));
const int vector_offset = combined_off.x() +
combined_off.y() * (Ox_rn + 1) +
combined_off.z() * (Ox_rn + 1) * (Oy_rn + 1);
const int id = vector_offset * number_of_vertices + V[cit->vertex(l)];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
os << id << " ";
t[l] = id - 1;
}
// For multiple copies, color to distinguish copies rather than to distinguish subdomains
if(!distinguish_copies || occ_mult == 1) {
os << get(cell_pmap, cit) << '\n';
t[4] = get(cell_pmap, cit);
} else {
os << 1 + k + 3*j + 9*i << '\n';
t[4] = 1 + k + 3*j + 9*i;
}
finite_cells.push_back(t);
}
}
}
}
os << "End" << std::endl;
//
//std::vector<typename Tr::Vertex_handle> vertices(0);
std::vector<typename Tr::Vertex_handle> vertices(points.size() + 1);
bool is_well_built = build_triangulation<Tr, true>(c3t3.triangulation(), points, finite_cells, border_facets, vertices, true/*verbose*/, false/*replace_domain*/);
// Check
std::cout << points.size() << " points" << std::endl;
std::cout << border_facets.size() << " border facets" << std::endl;
std::cout << finite_cells.size() << " cells" << std::endl;
std::cout << c3t3.number_of_facets() << " border facets expanded c3t3" << std::endl;
std::cout << c3t3.number_of_cells() << " cells expanded c3t3" << std::endl;
}
#ifdef CGAL_MESH_3_IO_VERBOSE
std::cerr << "done.\n";
#endif
} // namespace periodic_replicator
} // namespace CGAL
#endif // CGAL_PERIODIC_REPLICATOR_H

What is the problem with generated SPIR-V code and how to verify it?

I have some generated SPIR-V code which I want to use with the vulkan API. But I get an
Exception thrown at 0x00007FFB68D933CB (nvoglv64.dll) in vulkanCompute.exe: 0xC0000005: Access violation reading location 0x0000000000000008. when trying to create the pipline with vkCreateComputePipelines.
The API calls should be fine, because the same code works with a shader compiled with glslangValidator. Therefore I assume that the generated SPIR-V code must be illformed somehow.
I've checked the SPIR-V code with the validator tool from khronos, using spirv-val --target-env vulkan1.1 mainV.spv which exited without error. Anyhow it is also known that this tool is still incomplete.
I've also tried to use the Radeon GPU Analyzer to compile my SPIR-V code, which is also available online at the shader playground and this tool throws the error Error: Error: internal error: Bil::BilInstructionConvert::Create(60) Code Not Tested! which is not really helpful, but encourages the assumption that the code is malformed.
The SPIR-V code is unfortunately to long to post it here, but it is in the link of the shader playground.
Does anyone know what the problem is with my setting or has any idea how I can verify my SPIR-V code in a better way, without checking all 700 lines of code manually.
I don't thinkt the problem is there, but anyway here is the c++ host code:
#include "vulkan/vulkan.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#define BAIL_ON_BAD_RESULT(result) \
if (VK_SUCCESS != (result)) \
{ \
fprintf(stderr, "Failure at %u %s\n", __LINE__, __FILE__); \
exit(-1); \
}
VkResult vkGetBestComputeQueueNPH(vk::PhysicalDevice &physicalDevice, uint32_t &queueFamilyIndex)
{
auto properties = physicalDevice.getQueueFamilyProperties();
int i = 0;
for (auto prop : properties)
{
vk::QueueFlags maskedFlags = (~(vk::QueueFlagBits::eTransfer | vk::QueueFlagBits::eSparseBinding) & prop.queueFlags);
if (!(vk::QueueFlagBits::eGraphics & maskedFlags) && (vk::QueueFlagBits::eCompute & maskedFlags))
{
queueFamilyIndex = i;
return VK_SUCCESS;
}
i++;
}
i = 0;
for (auto prop : properties)
{
vk::QueueFlags maskedFlags = (~(vk::QueueFlagBits::eTransfer | vk::QueueFlagBits::eSparseBinding) & prop.queueFlags);
if (vk::QueueFlagBits::eCompute & maskedFlags)
{
queueFamilyIndex = i;
return VK_SUCCESS;
}
i++;
}
return VK_ERROR_INITIALIZATION_FAILED;
}
int main(int argc, const char *const argv[])
{
(void)argc;
(void)argv;
try
{
// initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo("VecAdd", 1, "Vulkan.hpp", 1, VK_API_VERSION_1_1);
// initialize the vk::InstanceCreateInfo
std::vector<char *> layers = {
"VK_LAYER_LUNARG_api_dump",
"VK_LAYER_KHRONOS_validation"
};
vk::InstanceCreateInfo instanceCreateInfo({}, &applicationInfo, static_cast<uint32_t>(layers.size()), layers.data());
// create a UniqueInstance
vk::UniqueInstance instance = vk::createInstanceUnique(instanceCreateInfo);
auto physicalDevices = instance->enumeratePhysicalDevices();
for (auto &physicalDevice : physicalDevices)
{
auto props = physicalDevice.getProperties();
// get the QueueFamilyProperties of the first PhysicalDevice
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
uint32_t computeQueueFamilyIndex = 0;
// get the best index into queueFamiliyProperties which supports compute and stuff
BAIL_ON_BAD_RESULT(vkGetBestComputeQueueNPH(physicalDevice, computeQueueFamilyIndex));
std::vector<char *>extensions = {"VK_EXT_external_memory_host", "VK_KHR_shader_float16_int8"};
// create a UniqueDevice
float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(computeQueueFamilyIndex), 1, &queuePriority);
vk::StructureChain<vk::DeviceCreateInfo, vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceShaderFloat16Int8Features> createDeviceInfo = {
vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo, 0, nullptr, static_cast<uint32_t>(extensions.size()), extensions.data()),
vk::PhysicalDeviceFeatures2(),
vk::PhysicalDeviceShaderFloat16Int8Features()
};
createDeviceInfo.get<vk::PhysicalDeviceFeatures2>().features.setShaderInt64(true);
createDeviceInfo.get<vk::PhysicalDeviceShaderFloat16Int8Features>().setShaderInt8(true);
vk::UniqueDevice device = physicalDevice.createDeviceUnique(createDeviceInfo.get<vk::DeviceCreateInfo>());
auto memoryProperties2 = physicalDevice.getMemoryProperties2();
vk::PhysicalDeviceMemoryProperties const &memoryProperties = memoryProperties2.memoryProperties;
const int32_t bufferLength = 16384;
const uint32_t bufferSize = sizeof(int32_t) * bufferLength;
// we are going to need two buffers from this one memory
const vk::DeviceSize memorySize = bufferSize * 3;
// set memoryTypeIndex to an invalid entry in the properties.memoryTypes array
uint32_t memoryTypeIndex = VK_MAX_MEMORY_TYPES;
for (uint32_t k = 0; k < memoryProperties.memoryTypeCount; k++)
{
if ((vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent) & memoryProperties.memoryTypes[k].propertyFlags &&
(memorySize < memoryProperties.memoryHeaps[memoryProperties.memoryTypes[k].heapIndex].size))
{
memoryTypeIndex = k;
std::cout << "found memory " << memoryTypeIndex + 1 << " out of " << memoryProperties.memoryTypeCount << std::endl;
break;
}
}
BAIL_ON_BAD_RESULT(memoryTypeIndex == VK_MAX_MEMORY_TYPES ? VK_ERROR_OUT_OF_HOST_MEMORY : VK_SUCCESS);
auto memory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memorySize, memoryTypeIndex));
auto in_buffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), bufferSize, vk::BufferUsageFlagBits::eStorageBuffer, vk::SharingMode::eExclusive));
device->bindBufferMemory(in_buffer.get(), memory.get(), 0);
// create a DescriptorSetLayout
std::vector<vk::DescriptorSetLayoutBinding> descriptorSetLayoutBinding{
{0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute}};
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), static_cast<uint32_t>(descriptorSetLayoutBinding.size()), descriptorSetLayoutBinding.data()));
std::cout << "Memory bound" << std::endl;
std::ifstream myfile;
myfile.open("shaders/MainV.spv", std::ios::ate | std::ios::binary);
if (!myfile.is_open())
{
std::cout << "File not found" << std::endl;
return EXIT_FAILURE;
}
auto size = myfile.tellg();
std::vector<unsigned int> shader_spv(size / sizeof(unsigned int));
myfile.seekg(0);
myfile.read(reinterpret_cast<char *>(shader_spv.data()), size);
myfile.close();
std::cout << "Shader size: " << shader_spv.size() << std::endl;
auto shaderModule = device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shader_spv.size() * sizeof(unsigned int), shader_spv.data()));
// create a PipelineLayout using that DescriptorSetLayout
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get()));
vk::ComputePipelineCreateInfo computePipelineInfo(
vk::PipelineCreateFlags(),
vk::PipelineShaderStageCreateInfo(
vk::PipelineShaderStageCreateFlags(),
vk::ShaderStageFlagBits::eCompute,
shaderModule.get(),
"_ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEE6VecAdd"),
pipelineLayout.get());
auto pipeline = device->createComputePipelineUnique(nullptr, computePipelineInfo);
auto descriptorPoolSize = vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 2);
auto descriptorPool = device->createDescriptorPool(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlags(), 1, 1, &descriptorPoolSize));
auto commandPool = device->createCommandPoolUnique(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), computeQueueFamilyIndex));
auto commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front());
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)));
commandBuffer->bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.get());
commandBuffer->dispatch(bufferSize / sizeof(int32_t), 1, 1);
commandBuffer->end();
auto queue = device->getQueue(computeQueueFamilyIndex, 0);
vk::SubmitInfo submitInfo(0, nullptr, nullptr, 1, &commandBuffer.get(), 0, nullptr);
queue.submit(1, &submitInfo, vk::Fence());
queue.waitIdle();
printf("all done\nWoohooo!!!\n\n");
}
}
catch (vk::SystemError &err)
{
std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1);
}
catch (std::runtime_error &err)
{
std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1);
}
catch (...)
{
std::cout << "unknown error\n";
exit(-1);
}
return EXIT_SUCCESS;
}
Well after checking out line per line it showed that the problem is when working with pointers of pointers. For me it is still not clear from the specification that it is not allowed, but it is understandable that it does not work with logical pointers.
Still the behaviour is strange that the validator is not able to note that and that compiling the SPIRV code crashes instead of throwing a clear error message.
So in the end, it was the Shader code which was wrong.

Missing data inside the dat file after writing operation

I am trying to save the data the user inputted inside a linked-list and then store those data inside a file so that I can retrieve them back when I enter the 2nd option(as per in the int main()). Unfortunately, after I wrote the data into the file and check back the file, I found out that my data is missing and the file is filled with garbage.so I cant retrieve the data back. Is there any solution to this problem?? Thank you.
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<fstream>
using namespace std;
fstream fp;
class List{
private:
struct node{
string name;
string surname;
int idNum;
string nationality;
int number;
node *next;
}nod;
node* head;
node* curr;
node* temp;
public:
List();
bool isEmpty(node *head){
if(head==NULL){
return true;
}
else
return false;
}
void AddNode(string addName,string addsurName,int addId,string addNation,int addNumber);
void insertAsFirst(string addName,string addsurName,int addId,string addNation,int addNum);
//void DeleteNode(int delData);
void printList();
void write_linky(string name,string surName,int idNum,string nation,int number);
void read_linky();
}lb;
List::List(){
head=NULL;
curr=NULL;
temp=NULL;
}
void List::insertAsFirst(string addName,string addsurName,int addId, string addNation,int addNum){
node *n = new node;
n->name=addName;
n->surname=addsurName;
n->idNum=addId;
n->nationality=addNation;
n->number=addNum;
n->next = NULL;
head = n;
//last = temp;
}
void List::AddNode(string addName,string addsurName,int addId,string addNation,int addNum){
if(isEmpty(head)){
insertAsFirst(addName,addsurName,addId,addNation,addNum);
}
else{
node* n = new node;
n->next=NULL;
n->name=addName;
n->surname=addsurName;
n->idNum=addId;
n->nationality=addNation;
n->number=addNum;
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = n;
}
}
void List::printList(){
curr=head;
cout << "\n\t\t\t\t CUSTOMER INFO" << endl << endl;
cout <<"NAME" << setw(20) << "SURNAME" << setw(20) << "ID NO. " << setw(20) << "NATIONALLITY" << setw(20) << "TELEPHONE" << endl << endl;
while(curr != NULL){
cout << curr -> name << setw(20) << curr -> surname << setw(20) << curr -> idNum << setw(20) << curr -> nationality << setw(20) << curr -> number << endl << endl;
curr=curr->next;
/*cout<<curr->number << endl;
cout<<curr->age << endl;
cout<<curr->idNum << endl;
cout<<curr->name<< endl;
cout<<curr->surname << endl;
cout<<curr->nationality << endl;
curr = curr->next;
}
*/
}
}
void List::write_linky(string name,string surName,int idNum,string nation,int number)
{
fp.open("Link.dat",ios::out|ios::app);
lb.AddNode(name,surName,idNum,nation,number);
lb.printList();
fp.write((char*)&nod,sizeof(node));
fp.close();
cout<<"\n\nThe Data Has Been Added ";
}
void List::read_linky(){
fp.open("Link.dat",ios::in);
while(fp.read((char*)&nod,sizeof(node)))
{
lb.printList();
//cout<<"\n\n=====================================================\n";
//getch();
}
fp.close();
//getch();
}
int main(){
List lb;
int idNum,number;
string name,surname,nationality;
char choice,ch;
cout<<"Please select your choice"<<endl;
cout<<"1.Book ticket"<<endl;
cout<<"2.view details"<<endl;
cin>>ch;
switch(ch){
case '1':
do{
cout<< "Enter name: ";
cin>>name;
cout<< "Enter surname: ";
cin>>surname;
cout<< "Enter identification number: ";
cin>>idNum;
cout<< "Enter your nationality: ";
cin>>nationality;
cout<< "Enter contact number: ";
cin>>number;
lb.write_linky(name,surname,idNum,nationality,number);
//lb.AddNode(number,age,idNum,name,surname,nationality);
cout<<"\n\nDo you want to add more entry?";
cin>>choice;
}while(choice=='y');
break;
case '2':
lb.read_linky();
break;
}
}
//lb.printList();
I've never done this but I'd guess string is a complex structure that doesn't lend itself to being written to disk like this. As a test change these to (say) char[255] and it might be happier.

Apache thrift multi client server

I am writing simple chat in Qt + Apache Thrift but right now I need to face a problem with connecting multiple clients. On first sight everything looks good and I cannot find where the problem is.
Here is my server main.cpp:
int main(int argc, char **argv)
{
int port = 9090;
::apache::thrift::stdcxx::shared_ptr<UsersStorageHandler> handler(new UsersStorageHandler());
::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new UsersStorageProcessor(handler));
::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
std::cout << "Users server started..." << std::endl;
std::cout << std::endl;
std::cout << std::endl;
server.serve();
return 0;
}
Here is my server handler.h:
class UsersStorageHandler : virtual public UsersStorageIf
{
public:
UsersStorageHandler();
int32_t subscribeUser(const std::string& username);
void unsubscribeUser(const int32_t userID);
private:
Users users;
};
Here is my server handler.cpp:
UsersStorageHandler::UsersStorageHandler()
{
srand(time(NULL));
}
int32_t UsersStorageHandler::subscribeUser(const std::string &username)
{
++idGenerator;
assert(username != "");
User user;
user.userId = idGenerator;
user.username = username;
user.colorR = (rand() % 255) + 0;
user.colorG = (rand() % 255) + 0;
user.colorB = (rand() % 255) + 0;
user.colorA = 0;
users[idGenerator] = user;
std::cout << "NEW USER CONNECTED" << std::endl;
std::cout << "==================" << std::endl;
std::cout << "Username:\t" << user.username << std::endl;
std::cout << "User ID:\t" << user.userId << std::endl;
std::cout << "User R:\t" << user.colorR << std::endl;
std::cout << "User G:\t" << user.colorG << std::endl;
std::cout << "User B:\t" << user.colorB << std::endl;
std::cout << "User A:\t" << user.colorA << std::endl;
std::cout << "==================" << std::endl;
std::cout << "CURRENT USERS COUNT:\t" << users.size() << std::endl;
std::cout << std::endl;
std::cout << std::endl;
/*
* SEND TO CLIENT INFO ABOUT NEW USER HERE
*/
return idGenerator;
}
void UsersStorageHandler::unsubscribeUser(const int32_t userID)
{
auto index = users.find(userID);
assert(index != users.end());
users.erase(index);
std::cout << "USER DISCONNECTED" << std::endl;
std::cout << "=================" << std::endl;
std::cout << "USER WITH ID " << userID << " ERASED" << std::endl;
std::cout << "USERS COUNT:\t" << users.size() << std::endl;
std::cout << std::endl;
std::cout << std::endl;
/*
* SEND TO CLIENT INFO ABOUT NEW USER HERE
*/
}
And right here is a method for connect to the server in client app:
void MainWindow::connectToServers(const std::string &ip, const uint32_t &port, const std::string &nick)
{
m_usersServerIP = ip;
m_usersServerPort = port;
try
{
::apache::thrift::stdcxx::shared_ptr<TTransport> socket(new TSocket(m_usersServerIP, m_usersServerPort));
::apache::thrift::stdcxx::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
::apache::thrift::stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
m_usersServerClient = std::make_shared<UsersStorageClient>(protocol);
transport->open();
m_clientID = m_usersServerClient.get()->subscribeUser(nick);
QMessageBox::information(this, "Connected",
"You are connected "
"with users server");
createAndRegisterUsersServerReactor();
activateChatScreen();
}
catch (const std::exception &e)
{
qDebug() << e.what();
}
qDebug() << "ID FROM SERVER:\t" << m_clientID;
}
As far as I checked right now it is working like this:
Created two instances of client app. In one instance fill nickname, ip, port and clicked connect (connectToServers method). Client connected. In another instance done the same but after clicked connected ... nothing happens. App freezes at this line:
m_clientID = m_usersServerClient.get()->subscribeUser(nick);
After closing first client, second one connects to the server.
A TSimplerServer supports a single connection. You should try using TThreadedServer to support multiple simultaneous clients.
As Chris mentioned above either make a Threaded server to server multiple requests simultaneously. For me I have created a non-blocking server as below to be able to serve multiple clients in async manner for loose coupling.
public static void start(dataClass configData, String env, int port) throws TTransportException {
TNonblockingServerTransport transport = new TNonblockingServerSocket(port);
TNonblockingServer.Args nBlockServer = new TNonblockingServer.Args(transport);
ccmProviderServiceImpl impl = new ccmProviderServiceImpl(configData, env);
Processor<ccmProviderServiceImpl> processor = new ccmProviderService.Processor<>(impl);
TServer server = new TNonblockingServer(nBlockServer.processor(processor));
//custom event handling for tracking
ccmServerEventHandler cse = new ccmServerEventHandler();
server.setServerEventHandler(cse);
server.serve();
}

where is boost property_tree::empty_ptree?

I'm using boots's property_tree library. I'm looking for a way to get a child node from a ptree object, but return an empty ptree if failed. I came across a nice example in property_tree/examples/empty_ptree_trick.cpp:
void process_settings(const std::string &filename)
{
ptree pt;
read_info(filename, pt);
const ptree &settings = pt.get_child("settings", empty_ptree<ptree>());
std::cout << "\n Processing " << filename << std::endl;
std::cout << " Setting 1 is " << settings.get("setting1", 0) << std::endl;
std::cout << " Setting 2 is " << settings.get("setting2", 0.0) << std::endl;
std::cout << " Setting 3 is " << settings.get("setting3", "default") << std::endl;
}
which does exactly what I need. The problem is that the compiler complains that empty_ptree() function is not a member of boost:property_tree. Any ideas where empty_ptree() is?
I'm using boost 1.44 on VS2010.
I have just blown a full day trying to answer that question!
This was my solution. Firstly I used pointers, and not references as you have to initialize them immediately. Then I just caught the exception and added a new ptree.
using namespace boost::property_tree;
ptree r_pt;
ptree *c_pt;
read_xml( "file.xml" , r_pt);
try {
c_pt = &(r_pt.get_child( "example" ));
}
catch (ptree_bad_path) {
c_pt = &(r_pt.put_child( "example", ptree() ));
}
std::cout << "Setting 1 is " << c_pt.get("setting1", 0) << std::endl;
From what I could pick up they expect us to use the boost::optional type. But I'm just a beginner..
EDIT
I just found the implementation of empty_ptree<>.
template<class Ptree>
inline const Ptree &empty_ptree()
{
static Ptree pt;
return pt;
}
I think you can just add this to your code and use it as described in the empty_ptree_trick.cpp, but I am sticking with my solution for now untill I find out how its actually supposed to be done.
void process_settings(const std::string &filename)
{
ptree pt;
read_info(filename, pt);
const ptree &settings = pt.get_child("settings", ptree());
std::cout << "\n Processing " << filename << std::endl;
std::cout << " Setting 1 is " << settings.get("setting1", 0) << std::endl;
std::cout << " Setting 2 is " << settings.get("setting2", 0.0) << std::endl;
std::cout << " Setting 3 is " << settings.get("setting3", "default") << std::endl;
}
Note, that will prevent throwing an instance of 'boost::wrapexceptboost::property_tree::ptree_bad_path'