CartesianGraphFactory.hpp 9.67 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*
 * CartesianGraphFactory.hpp
 *
 *  Created on: Nov 28, 2014
 *      Author: i-bird
 */

#ifndef CARTESIANGRAPHFACTORY_HPP_
#define CARTESIANGRAPHFACTORY_HPP_

incardon's avatar
incardon committed
11 12
#include "Vector/map_vector.hpp"
#include "Graph/map_graph.hpp"
13
#include "Grid/grid_sm.hpp"
14
#include "Space/Shape/Box.hpp"
incardon's avatar
incardon committed
15
#include "Space/Shape/HyperCube.hpp"
16

incardon's avatar
incardon committed
17
/*! \brief This class work as a functor
18
 *
incardon's avatar
incardon committed
19 20 21 22 23 24 25 26
 * For each number in the boost::mpl::vector (for example 3 6) set the properties of the vertex at the
 * specified id (3 6) with pos[d] * spacing[d] with d running from 0 to 1, pos[d] the position id of the vertex
 * spacing the grid spacing
 *
 * Example
 *
 * if we give a grid_key of dimension 2 4x4 the expression "pos[d] * spacing[d]"
 * will assume the value
27
 *
incardon's avatar
incardon committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41
 * (0.0 0.0) (0.25 0.0) ...... (1.0 0.0)
 * (0.0 0.25)................. (1.0 0.25)
 * ....................................
 * (0.0 1.0).................. (1.0 1.0)
 *
 * and the properties 3 6 will be filled with the numbers 0.0 0.0    .......  1.0 1.0
 * progressively
 *
 * \tparam dim Dimensionality of the cartesian grid
 * \tparam dT type of the domain
 * \tparam G_v vertex type object
 * \tparam v boost::mpl::vector containing all the index to fill
 * \tparam is_stub when is true, produce a trivial operator(),
 *         to use when v is an empty vector to avoid compilation error
42 43 44
 *
 */

incardon's avatar
incardon committed
45 46
template<unsigned int dim, typename dT, typename G_v, typename v, bool is_stub>
class fill_prop
47
{
incardon's avatar
incardon committed
48 49 50 51 52 53 54 55
	//! Reference to an array containing the spacing
	const dT (& szd)[dim];

	//! grid_key_dx Reference containing the actual position
	grid_key_dx<dim> & gk;

	//! Vertex object to fill
	G_v & g_v;
56 57 58

public:

incardon's avatar
incardon committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
	//! Fill the object from where to take the properties
	fill_prop(G_v & g_v , const dT (& szd)[dim], grid_key_dx<dim> & gk)
	:szd(szd),gk(gk),g_v(g_v)
	{}

	//! It call the function for each property we want to copy
    template<typename T>
    void operator()(T& t) const
    {
    	typedef typename boost::fusion::result_of::at<v,boost::mpl::int_<T::value>>::type t_val;

    	g_v.template get<t_val::value>() = gk.get(T::value) * szd[T::value];
    }
};

/*! \brief Graph constructor function specialization
 *
 * On C++ partial function specialization is not allowed, so we need a class to do it
 *
 * \see CartesianGraphFactory method construct
 *
 */

template<unsigned int dim, typename Graph, unsigned int se,typename T, unsigned int dim_c, int... pos>
class Graph_constructor_impl
{
public:
	//! Construct cartesian graph
incardon's avatar
incardon committed
87
	static Graph construct(size_t (& sz)[dim], Box<dim,T> dom)
88 89 90 91 92 93 94 95 96 97 98 99 100 101
	{
		// Calculate the size of the hyper-cubes on each dimension

		T szd[dim];

		for (int i = 0 ; i < dim ; i++)
		{szd[i] = (dom.getHigh(i) - dom.getLow(i)) / sz[i];}

		//! Construct an hyper-cube of dimension dim

		HyperCube<dim> hc;

		// Construct a grid info

102
		grid_sm<dim,void> g(sz);
103 104 105 106 107 108 109 110 111 112

		// Create a graph with the number of vertices equal to the number of
		// grid point

		//! Graph to construct

		Graph gp(g.size());

		/******************
		 *
incardon's avatar
incardon committed
113 114
		 * Create the edges and fill spatial
		 * information properties
115 116 117 118 119 120 121 122 123
		 *
		 ******************/

		//! Construct a key iterator

		grid_key_dx_iterator<dim> k_it(g);

		//! Iterate through all the elements

incardon's avatar
incardon committed
124
		while (k_it.isNext())
125 126 127
		{
			grid_key_dx<dim> key = k_it.get();

incardon's avatar
incardon committed
128 129 130 131 132 133 134 135 136 137
			// Vertex object
			auto obj = gp.vertex(g.LinId(key));

			// vertex spatial properties functor
			fill_prop<dim,T,decltype(gp.vertex(g.LinId(key))), typename to_boost_mpl<pos...>::type, sizeof...(pos) == 0 > flp(obj,szd,key);

			// fill properties

			boost::mpl::for_each< boost::mpl::range_c<int,0,sizeof...(pos)> >(flp);

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
			// Get the combinations of dimension d

			for (int d = dim-1 ; d >= dim_c ; d--)
			{
				// create the edges for that dimension

				std::vector<comb<dim>> c = hc.getCombinations_R(d);

				// for each combination calculate a safe linearization and create an edge

				for (int j = 0 ; j < c.size() ; j++)
				{
					// Calculate the element size

					T ele_sz = 0;

					// for each dimension multiply and reduce

					for (int s = 0 ; s < dim ; s++)
					{
incardon's avatar
incardon committed
158
						ele_sz += szd[s] * abs(c[j][s]);
159 160 161 162 163 164
					}

					// Calculate the end point vertex id
					// Calculate the start point id

					size_t start_v = g.LinId(key);
incardon's avatar
incardon committed
165
					size_t end_v = g.template LinId<CheckExistence>(key,c[j].getComb());
166

incardon's avatar
incardon committed
167
					// Add an edge and set the the edge property to the size of the face (communication weight)
incardon's avatar
incardon committed
168
					gp.template addEdge<CheckExistence>(start_v,end_v).template get<se>() = ele_sz;
169 170 171
				}
			}

incardon's avatar
incardon committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
			// Fill vertex properties



			++k_it;
		}

		return gp;
	}
};

/*! \brief Graph constructor function specialization
 *
 * On C++ partial function specialization is not allowed, so we need a class to do it
 * This specialization handle the case when we have NO_EDGE option active
 *
 * \see CartesianGraphFactory method construct
 *
 */

template<unsigned int dim, typename Graph,typename T, unsigned int dim_c, int... pos>
class Graph_constructor_impl<dim,Graph,NO_EDGE,T,dim_c,pos...>
{
public:
	//! Construct cartesian graph
incardon's avatar
incardon committed
197
	static Graph construct(size_t ( & sz)[dim], Box<dim,T> dom)
incardon's avatar
incardon committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211
	{
		// Calculate the size of the hyper-cubes on each dimension

		T szd[dim];

		for (int i = 0 ; i < dim ; i++)
		{szd[i] = (dom.getHigh(i) - dom.getLow(i)) / sz[i];}

		//! Construct an hyper-cube of dimension dim

		HyperCube<dim> hc;

		// Construct a grid info

212
		grid_sm<dim,void> g(sz);
incardon's avatar
incardon committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

		// Create a graph with the number of vertices equal to the number of
		// grid point

		//! Graph to construct

		Graph gp(g.size());

		/******************
		 *
		 * Create the edges and fill spatial
		 * information properties
		 *
		 ******************/

		//! Construct a key iterator

		grid_key_dx_iterator<dim> k_it(g);

		//! Iterate through all the elements

		while (k_it.isNext())
		{
			grid_key_dx<dim> key = k_it.get();

			// Vertex object
			auto obj = gp.vertex(g.LinId(key));

			// vertex spatial properties functor
			fill_prop<dim,T,decltype(gp.vertex(g.LinId(key))), typename to_boost_mpl<pos...>::type, sizeof...(pos) == 0 > flp(obj,szd,key);

			// fill properties

			boost::mpl::for_each< boost::mpl::range_c<int,0,sizeof...(pos)> >(flp);

			// Get the combinations of dimension d

			for (int d = dim-1 ; d >= dim_c ; d--)
			{
				// create the edges for that dimension

				std::vector<comb<dim>> c = hc.getCombinations_R(d);

				// for each combination calculate a safe linearization and create an edge

				for (int j = 0 ; j < c.size() ; j++)
				{
					// Calculate the element size

					T ele_sz = 0;

					// for each dimension multiply and reduce

					for (int s = 0 ; s < dim ; s++)
					{
						ele_sz += szd[s] * abs(c[j][s]);
					}

					// Calculate the end point vertex id
					// Calculate the start point id

					size_t start_v = g.LinId(key);
					size_t end_v = g.template LinId<CheckExistence>(key,c[j].getComb());

					// Add an edge and set the the edge property to the size of the face (communication weight)
					gp.template addEdge<CheckExistence>(start_v,end_v);
				}
			}

			// Fill vertex properties

284 285 286
			++k_it;
		}

incardon's avatar
incardon committed
287
		return gp;
incardon's avatar
incardon committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
	}
};


/*! \brief This class work as a functor
 *
 * For each number in the boost::mpl::vector (for example 3 6) set the properties of the vertex at the
 * specified id (3 6) with pos[d] * spacing[d] with d running from 0 to 1, pos[d] the position id of the vertex
 * spacing the grid spacing
 *
 * Example
 *
 * if we give a grid_key of dimension 2 4x4 the expression "pos[d] * spacing[d]"
 * will assume the value
 *
 * (0.0 0.0) (0.25 0.0) ...... (1.0 0.0)
 * (0.0 0.25)................. (1.0 0.25)
 * ....................................
 * (0.0 1.0).................. (1.0 1.0)
 *
 * and the properties 3 6 will be filled with the numbers 0.0 0.0    .......  1.0 1.0
 * progressively
 *
 * \tparam dim Dimensionality of the cartesian grid
 * \tparam dT type of the domain
 * \tparam G_v vertex type object
 * \tparam v boost::mpl::vector containing all the index to fill
 *
 */

template<unsigned int dim, typename dT, typename G_v, typename v>
class fill_prop<dim,dT,G_v,v,true>
{

public:

	//! Fill the object from where to take the properties
	fill_prop(G_v & g_v , const dT (& szd)[dim], grid_key_dx<dim> & gk)
	{}

	//! It call the function for each property we want to copy
    template<typename T>
    void operator()(T& t) const
    {}
};

/*! \brief This class construct a cartesian graph
 *
 * This class construct a cartesian graph
 *
 * \param dim dimensionality of the cartesian grid
 *
 */

template<unsigned int dim, typename Graph>
class CartesianGraphFactory
{

public:
347

incardon's avatar
incardon committed
348 349 350 351 352 353 354 355
	/*!
	 *
	 * \brief Construct a cartesian graph, with V and E edge properties
	 *
	 * Construct a cartesian graph, with V and E edge properties
	 *
	 * Each vertex is a subspace (Hyper-cube) of dimension dim, each vertex is
	 * connected with an edge if two vertex (Hyper-cube) share a element of dimension grater than
incardon's avatar
incardon committed
356 357
	 * dim_c. One property can be used to store the contact size or the d-dimensional
	 * surface in common between two connected hyper-cube.
incardon's avatar
incardon committed
358 359 360 361
	 *
	 * \param sz Vector that store the size of the grid on each dimension
	 * \param dom Box enclosing the physical domain
	 *
incardon's avatar
incardon committed
362 363 364
	 * \tparam se Indicate which properties fill with the contact size. The
	 *           contact size is the point, line , surface, d-dimensional object size
	 *           in contact (in common) between two hyper-cube. NO_EDGE indicate
incardon's avatar
incardon committed
365 366 367
	 *           no property will store this information
	 * \tparam T type of the domain like (int real complex ... )
	 * \tparam dim_c Connectivity dimension
incardon's avatar
incardon committed
368
	 * \tparam pos... (optional)one or more integer indicating the spatial properties
incardon's avatar
incardon committed
369 370 371
	 *
	 */
	template <unsigned int se,typename T, unsigned int dim_c, int... pos>
incardon's avatar
incardon committed
372
	static Graph construct(size_t (& sz)[dim], Box<dim,T> dom)
incardon's avatar
incardon committed
373 374
	{
		return Graph_constructor_impl<dim,Graph,se,T,dim_c,pos...>::construct(sz,dom);
375 376 377 378
	}
};

#endif /* CARTESIANGRAPHFACTORY_HPP_ */