KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
octree_binary_cell.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Abel
11 //
12 
13 #pragma once
14 
15 // System includes
16 #include <string>
17 #include <iostream>
18 
19 // External includes
20 
21 // Project includes
22 #ifdef KRATOS_INDEPENDENT
23 #else
24 #include "includes/define.h"
25 #endif
26 
27 namespace Kratos {
30 
34 
36 
69  template<class TConfiguration>
71  public:
74 
76  //KRATOS_CLASS_POINTER_DEFINITION(OctreeBinaryCell);
77 
78  typedef typename TConfiguration::data_type data_type;
79 
80  typedef TConfiguration configuration_type;
81 
82  typedef typename TConfiguration::pointer_type pointer_type;
83 
84  typedef std::vector<pointer_type> object_container_type;
85 
86  typedef std::size_t key_type;
87 
88  static constexpr std::size_t CHILDREN_NUMBER = 8;
89  static constexpr std::size_t DIMENSION = TConfiguration::DIMENSION;
90  static constexpr std::size_t MAX_LEVEL = TConfiguration::MAX_LEVEL;
91  static constexpr std::size_t ROOT_LEVEL = MAX_LEVEL - 1;
92  static constexpr std::size_t MIN_LEVEL = TConfiguration::MIN_LEVEL;
93 
94  enum {
95  LEFT = 0,
96  RIGHT = 1,
97  BACK = 2,
98  FRONT = 3,
99  BOTTOM = 4,
100  TOP = 6
101  };
102 
106 
108 
109  explicit OctreeBinaryCell(char Level = ROOT_LEVEL) : level_(Level), children_(NULL), data_(NULL) {
110  for (std::size_t i = 0; i < DIMENSION; i++)
111  min_key_[i] = 0;
112  }
113 
115 
116  virtual ~OctreeBinaryCell() {
117 
118  if (data_) configuration_type::DeleteData(data_);
119  delete [] children_;
120  }
121 
122  void DeleteChildren() {
123  delete [] children_;
124  children_=NULL;
125  }
126  void DeleteData() {
127  if (data_){
128  configuration_type::DeleteData(data_);
129  data_=NULL;
130  }
131  }
135 
136 
140 
141  std::size_t GetChildIndex(key_type x_key, key_type y_key, key_type z_key) const {
142  char next_level = ( char)( level_ - 1);
143  key_type level_bit = 1 << next_level;
144  return (((x_key & level_bit) >> next_level) + (((y_key & level_bit) >> next_level) << 1) + (((z_key & level_bit) >> next_level) << 2));
145  }
146 
148  if (level_ == 0)
149  return 1;
150  if(children_)
151  return 1;
152 
153  children_ = new OctreeBinaryCell[CHILDREN_NUMBER];
154 
155  char next_level = ( char)( level_ - 1);
156 
157  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++) {
158  children_[i].SetMinKey(min_key_[0] | ((i & 1) << next_level), min_key_[1] | (((i & 2) >> 1)) << next_level, min_key_[2] | (((i & 4) >> 2)) << next_level);
159  children_[i].SetLevel(next_level);
160  }
161 
162  return 0; // Zero says no error!
163  }
164 
165  void GetMinPointNormalized(double* min_point) const {
166  for (std::size_t i = 0; i < DIMENSION; i++) {
167  min_point[i] = GetCoordinateNormalized(min_key_[i]);
168  }
169  }
170 
171  void GetMaxPointNormalized(double* max_point) const {
172  double size = CalcSizeNormalized();
173  for (std::size_t i = 0; i < DIMENSION; i++) {
174  max_point[i] = GetCoordinateNormalized(min_key_[i]) + size;
175  }
176  }
177 
178  int GetLeftKey(key_type* keys) const {
179 // if (min_key_[0] >= static_cast<key_type> (1 << level_)) {
180  if (min_key_[0] >= 1) {
181  keys[0] = min_key_[0] - 1;
182  keys[1] = min_key_[1];
183  keys[2] = min_key_[2];
184  return 1; // There is a neighbour
185  }
186  return 0; // There is no neighbour
187  }
188 
189  int GetRightKey(key_type* keys) const {
190  if (min_key_[0] < static_cast<key_type> ((1 << ROOT_LEVEL) - (1 << level_))) {
191  keys[0] = min_key_[0] + (static_cast<key_type>(1) << level_);
192  keys[1] = min_key_[1];
193  keys[2] = min_key_[2];
194  return 1; // There is a neighbour
195  }
196  return 0; // There is no neighbour
197  }
198 
199  int GetBackKey(key_type* keys) const {
200 // if (min_key_[1] >= static_cast<key_type> (1 << level_)) {
201  if (min_key_[1] >= 1) {
202  keys[0] = min_key_[0];
203  keys[1] = min_key_[1] - 1;
204  keys[2] = min_key_[2];
205  return 1; // There is a neighbour
206  }
207  return 0; // There is no neighbour
208  }
209 
210  int GetFrontKey(key_type* keys) const {
211  if (min_key_[1] < static_cast<key_type> ((1 << ROOT_LEVEL) - (1 << level_))) {
212  keys[0] = min_key_[0];
213  keys[1] = min_key_[1] + (static_cast<key_type>(1) << level_);
214  keys[2] = min_key_[2];
215  return 1; // There is a neighbour
216  }
217  return 0; // There is no neighbour
218  }
219 
220  int GetBottomKey(key_type* keys) const {
221 // if (min_key_[2] >= static_cast<key_type> (1 << level_)) {
222  if (min_key_[2] >= 1) {
223  keys[0] = min_key_[0];
224  keys[1] = min_key_[1];
225  keys[2] = min_key_[2] - 1;
226  return 1; // There is a neighbour
227  }
228  return 0; // There is no neighbour
229  }
230 
231  int GetTopKey(key_type* keys) const {
232  if (min_key_[2] < static_cast<key_type> ((1 << ROOT_LEVEL) - (1 << level_))) {
233  keys[0] = min_key_[0];
234  keys[1] = min_key_[1];
235  keys[2] = min_key_[2] + (static_cast<key_type>(1) << level_);
236  return 1; // There is a neighbour
237  }
238  return 0; // There is no neighbour
239  }
240 
241  int GetKey(std::size_t position, key_type* keys) const {
242  //in total, there are a maximum of 27 nodes (as the Quadratic9 Hexa in GiD). The only difference is that here
243  //the central node of the hexa (cell) is just after the lineal nodes.
244  // the node index : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
245  const std::size_t x_position[] = {0, 2, 2, 0, 0, 2, 2, 0, 1, 1, 2, 1, 0, 0, 2, 2, 0, 1, 2, 1, 0, 1, 1, 2, 1, 0, 1};
246  const std::size_t y_position[] = {0, 0, 2, 2, 0, 0, 2, 2, 1, 0, 1, 2, 1, 0, 0, 2, 2, 0, 1, 2, 1, 1, 0, 1, 2, 1, 1};
247  const std::size_t z_position[] = {0, 0, 0, 0, 2, 2, 2, 2, 1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 1, 1, 1, 1, 2};
248 
249  keys[0] = min_key_[0] + ((x_position[position]) << (level_ - 1));
250  keys[1] = min_key_[1] + ((y_position[position]) << (level_ - 1));
251  keys[2] = min_key_[2] + ((z_position[position]) << (level_ - 1));
252 
253  return 1;
254  }
255 // int GetKey(std::size_t position, key_type* keys) {
256 // const std::size_t local_position[] = {0, 1, 3, 2, 4, 5, 7, 6};
257 //
258 // keys[0] = min_key_[0] + ((local_position[position] & 1) << level_);
259 // keys[1] = min_key_[1] + ((((local_position[position] & 2) >> 1)) << level_);
260 // keys[2] = min_key_[2] + ((((local_position[position] & 4) >> 2)) << level_);
261 //
262 // return 1;
263 // }
264 
265  int GetNeighbourKey(std::size_t direction, key_type* keys) const {
266  // direction 0 : X < 0
267  // direction 1 : X > 0
268  // direction 2 : Y < 0
269  // direction 3 : Y > 0
270  // direction 4 : Z < 0
271  // direction 5 : Z > 0
272  //from 6 to 18 are the directions coorresponding to edges of the cell
273 
274  //the key returned is inside the cell (minkey +1), to ensure that the corresponding
275  //cell get in pGetCell is the right one.
276 
277  assert(direction<18);
278  const std::size_t x_offset[]={0,2,1,1,1,1,0,2,0,2,0,2,0,2,1,1,1,1};
279  const std::size_t y_offset[]={1,1,0,2,1,1,0,0,2,2,1,1,1,1,0,2,0,2};
280  const std::size_t z_offset[]={1,1,1,1,0,2,1,1,1,1,0,0,2,2,0,0,2,2};
281  const std::size_t x_coef[] ={0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0};
282  const std::size_t y_coef[] ={0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1};
283  const std::size_t z_coef[] ={0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,1};
284 
285  std::size_t size = (1<<level_);
286 
287  // here i'm adding 2 to each dimension and it won't overflow
288  keys[0] = min_key_[0] + x_offset[direction] + x_coef[direction] * size;
289  keys[1] = min_key_[1] + y_offset[direction] + y_coef[direction] * size;
290  keys[2] = min_key_[2] + z_offset[direction] + z_coef[direction] * size;
291 
292  for(unsigned int i = 0 ; i < DIMENSION ; i++){
293  if(keys[i] == 0)
294  return 0; // There is no neighbour
295  else
296  (keys[i])--;
297 
298  //now we are in correct location and we can check if the right nieigbours exist
299  if(keys[i] > static_cast<key_type>(1 << ROOT_LEVEL))
300  return 0; // There is no neighbour
301  }
302  return 1; // There is a neighbour
303  }
304 
305  int GetNeighbourKey(std::size_t position, std::size_t direction, key_type* keys) const {
306 
307  GetKey(position, keys);
308 
309  // here i'm adding 2 to each dimension and it won't overflow
310  keys[0] += (direction & 1) << 1;
311  keys[1] += (direction & 2);
312  keys[2] += (direction & 4) >> 1;
313 
314  for(unsigned int i = 0 ; i < DIMENSION ; i++){
315  if(keys[i] == 0)
316  return 0; // There is no neighbour
317  else
318  (keys[i])--;
319 
320  //now we are in correct location and we can check if the right nieigbours exist
321  if(keys[i] > static_cast<key_type>(1 << ROOT_LEVEL))
322  return 0; // There is no neighbour
323  }
324  return 1; // There is a neighbour
325  }
326 
328  key_type position[3];
329  //in total, there are a maximum of 27 nodes (as the Quadratic9 Hexa in GiD). The only difference is that here
330  //the central node of the hexa (cell) is just after the lineal nodes.
331  // the node index : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
332  const std::size_t local_index[]={0, 9, 1,12,21,10, 3,11, 2,13,22,14,25, 8,23,16,24,15, 4,17, 5,20,26,18, 7,19,6};
333 
334  for(std::size_t i = 0 ; i < DIMENSION ; i++)
335  {
336  position[i] = (keys[i] - min_key_[i]) >> (level_-1);
337  }
338  std::size_t index = position[0] + position[1] * 3 + position[2] * 9;
339  assert(index <= 26);
340 // if(local_index[index] > 26)
341 // {
342 // KRATOS_WATCH(int(level_));
343 // KRATOS_WATCH(index);
344 // KRATOS_WATCH(min_key_[0]);
345 // KRATOS_WATCH(min_key_[1]);
346 // KRATOS_WATCH(min_key_[2]);
347 // KRATOS_WATCH(keys[0]);
348 // KRATOS_WATCH(keys[1]);
349 // KRATOS_WATCH(keys[2]);
350 // KRATOS_WATCH(position[0]);
351 // KRATOS_WATCH(position[1]);
352 // KRATOS_WATCH(position[2]);
353 // KRATOS_WATCH(local_index[index]);
354 // }
355  return local_index[index];
356 
357  }
358 
359 
360  void Insert(pointer_type object){
361  objects_.push_back(object);
362  }
363 
365 
366  if (!objects_.size()) return;
367  assert(this->HasChildren());
368 
369  const double tolerance = 0.001 * double(1 << MIN_LEVEL) / double(1 << ROOT_LEVEL) ; // 0.1% of the min size
370  double min_coord[3]={0.00, 0.00, 0.00};
371  double max_coord[3]={0.00, 0.00, 0.00};
372 
373  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++){
374  OctreeBinaryCell* son = pGetChild(i);
375  if (son->HasChildren()){
377  continue;
378  }
379  son->GetMinPointNormalized(min_coord);
380  son->GetMaxPointNormalized(max_coord);
381  pointer_type object;
382  for (int j=0;j<(int)objects_.size();j++){
383  object=objects_[j];
384  //for (object_container_type::iterator i_object = objects_.begin(); i_object != objects_.end(); i_object++) {
385  const int is_intersected = configuration_type::IsIntersected(object,tolerance, min_coord, max_coord);
386  if(is_intersected)
387  son->Insert(object);
388  }
389  }
390 
391  //clear the memory of objects_ (now the objects are transfered to children)
393  objects_.swap(temp);
394  }
395 
399 
400  unsigned char GetLevel() const {
401  return level_;
402  }
403 
404  char SetLevel(char level) {
405  level_ = level;
406  return level_;
407  }
408 
409  void GetMinKey(key_type& min_key_x, key_type& min_key_y, key_type& min_key_z) const {
410  min_key_x = min_key_[0];
411  min_key_y = min_key_[1];
412  min_key_z = min_key_[2];
413  }
414 
415  void SetMinKey(key_type min_key_x, key_type min_key_y, key_type min_key_z) {
416  min_key_[0] = min_key_x;
417  min_key_[1] = min_key_y;
418  min_key_[2] = min_key_z;
419  }
420 
421  OctreeBinaryCell& rGetChild(std::size_t pos) const {
422  return children_[pos];
423  }
424 
425  OctreeBinaryCell* pGetChild(std::size_t pos) const {
426  return children_ + pos;
427  }
428 
429  OctreeBinaryCell* pGetChild(key_type x_key, key_type y_key, key_type z_key) const {
430  return pGetChild(GetChildIndex(x_key, y_key, z_key));
431  }
432 
434  return children_;
435  }
436 
437  OctreeBinaryCell const* GetChildren() const {
438  return children_;
439  }
440 
442  {
443  return data_;
444  }
445 
447  {
448  return &data_;
449  }
450 
451  const std::vector<pointer_type>* pGetObjects() const
452  {
453  return &objects_;
454  }
455 
456  std::vector<pointer_type>* pGetObjects()
457  {
458  return &objects_;
459  }
460 
462  {
464  tmp.swap(objects_);
465  }
466 
470 
471  bool IsLeaf() const {
472  return (children_ == NULL);
473  }
474 
475  bool HasChildren() const {
476  return (children_ != NULL);
477  }
478 
482 
484 
485  virtual std::string Info() const {
486  return "OctreeBinaryCell";
487  }
488 
490 
491  virtual void PrintInfo(std::ostream& rOStream) const {
492  for (char i = ROOT_LEVEL; i > level_; i--) {
493  rOStream << " ";
494  }
495  rOStream << Info() << " at level " << static_cast<int> (level_);
496  }
497 
499 
500  virtual void PrintData(std::ostream& rOStream) const {
501  rOStream << "(" << GetCoordinateNormalized(min_key_[0]) << "," << GetCoordinateNormalized(min_key_[1]) << "," << GetCoordinateNormalized(min_key_[2]) << "),";
502  rOStream << "(" << GetCoordinateNormalized(min_key_[0]) + CalcSizeNormalized() << "," << GetCoordinateNormalized(min_key_[1]) + CalcSizeNormalized() << "," << GetCoordinateNormalized(min_key_[2]) + CalcSizeNormalized() << ")" << std::endl;
503 
504  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++) {
505  if (children_) {
506  for (char j = ROOT_LEVEL + 1; j > level_; j--) {
507  rOStream << " ";
508  }
509 
510  rOStream << "child #" << i;
511 
512  children_[i].PrintData(rOStream);
513  }
514  }
515  }
516 
520 
521 
523 
524  protected:
527 
528 
532 
533 
537 
538 
542 
543 
547 
548 
552 
553 
557 
558 
560 
561  private:
564 
565 
569 
570  char level_;
571  key_type min_key_[DIMENSION];
572  OctreeBinaryCell* children_;
573  data_type* data_;
574  object_container_type objects_;
575 
576 
577  double CalcSizeNormalized() const {
578  const double scale = 1.00 / (1 << ROOT_LEVEL);
579 
580  return (1 << level_) * scale; // I'm doing it in this way to avoid division
581  }
582 
583  double GetCoordinateNormalized(key_type key) const {
584  const double scale = 1.00 / (1 << ROOT_LEVEL);
585 
586  return static_cast<double>(key * scale);
587  }
588 
592 
593 
597 
598 
602 
603 
607 
608 
612 
614 
615  OctreeBinaryCell & operator=(OctreeBinaryCell const& rOther) {
616  return *this;
617  }
618 
620 
621  OctreeBinaryCell(OctreeBinaryCell const& rOther) {
622  }
623 
624 
626 
627  }; // Class OctreeBinaryCell
628 
630 
633 
634 
638 
639 
640 // /// input stream function
641 // inline std::istream & operator >>(std::istream& rIStream,
642 // OctreeBinaryCell& rThis);
643 
645  template<class TConfiguration>
646  inline std::ostream & operator <<(std::ostream& rOStream,
647  const OctreeBinaryCell<TConfiguration>& rThis) {
648  rThis.PrintInfo(rOStream);
649  rThis.PrintData(rOStream);
650 
651  return rOStream;
652  }
654 
656 
657 } // namespace Kratos.
658 
659 
This class represents a cell in an octree to be used with Octree class.
Definition: octree_binary_cell.h:70
OctreeBinaryCell * GetChildren()
Definition: octree_binary_cell.h:433
static constexpr std::size_t DIMENSION
Definition: octree_binary_cell.h:89
std::size_t GetLocalPosition(key_type *keys)
Definition: octree_binary_cell.h:327
OctreeBinaryCell & rGetChild(std::size_t pos) const
Definition: octree_binary_cell.h:421
std::vector< pointer_type > * pGetObjects()
Definition: octree_binary_cell.h:456
int GetFrontKey(key_type *keys) const
Definition: octree_binary_cell.h:210
static constexpr std::size_t ROOT_LEVEL
Definition: octree_binary_cell.h:91
void TransferObjectsToSonsNormalized()
Definition: octree_binary_cell.h:364
void DeleteData()
Definition: octree_binary_cell.h:126
const std::vector< pointer_type > * pGetObjects() const
Definition: octree_binary_cell.h:451
void Insert(pointer_type object)
Definition: octree_binary_cell.h:360
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: octree_binary_cell.h:491
TConfiguration configuration_type
Definition: octree_binary_cell.h:80
virtual ~OctreeBinaryCell()
Destructor.
Definition: octree_binary_cell.h:116
void EmptyObjects()
Definition: octree_binary_cell.h:461
int GetTopKey(key_type *keys) const
Definition: octree_binary_cell.h:231
bool IsLeaf() const
Definition: octree_binary_cell.h:471
OctreeBinaryCell(char Level=ROOT_LEVEL)
Default constructor.
Definition: octree_binary_cell.h:109
int SubdivideCell()
Definition: octree_binary_cell.h:147
TConfiguration::pointer_type pointer_type
Definition: octree_binary_cell.h:82
static constexpr std::size_t CHILDREN_NUMBER
Definition: octree_binary_cell.h:88
bool HasChildren() const
Definition: octree_binary_cell.h:475
static constexpr std::size_t MIN_LEVEL
Definition: octree_binary_cell.h:92
std::vector< pointer_type > object_container_type
Definition: octree_binary_cell.h:84
void DeleteChildren()
Definition: octree_binary_cell.h:122
void GetMinKey(key_type &min_key_x, key_type &min_key_y, key_type &min_key_z) const
Definition: octree_binary_cell.h:409
std::size_t key_type
Definition: octree_binary_cell.h:86
data_type * pGetData() const
Definition: octree_binary_cell.h:441
@ LEFT
Definition: octree_binary_cell.h:95
@ BACK
Definition: octree_binary_cell.h:97
@ FRONT
Definition: octree_binary_cell.h:98
@ BOTTOM
Definition: octree_binary_cell.h:99
@ RIGHT
Definition: octree_binary_cell.h:96
@ TOP
Definition: octree_binary_cell.h:100
OctreeBinaryCell const * GetChildren() const
Definition: octree_binary_cell.h:437
int GetKey(std::size_t position, key_type *keys) const
Definition: octree_binary_cell.h:241
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: octree_binary_cell.h:500
int GetNeighbourKey(std::size_t position, std::size_t direction, key_type *keys) const
Definition: octree_binary_cell.h:305
int GetNeighbourKey(std::size_t direction, key_type *keys) const
Definition: octree_binary_cell.h:265
int GetRightKey(key_type *keys) const
Definition: octree_binary_cell.h:189
char SetLevel(char level)
Definition: octree_binary_cell.h:404
data_type ** pGetDataPointer()
Definition: octree_binary_cell.h:446
OctreeBinaryCell * pGetChild(key_type x_key, key_type y_key, key_type z_key) const
Definition: octree_binary_cell.h:429
static constexpr std::size_t MAX_LEVEL
Definition: octree_binary_cell.h:90
TConfiguration::data_type data_type
Pointer definition of OctreeBinaryCell.
Definition: octree_binary_cell.h:78
unsigned char GetLevel() const
Definition: octree_binary_cell.h:400
int GetBackKey(key_type *keys) const
Definition: octree_binary_cell.h:199
void GetMinPointNormalized(double *min_point) const
Definition: octree_binary_cell.h:165
int GetBottomKey(key_type *keys) const
Definition: octree_binary_cell.h:220
std::size_t GetChildIndex(key_type x_key, key_type y_key, key_type z_key) const
Definition: octree_binary_cell.h:141
void GetMaxPointNormalized(double *max_point) const
Definition: octree_binary_cell.h:171
int GetLeftKey(key_type *keys) const
Definition: octree_binary_cell.h:178
virtual std::string Info() const
Turn back information as a string.
Definition: octree_binary_cell.h:485
OctreeBinaryCell * pGetChild(std::size_t pos) const
Definition: octree_binary_cell.h:425
void SetMinKey(key_type min_key_x, key_type min_key_y, key_type min_key_z)
Definition: octree_binary_cell.h:415
pybind11::list keys(Parameters const &self)
Definition: add_kratos_parameters_to_python.cpp:32
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
int j
Definition: quadrature.py:648
float temp
Definition: rotating_cone.py:85
integer i
Definition: TensorModule.f:17