NEST  2.6.0,not_revisioned_source_dir@0
free_layer.h
Go to the documentation of this file.
1 /*
2  * free_layer.h
3  *
4  * This file is part of NEST.
5  *
6  * Copyright (C) 2004 The NEST Initiative
7  *
8  * NEST is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * NEST is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef FREE_LAYER_H
24 #define FREE_LAYER_H
25 
26 #include <limits>
27 #include <sstream>
28 #include <algorithm>
29 #include "layer.h"
30 #include "topology_names.h"
31 #include "dictutils.h"
32 #include "ntree_impl.h"
33 
34 namespace nest
35 {
36 
40  template <int D>
41  class FreeLayer: public Layer<D>
42  {
43  public:
44  Position<D> get_position(index sind) const;
45  void set_status(const DictionaryDatum&);
46  void get_status(DictionaryDatum&) const;
47 
48  protected:
49 
55  template <class Ins>
56  void communicate_positions_(Ins iter, const Selector& filter);
57 
58  void insert_global_positions_ntree_(Ntree<D,index> & tree, const Selector& filter);
59  void insert_global_positions_vector_(std::vector<std::pair<Position<D>,index> > & vec, const Selector& filter);
60  void insert_local_positions_ntree_(Ntree<D,index> & tree, const Selector& filter);
61 
63  std::vector<Position<D> > positions_;
64 
67  public:
68  index get_gid() const { return gid_; }
70  bool operator<(const NodePositionData& other) const
71  { return gid_<other.gid_; }
72  bool operator==(const NodePositionData& other) const
73  { return gid_==other.gid_; }
74 
75  private:
78  };
79 
80  };
81 
82  template <int D>
84  {
86 
87  // Read positions from dictionary
88  if(d->known(names::positions)) {
89  TokenArray pos = getValue<TokenArray>(d, names::positions);
90  if(this->global_size()/this->depth_ != pos.size()) {
91  std::stringstream expected;
92  std::stringstream got;
93  expected << "position array with length " << this->global_size()/this->depth_;
94  got << "position array with length" << pos.size();
95  throw TypeMismatch(expected.str(), got.str());
96  }
97 
98  positions_.clear();
99  positions_.reserve(this->local_size());
100 
101  const index nodes_per_depth = this->global_size()/this->depth_;
102  const index first_lid = this->nodes_[0]->get_lid();
103 
104  for(vector<Node*>::iterator i = this->local_begin(); i != this->local_end(); ++i) {
105 
106  // Nodes are grouped by depth. When lid % nodes_per_depth ==
107  // first_lid, we have "wrapped around", and do not need to gather
108  // more positions.
109  if ( ((*i)->get_lid() != first_lid) &&
110  ((*i)->get_lid() % nodes_per_depth == first_lid ) ) {
111  break;
112  }
113 
114  Position<D> point =
115  getValue<std::vector<double_t> >(pos[(*i)->get_lid() % nodes_per_depth]);
116 
117  if (not ((point >= this->lower_left_) and (point < this->lower_left_+this->extent_)))
118  throw BadProperty("Node position outside of layer");
119 
120  positions_.push_back(point);
121 
122  }
123 
124  }
125  }
126 
127  template <int D>
129  {
131 
132  DictionaryDatum topology_dict = getValue<DictionaryDatum>((*d)[names::topology]);
133 
135  for(typename std::vector<Position<D> >::const_iterator it = positions_.begin();
136  it != positions_.end(); ++it) {
137  points.push_back(it->getToken());
138  }
139  def2<TokenArray, ArrayDatum>(topology_dict, names::positions, points);
140 
141  }
142 
143  template <int D>
145  {
146  // If sind > positions_.size(), we must have "wrapped around" when
147  // storing positions, so we may simply mod with the size
148  return positions_[sind % positions_.size()];
149  }
150 
151  template <int D>
152  template <class Ins>
153  void FreeLayer<D>::communicate_positions_(Ins iter, const Selector& filter)
154  {
155  assert(this->nodes_.size() >= positions_.size());
156 
157  // This array will be filled with GID,pos_x,pos_y[,pos_z] for local nodes:
158  std::vector<double_t> local_gid_pos;
159  std::vector<Node*>::const_iterator nodes_begin;
160  std::vector<Node*>::const_iterator nodes_end;
161 
162  // Nodes in the subnet are grouped by depth, so to select by depth, we
163  // just adjust the begin and end pointers:
164  if (filter.select_depth()) {
165  local_gid_pos.reserve((D+1)*(this->nodes_.size()/this->depth_ + 1));
166  nodes_begin = this->local_begin(filter.depth);
167  nodes_end = this->local_end(filter.depth);
168  } else {
169  local_gid_pos.reserve((D+1)*this->nodes_.size());
170  nodes_begin = this->local_begin();
171  nodes_end = this->local_end();
172  }
173 
174  for(std::vector<Node*>::const_iterator node_it = nodes_begin; node_it != nodes_end; ++node_it) {
175 
176  if (filter.select_model() && ((*node_it)->get_model_id() != filter.model))
177  continue;
178 
179  // Push GID into array to communicate
180  local_gid_pos.push_back((*node_it)->get_gid());
181  // Push coordinates one by one
182  for(int j=0;j<D;++j)
183  local_gid_pos.push_back(positions_[(*node_it)->get_subnet_index() % positions_.size()][j]);
184  }
185 
186  // This array will be filled with GID,pos_x,pos_y[,pos_z] for global nodes:
187  std::vector<double_t> global_gid_pos;
188  std::vector<int> displacements;
189  Communicator::communicate(local_gid_pos,global_gid_pos,displacements);
190 
191  // To avoid copying the vector one extra time in order to sort, we
192  // sneakishly use reinterpret_cast
193  NodePositionData * pos_ptr;
194  NodePositionData * pos_end;
195  pos_ptr = reinterpret_cast<NodePositionData*>(&global_gid_pos[0]);
196  pos_end = pos_ptr + global_gid_pos.size()/(D+1);
197 
198  // Get rid of any multiple entries
199  std::sort(pos_ptr, pos_end);
200  pos_end = std::unique(pos_ptr, pos_end);
201 
202  // Unpack GIDs and coordinates
203  for(;pos_ptr < pos_end; pos_ptr++) {
204  *iter++ = std::pair<Position<D>,index>(pos_ptr->get_position(), pos_ptr->get_gid());
205  }
206 
207  }
208 
209  template <int D>
211  {
212 
213  communicate_positions_(std::inserter(tree, tree.end()), filter);
214 
215  }
216 
217  template <int D>
219  {
220  assert(this->nodes_.size() >= positions_.size());
221 
222  std::vector<Node*>::const_iterator nodes_begin;
223  std::vector<Node*>::const_iterator nodes_end;
224 
225  // Nodes in the subnet are grouped by depth, so to select by depth, we
226  // just adjust the begin and end pointers:
227  if (filter.select_depth()) {
228  nodes_begin = this->local_begin(filter.depth);
229  nodes_end = this->local_end(filter.depth);
230  } else {
231  nodes_begin = this->local_begin();
232  nodes_end = this->local_end();
233  }
234 
235  for(std::vector<Node*>::const_iterator node_it = nodes_begin; node_it != nodes_end; ++node_it) {
236 
237  if (filter.select_model() && ((*node_it)->get_model_id() != filter.model))
238  continue;
239 
240  tree.insert(std::pair<Position<D>,index>(positions_[(*node_it)->get_subnet_index() % positions_.size()],(*node_it)->get_gid()));
241  }
242 
243  }
244 
245  // Helper function to compare GIDs used for sorting (Position,GID) pairs
246  template<int D>
247  static bool gid_less(const std::pair<Position<D>,index>& a, const std::pair<Position<D>,index>& b)
248  {
249  return a.second < b.second;
250  }
251 
252  template <int D>
253  void FreeLayer<D>::insert_global_positions_vector_(std::vector<std::pair<Position<D>,index> > & vec, const Selector& filter)
254  {
255 
256  communicate_positions_(std::back_inserter(vec), filter);
257 
258  // Sort vector to ensure consistent results
259  std::sort(vec.begin(),vec.end(),gid_less<D>);
260 
261  }
262 
263 } // namespace nest
264 
265 #endif
size_t index
Unsigned long type for enumerations.
Definition: nest.h:109
bool operator<(const NodePositionData &other) const
Definition: free_layer.h:70
Position< D > get_position(index sind) const
Get position of node.
Definition: free_layer.h:144
const Name d("d")
Specific to Izhikevich 2003.
Definition: nest_names.h:83
Exception to be thrown if a given SLI type does not match the expected type.
Definition: sliexceptions.h:147
void get_status(DictionaryDatum &) const
Export properties of the layer by setting entries in the status dictionary.
Definition: layer_impl.h:79
std::vector< Position< D > > positions_
Vector of positions. Should match node vector in Subnet.
Definition: free_layer.h:63
bool operator==(const NodePositionData &other) const
Definition: free_layer.h:72
Contains rules for selecting nodes from a layer when connecting.
Definition: selector.h:36
Definition: tokenarray.h:62
const Name points("points")
Definition: topology_names.h:55
const Name a("a")
Specific to Brette & Gerstner 2005 (aeif_cond-*)
Definition: nest_names.h:41
void get_status(DictionaryDatum &) const
Definition: free_layer.h:128
assert(pNet!=0)
index get_gid() const
Definition: free_layer.h:68
A Ntree object represents a subtree or leaf in a Ntree structure.
Definition: ntree.h:49
bool select_depth() const
Definition: selector.h:58
static void communicate(std::vector< uint_t > &send_buffer, std::vector< uint_t > &recv_buffer, std::vector< int > &displacements)
communicate (on-grid) if compiled without MPI
Definition: communicator.cpp:239
Abstract base class for Layer of given dimension (D=2 or 3).
Definition: connection_creator.h:39
const Name other("other")
Node type.
Definition: nest_names.h:216
iterator insert(Position< D > pos, const T &node)
Traverse quadtree structure from current ntree.
Definition: ntree_impl.h:362
long_t model
The model to select, or -1 if all models are allowed.
Definition: selector.h:69
const Name positions("positions")
Definition: topology_names.h:53
void set_status(const DictionaryDatum &)
Definition: free_layer.h:83
double_t pos_[D]
Definition: free_layer.h:77
Layer with free positioning of neurons, positions specified by user.
Definition: free_layer.h:41
const Name topology("topology")
Definition: topology_names.h:54
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition: exceptions.h:420
size_t size(void) const
Return number of elements in the array.
Definition: tokenarray.h:142
void insert_local_positions_ntree_(Ntree< D, index > &tree, const Selector &filter)
Insert local position info into ntree.
Definition: free_layer.h:218
void insert_global_positions_vector_(std::vector< std::pair< Position< D >, index > > &vec, const Selector &filter)
Insert global position info into vector.
Definition: free_layer.h:253
double double_t
Double precision floating point numbers.
Definition: nest.h:93
long_t depth
The depth to select, or -1 if all depths are allowed.
Definition: selector.h:73
const Name b("b")
Specific to Brette & Gerstner 2005 (aeif_cond-*)
Definition: nest_names.h:58
void insert_global_positions_ntree_(Ntree< D, index > &tree, const Selector &filter)
Insert global position info into ntree.
Definition: free_layer.h:210
This class is used when communicating positions across MPI procs.
Definition: free_layer.h:66
double_t gid_
Definition: free_layer.h:76
void set_status(const DictionaryDatum &)
Change properties of the layer according to the entries in the dictionary.
Definition: layer_impl.h:58
void communicate_positions_(Ins iter, const Selector &filter)
Communicate positions across MPI processes.
Definition: free_layer.h:153
static bool gid_less(const std::pair< Position< D >, index > &a, const std::pair< Position< D >, index > &b)
Definition: free_layer.h:247
bool select_model() const
Definition: selector.h:53
iterator end()
Definition: ntree.h:261
Position< D > get_position() const
Definition: free_layer.h:69