faunus
radical_tessellation.h
1 #ifndef VORONOTALT_RADICAL_TESSELLATION_H_
2 #define VORONOTALT_RADICAL_TESSELLATION_H_
3 
4 #include <map>
5 
6 #include "spheres_container.h"
7 #include "radical_tessellation_contact_construction.h"
8 #include "time_recorder.h"
9 
10 namespace voronotalt
11 {
12 
14 {
15 public:
17  {
18  Float area;
19  Float arc_length;
20  Float solid_angle_a;
21  Float solid_angle_b;
22  Float pyramid_volume_a;
23  Float pyramid_volume_b;
24  Float distance;
25  UnsignedInt flags;
26  UnsignedInt id_a;
27  UnsignedInt id_b;
28 
29  ContactDescriptorSummary() noexcept :
30  area(FLOATCONST(0.0)),
31  arc_length(FLOATCONST(0.0)),
32  solid_angle_a(FLOATCONST(0.0)),
33  solid_angle_b(FLOATCONST(0.0)),
34  pyramid_volume_a(FLOATCONST(0.0)),
35  pyramid_volume_b(FLOATCONST(0.0)),
36  distance(FLOATCONST(0.0)),
37  flags(0),
38  id_a(0),
39  id_b(0)
40  {
41  }
42 
44  {
45  if(cd.area>FLOATCONST(0.0))
46  {
47  id_a=cd.id_a;
48  id_b=cd.id_b;
49  area=cd.area;
50  arc_length=(cd.sum_of_arc_angles*cd.intersection_circle_sphere.r);
51  solid_angle_a=cd.solid_angle_a;
52  solid_angle_b=cd.solid_angle_b;
53  pyramid_volume_a=cd.pyramid_volume_a;
54  pyramid_volume_b=cd.pyramid_volume_b;
55  distance=cd.distance;
56  flags=cd.flags;
57  }
58  }
59 
60  void ensure_ids_ordered() noexcept
61  {
62  if(id_a>id_b)
63  {
64  std::swap(id_a, id_b);
65  std::swap(solid_angle_a, solid_angle_b);
66  std::swap(pyramid_volume_a, pyramid_volume_b);
67  }
68  }
69  };
70 
72  {
74  {
75  }
76 
77  explicit ContactDescriptorSummaryAdjunct(const UnsignedInt levels) noexcept : level_areas(levels, FLOATCONST(0.0))
78  {
79  }
80 
81  std::vector<Float> level_areas;
82  };
83 
85  {
86  Float area;
87  Float arc_length;
88  Float explained_solid_angle_positive;
89  Float explained_solid_angle_negative;
90  Float explained_pyramid_volume_positive;
91  Float explained_pyramid_volume_negative;
92  Float sas_area;
93  Float sas_inside_volume;
94  UnsignedInt id;
95  UnsignedInt count;
96  int stage;
97 
99  area(FLOATCONST(0.0)),
100  arc_length(FLOATCONST(0.0)),
101  explained_solid_angle_positive(FLOATCONST(0.0)),
102  explained_solid_angle_negative(FLOATCONST(0.0)),
103  explained_pyramid_volume_positive(FLOATCONST(0.0)),
104  explained_pyramid_volume_negative(FLOATCONST(0.0)),
105  sas_area(FLOATCONST(0.0)),
106  sas_inside_volume(FLOATCONST(0.0)),
107  id(0),
108  count(0),
109  stage(0)
110  {
111  }
112 
113  void add(const ContactDescriptorSummary& cds) noexcept
114  {
115  if(cds.area>FLOATCONST(0.0) && (cds.id_a==id || cds.id_b==id))
116  {
117  count++;
118  area+=cds.area;
119  arc_length+=cds.arc_length;
120  explained_solid_angle_positive+=std::max(FLOATCONST(0.0), (cds.id_a==id ? cds.solid_angle_a : cds.solid_angle_b));
121  explained_solid_angle_negative+=FLOATCONST(0.0)-std::min(FLOATCONST(0.0), (cds.id_a==id ? cds.solid_angle_a : cds.solid_angle_b));
122  explained_pyramid_volume_positive+=std::max(FLOATCONST(0.0), (cds.id_a==id ? cds.pyramid_volume_a : cds.pyramid_volume_b));
123  explained_pyramid_volume_negative+=FLOATCONST(0.0)-std::min(FLOATCONST(0.0), (cds.id_a==id ? cds.pyramid_volume_a : cds.pyramid_volume_b));
124  stage=1;
125  }
126  }
127 
128  void add(const UnsignedInt new_id, const ContactDescriptorSummary& cds) noexcept
129  {
130  if(cds.area>FLOATCONST(0.0))
131  {
132  if(stage==0)
133  {
134  id=new_id;
135  }
136  add(cds);
137  }
138  }
139 
140  void compute_sas(const Float r) noexcept
141  {
142  if(stage==1)
143  {
144  sas_area=FLOATCONST(0.0);
145  sas_inside_volume=FLOATCONST(0.0);
146  if(arc_length>FLOATCONST(0.0) && !equal(explained_solid_angle_positive, explained_solid_angle_negative))
147  {
148  if(explained_solid_angle_positive>explained_solid_angle_negative)
149  {
150  sas_area=((FLOATCONST(4.0)*PIVALUE)-std::max(FLOATCONST(0.0), explained_solid_angle_positive-explained_solid_angle_negative))*(r*r);
151  }
152  else if(explained_solid_angle_negative>explained_solid_angle_positive)
153  {
154  sas_area=(std::max(FLOATCONST(0.0), explained_solid_angle_negative-explained_solid_angle_positive))*(r*r);
155  }
156  sas_inside_volume=(sas_area*r/FLOATCONST(3.0))+explained_pyramid_volume_positive-explained_pyramid_volume_negative;
157  if(sas_inside_volume>(FLOATCONST(4.0)/FLOATCONST(3.0)*PIVALUE*r*r*r))
158  {
159  sas_area=FLOATCONST(0.0);
160  sas_inside_volume=explained_pyramid_volume_positive-explained_pyramid_volume_negative;
161  }
162  }
163  else
164  {
165  sas_inside_volume=explained_pyramid_volume_positive-explained_pyramid_volume_negative;
166  }
167  stage=2;
168  }
169  }
170 
171  void compute_sas_detached(const UnsignedInt new_id, const Float r) noexcept
172  {
173  if(stage==0)
174  {
175  id=new_id;
176  sas_area=(FLOATCONST(4.0)*PIVALUE)*(r*r);
177  sas_inside_volume=(sas_area*r/FLOATCONST(3.0));
178  stage=2;
179  }
180  }
181  };
182 
184  {
185  Float area;
186  Float arc_length;
187  Float distance;
188  UnsignedInt count;
189 
190  TotalContactDescriptorsSummary() noexcept :
191  area(FLOATCONST(0.0)),
192  arc_length(FLOATCONST(0.0)),
193  distance(FLOATCONST(-1.0)),
194  count(0)
195  {
196  }
197 
198  void add(const ContactDescriptorSummary& cds) noexcept
199  {
200  if(cds.area>FLOATCONST(0.0))
201  {
202  count++;
203  area+=cds.area;
204  arc_length+=cds.arc_length;
205  distance=((distance<FLOATCONST(0.0)) ? cds.distance : std::min(distance, cds.distance));
206  }
207  }
208  };
209 
211  {
212  Float sas_area;
213  Float sas_inside_volume;
214  UnsignedInt count;
215 
217  sas_area(FLOATCONST(0.0)),
218  sas_inside_volume(FLOATCONST(0.0)),
219  count(0)
220  {
221  }
222 
223  void add(const CellContactDescriptorsSummary& ccds) noexcept
224  {
225  if(ccds.stage==2)
226  {
227  count++;
228  sas_area+=ccds.sas_area;
229  sas_inside_volume+=ccds.sas_inside_volume;
230  }
231  }
232  };
233 
234  struct Result
235  {
236  UnsignedInt total_spheres;
237  UnsignedInt total_collisions;
238  UnsignedInt total_relevant_collisions;
239  std::vector<ContactDescriptorSummary> contacts_summaries;
240  std::vector<ContactDescriptorSummaryAdjunct> adjuncts_for_contacts_summaries;
241  TotalContactDescriptorsSummary total_contacts_summary;
242  std::vector<CellContactDescriptorsSummary> cells_summaries;
243  TotalCellContactDescriptorsSummary total_cells_summary;
244  std::vector<ContactDescriptorSummary> contacts_summaries_with_redundancy_in_periodic_box;
245  std::vector<UnsignedInt> contacts_canonical_ids_with_redundancy_in_periodic_box;
246 
247  Result() noexcept : total_spheres(0), total_collisions(0), total_relevant_collisions(0)
248  {
249  }
250 
251  void clear() noexcept
252  {
253  total_spheres=0;
254  total_collisions=0;
255  total_relevant_collisions=0;
256  contacts_summaries.clear();
257  adjuncts_for_contacts_summaries.clear();
258  total_contacts_summary=TotalContactDescriptorsSummary();
259  cells_summaries.clear();
260  total_cells_summary=TotalCellContactDescriptorsSummary();
261  contacts_summaries_with_redundancy_in_periodic_box.clear();
262  contacts_canonical_ids_with_redundancy_in_periodic_box.clear();
263  }
264  };
265 
267  {
268  std::vector<RadicalTessellationContactConstruction::ContactDescriptorGraphics> contacts_graphics;
269  };
270 
272  {
273  std::vector<UnsignedInt> grouped_contacts_representative_ids;
274  std::vector<TotalContactDescriptorsSummary> grouped_contacts_summaries;
275  std::vector<UnsignedInt> grouped_cells_representative_ids;
276  std::vector<TotalCellContactDescriptorsSummary> grouped_cells_summaries;
277 
278  void clear() noexcept
279  {
280  grouped_contacts_representative_ids.clear();
281  grouped_contacts_summaries.clear();
282  grouped_cells_representative_ids.clear();
283  grouped_cells_summaries.clear();
284  }
285  };
286 
287  static void construct_full_tessellation(
288  const std::vector<SimpleSphere>& input_spheres,
289  Result& result) noexcept
290  {
291  TimeRecorder time_recorder;
292  SpheresContainer spheres_container;
293  spheres_container.init(input_spheres, time_recorder);
294  ResultGraphics result_graphics;
295  construct_full_tessellation(spheres_container, std::vector<int>(), std::vector<int>(), false, true, FLOATCONST(0.0), std::vector<Float>(), result, result_graphics, time_recorder);
296  }
297 
298  static void construct_full_tessellation(
299  const std::vector<SimpleSphere>& input_spheres,
300  const std::vector<int>& grouping_of_spheres,
301  Result& result) noexcept
302  {
303  TimeRecorder time_recorder;
304  SpheresContainer spheres_container;
305  spheres_container.init(input_spheres, time_recorder);
306  ResultGraphics result_graphics;
307  construct_full_tessellation(spheres_container, std::vector<int>(), grouping_of_spheres, false, grouping_of_spheres.empty(), FLOATCONST(0.0), std::vector<Float>(), result, result_graphics, time_recorder);
308  }
309 
310  static void construct_full_tessellation(
311  const std::vector<SimpleSphere>& input_spheres,
312  const PeriodicBox& periodic_box,
313  Result& result) noexcept
314  {
315  TimeRecorder time_recorder;
316  SpheresContainer spheres_container;
317  spheres_container.init(input_spheres, periodic_box, time_recorder);
318  ResultGraphics result_graphics;
319  construct_full_tessellation(spheres_container, std::vector<int>(), std::vector<int>(), false, true, FLOATCONST(0.0), std::vector<Float>(), result, result_graphics, time_recorder);
320  }
321 
322  static void construct_full_tessellation(
323  const std::vector<SimpleSphere>& input_spheres,
324  const std::vector<int>& grouping_of_spheres,
325  const PeriodicBox& periodic_box,
326  Result& result) noexcept
327  {
328  TimeRecorder time_recorder;
329  SpheresContainer spheres_container;
330  spheres_container.init(input_spheres, periodic_box, time_recorder);
331  ResultGraphics result_graphics;
332  construct_full_tessellation(spheres_container, std::vector<int>(), grouping_of_spheres, false, grouping_of_spheres.empty(), FLOATCONST(0.0), std::vector<Float>(), result, result_graphics, time_recorder);
333  }
334 
335  static void construct_full_tessellation(
336  const SpheresContainer& spheres_container,
337  const std::vector<int>& grouping_of_spheres,
338  const bool with_graphics,
339  const bool summarize_cells,
340  Result& result,
341  ResultGraphics& result_graphics,
342  TimeRecorder& time_recorder) noexcept
343  {
344  construct_full_tessellation(spheres_container, std::vector<int>(), grouping_of_spheres, with_graphics, summarize_cells, FLOATCONST(0.0), std::vector<Float>(), result, result_graphics, time_recorder);
345  }
346 
347  static void construct_full_tessellation(
348  const SpheresContainer& spheres_container,
349  const std::vector<int>& involvement_of_spheres,
350  const std::vector<int>& grouping_of_spheres,
351  const bool with_graphics,
352  const bool summarize_cells,
353  const Float max_circle_radius_restriction,
354  const std::vector<Float>& adjunct_max_circle_radius_restrictions,
355  Result& result,
356  ResultGraphics& result_graphics,
357  TimeRecorder& time_recorder) noexcept
358  {
359  time_recorder.reset();
360 
361  result.clear();
362 
364  spheres_container.prepare_for_tessellation(involvement_of_spheres, grouping_of_spheres, preparation_result, time_recorder);
365 
366  result_graphics=ResultGraphics();
367 
368  result.total_spheres=spheres_container.input_spheres().size();
369  result.total_collisions=spheres_container.total_collisions();
370  result.total_relevant_collisions=preparation_result.relevant_collision_ids.size();
371 
372  std::vector<ContactDescriptorSummary> possible_contacts_summaries(preparation_result.relevant_collision_ids.size());
373 
374  std::vector<RadicalTessellationContactConstruction::ContactDescriptorGraphics> possible_contacts_graphics;
375  if(with_graphics)
376  {
377  possible_contacts_graphics.resize(possible_contacts_summaries.size());
378  }
379 
380  time_recorder.record_elapsed_miliseconds_and_reset("allocate possible contact summaries");
381 
382 #ifdef VORONOTALT_OPENMP
383 #pragma omp parallel
384 #endif
385  {
387  cd.contour.reserve(12);
388 
389 #ifdef VORONOTALT_OPENMP
390 #pragma omp for
391 #endif
392  for(UnsignedInt i=0;i<preparation_result.relevant_collision_ids.size();i++)
393  {
394  const UnsignedInt id_a=preparation_result.relevant_collision_ids[i].first;
395  const UnsignedInt id_b=preparation_result.relevant_collision_ids[i].second;
396  if(RadicalTessellationContactConstruction::construct_contact_descriptor(
397  spheres_container.populated_spheres(),
398  spheres_container.all_exclusion_statuses(),
399  id_a,
400  id_b,
401  spheres_container.all_colliding_ids()[id_a],
402  max_circle_radius_restriction,
403  cd))
404  {
405  possible_contacts_summaries[i].set(cd);
406  if(with_graphics)
407  {
408  RadicalTessellationContactConstruction::construct_contact_descriptor_graphics(cd, 0.2, possible_contacts_graphics[i]);
409  }
410  }
411  }
412  }
413 
414  time_recorder.record_elapsed_miliseconds_and_reset("construct contacts");
415 
416  UnsignedInt number_of_valid_contact_summaries=0;
417  for(UnsignedInt i=0;i<possible_contacts_summaries.size();i++)
418  {
419  if(possible_contacts_summaries[i].area>FLOATCONST(0.0))
420  {
421  number_of_valid_contact_summaries++;
422  }
423  }
424 
425  time_recorder.record_elapsed_miliseconds_and_reset("count valid contact summaries");
426 
427  std::vector<UnsignedInt> ids_of_valid_pairs;
428  ids_of_valid_pairs.reserve(number_of_valid_contact_summaries);
429 
430  for(UnsignedInt i=0;i<possible_contacts_summaries.size();i++)
431  {
432  if(possible_contacts_summaries[i].area>FLOATCONST(0.0))
433  {
434  ids_of_valid_pairs.push_back(i);
435  }
436  }
437 
438  time_recorder.record_elapsed_miliseconds_and_reset("collect indices of valid contact summaries");
439 
440  result.contacts_summaries.resize(ids_of_valid_pairs.size());
441 
442  {
443 #ifdef VORONOTALT_OPENMP
444 #pragma omp parallel for
445 #endif
446  for(UnsignedInt i=0;i<ids_of_valid_pairs.size();i++)
447  {
448  result.contacts_summaries[i]=possible_contacts_summaries[ids_of_valid_pairs[i]];
449  result.contacts_summaries[i].ensure_ids_ordered();
450  }
451  }
452 
453  if(!adjunct_max_circle_radius_restrictions.empty())
454  {
455  result.adjuncts_for_contacts_summaries.clear();
456  result.adjuncts_for_contacts_summaries.resize(result.contacts_summaries.size(), ContactDescriptorSummaryAdjunct(adjunct_max_circle_radius_restrictions.size()));
457 
458 #ifdef VORONOTALT_OPENMP
459 #pragma omp parallel
460 #endif
461  {
463  cd.contour.reserve(12);
464 
465 #ifdef VORONOTALT_OPENMP
466 #pragma omp for
467 #endif
468  for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
469  {
470  const ContactDescriptorSummary& cds=result.contacts_summaries[i];
471  if(cds.area>FLOATCONST(0.0))
472  {
473  ContactDescriptorSummaryAdjunct& cdsa=result.adjuncts_for_contacts_summaries[i];
474  Float prev_circle_radius_restriction=0.0;
475  for(UnsignedInt j=0;j<adjunct_max_circle_radius_restrictions.size();j++)
476  {
477  const Float circle_radius_restriction=(max_circle_radius_restriction>FLOATCONST(0.0) ? std::min(adjunct_max_circle_radius_restrictions[j], max_circle_radius_restriction) : adjunct_max_circle_radius_restrictions[j]);
478  if(j==0 || (circle_radius_restriction>=prev_circle_radius_restriction)
479  || (circle_radius_restriction<prev_circle_radius_restriction && cdsa.level_areas[j-1]>FLOATCONST(0.0)))
480  {
481  if(RadicalTessellationContactConstruction::construct_contact_descriptor(
482  spheres_container.populated_spheres(),
483  spheres_container.all_exclusion_statuses(),
484  cds.id_a,
485  cds.id_b,
486  spheres_container.all_colliding_ids()[cds.id_a],
487  circle_radius_restriction,
488  cd))
489  {
490  cdsa.level_areas[j]=cd.area;
491  }
492  }
493  prev_circle_radius_restriction=circle_radius_restriction;
494  }
495  }
496  }
497  }
498  }
499 
500  time_recorder.record_elapsed_miliseconds_and_reset("copy valid contact summaries");
501 
502  if(with_graphics)
503  {
504  result_graphics.contacts_graphics.resize(ids_of_valid_pairs.size());
505 
506  for(UnsignedInt i=0;i<ids_of_valid_pairs.size();i++)
507  {
508  result_graphics.contacts_graphics[i]=possible_contacts_graphics[ids_of_valid_pairs[i]];
509  }
510 
511  time_recorder.record_elapsed_miliseconds_and_reset("copy valid contacts graphics");
512  }
513 
514  if(spheres_container.periodic_box().enabled())
515  {
516  std::vector< std::vector<UnsignedInt> > map_of_spheres_to_boundary_contacts(result.total_spheres);
517 
518  for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
519  {
520  const ContactDescriptorSummary& cds=result.contacts_summaries[i];
521  if(cds.id_a>=result.total_spheres || cds.id_b>=result.total_spheres)
522  {
523  map_of_spheres_to_boundary_contacts[cds.id_a%result.total_spheres].push_back(i);
524  map_of_spheres_to_boundary_contacts[cds.id_b%result.total_spheres].push_back(i);
525  }
526  }
527 
528  result.contacts_canonical_ids_with_redundancy_in_periodic_box.resize(result.contacts_summaries.size());
529 
530  UnsignedInt count_of_redundant_contacts_in_periodic_box=0;
531 
532  for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
533  {
534  result.contacts_canonical_ids_with_redundancy_in_periodic_box[i]=i;
535  const ContactDescriptorSummary& cds=result.contacts_summaries[i];
536  if(cds.id_a>=result.total_spheres || cds.id_b>=result.total_spheres)
537  {
538  const UnsignedInt sphere_id_a=(cds.id_a%result.total_spheres);
539  const UnsignedInt sphere_id_b=(cds.id_b%result.total_spheres);
540  const std::vector<UnsignedInt>& candidate_ids_a=map_of_spheres_to_boundary_contacts[sphere_id_a];
541  const std::vector<UnsignedInt>& candidate_ids_b=map_of_spheres_to_boundary_contacts[sphere_id_b];
542  const std::vector<UnsignedInt>& candidate_ids=(candidate_ids_a.size()<=candidate_ids_b.size() ? candidate_ids_a : candidate_ids_b);
543  UnsignedInt selected_id=result.contacts_summaries.size();
544  for(UnsignedInt j=0;j<candidate_ids.size() && selected_id>=result.contacts_summaries.size();j++)
545  {
546  const UnsignedInt candidate_id=candidate_ids[j];
547  const ContactDescriptorSummary& candidate_cds=result.contacts_summaries[candidate_id];
548  const UnsignedInt candidate_sphere_id_a=(candidate_cds.id_a%result.total_spheres);
549  const UnsignedInt candidate_sphere_id_b=(candidate_cds.id_b%result.total_spheres);
550  if((candidate_sphere_id_a==sphere_id_a && candidate_sphere_id_b==sphere_id_b)
551  || (candidate_sphere_id_a==sphere_id_b && candidate_sphere_id_b==sphere_id_a))
552  {
553  selected_id=candidate_id;
554  }
555  }
556  if(selected_id<result.contacts_summaries.size())
557  {
558  result.contacts_canonical_ids_with_redundancy_in_periodic_box[i]=selected_id;
559  if(i!=selected_id)
560  {
561  count_of_redundant_contacts_in_periodic_box++;
562  }
563  }
564  }
565  }
566 
567  if(count_of_redundant_contacts_in_periodic_box>0)
568  {
569  result.contacts_summaries_with_redundancy_in_periodic_box.swap(result.contacts_summaries);
570  result.contacts_summaries.reserve(result.contacts_summaries_with_redundancy_in_periodic_box.size()+1-count_of_redundant_contacts_in_periodic_box);
571  for(UnsignedInt i=0;i<result.contacts_summaries_with_redundancy_in_periodic_box.size();i++)
572  {
573  if(i>=result.contacts_canonical_ids_with_redundancy_in_periodic_box.size() || result.contacts_canonical_ids_with_redundancy_in_periodic_box[i]==i)
574  {
575  result.contacts_summaries.push_back(result.contacts_summaries_with_redundancy_in_periodic_box[i]);
576  ContactDescriptorSummary& cds=result.contacts_summaries.back();
577  cds.id_a=(cds.id_a%result.total_spheres);
578  cds.id_b=(cds.id_b%result.total_spheres);
579  cds.ensure_ids_ordered();
580  }
581  }
582  }
583 
584  time_recorder.record_elapsed_miliseconds_and_reset("reassign ids in contacts at boundaries");
585  }
586 
587  for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
588  {
589  result.total_contacts_summary.add(result.contacts_summaries[i]);
590  }
591 
592  time_recorder.record_elapsed_miliseconds_and_reset("accumulate total contacts summary");
593 
594  if(summarize_cells && grouping_of_spheres.empty())
595  {
596  const std::vector<ContactDescriptorSummary>& all_contacts_summaries=(result.contacts_summaries_with_redundancy_in_periodic_box.empty() ? result.contacts_summaries : result.contacts_summaries_with_redundancy_in_periodic_box);
597 
598  result.cells_summaries.resize(result.total_spheres);
599 
600  for(UnsignedInt i=0;i<all_contacts_summaries.size();i++)
601  {
602  const ContactDescriptorSummary& cds=all_contacts_summaries[i];
603  if(cds.id_a<result.total_spheres)
604  {
605  result.cells_summaries[cds.id_a].add(cds.id_a, cds);
606  }
607  if(cds.id_b<result.total_spheres)
608  {
609  result.cells_summaries[cds.id_b].add(cds.id_b, cds);
610  }
611  }
612 
613  time_recorder.record_elapsed_miliseconds_and_reset("accumulate cell summaries");
614 
615  for(UnsignedInt i=0;i<result.cells_summaries.size();i++)
616  {
617  result.cells_summaries[i].compute_sas(spheres_container.populated_spheres()[i].r);
618  if(result.cells_summaries[i].stage==0 && spheres_container.all_exclusion_statuses()[i]==0 && spheres_container.all_colliding_ids()[i].empty())
619  {
620  result.cells_summaries[i].compute_sas_detached(i, spheres_container.populated_spheres()[i].r);
621  }
622  }
623 
624  time_recorder.record_elapsed_miliseconds_and_reset("compute sas for cell summaries");
625 
626  for(UnsignedInt i=0;i<result.cells_summaries.size();i++)
627  {
628  result.total_cells_summary.add(result.cells_summaries[i]);
629  }
630 
631  time_recorder.record_elapsed_miliseconds_and_reset("accumulate total cells summary");
632  }
633  }
634 
635  static bool group_results(
636  const Result& full_result,
637  const std::vector<int>& grouping_of_spheres,
638  GroupedResult& grouped_result) noexcept
639  {
640  TimeRecorder time_recorder;
641  return group_results(full_result, grouping_of_spheres, grouped_result, time_recorder);
642  }
643 
644  static bool group_results(
645  const Result& full_result,
646  const std::vector<int>& grouping_of_spheres,
647  GroupedResult& grouped_result,
648  TimeRecorder& time_recorder) noexcept
649  {
650  time_recorder.reset();
651 
652  grouped_result.clear();
653 
654  if(!grouping_of_spheres.empty() && grouping_of_spheres.size()==full_result.total_spheres)
655  {
656  {
657  grouped_result.grouped_contacts_representative_ids.reserve(full_result.contacts_summaries.size()/5);
658  grouped_result.grouped_contacts_summaries.reserve(full_result.contacts_summaries.size()/5);
659 
660  std::map< std::pair<int, int>, UnsignedInt > map_of_groups;
661 
662  for(UnsignedInt i=0;i<full_result.contacts_summaries.size();i++)
663  {
664  const ContactDescriptorSummary& cds=full_result.contacts_summaries[i];
665  if(cds.id_a<grouping_of_spheres.size() && cds.id_b<grouping_of_spheres.size())
666  {
667  std::pair<int, int> group_id(grouping_of_spheres[cds.id_a], grouping_of_spheres[cds.id_b]);
668  if(group_id.first!=group_id.second)
669  {
670  if(group_id.first>group_id.second)
671  {
672  std::swap(group_id.first, group_id.second);
673  }
674  UnsignedInt group_index=0;
675  std::map< std::pair<int, int>, UnsignedInt >::const_iterator it=map_of_groups.find(group_id);
676  if(it==map_of_groups.end())
677  {
678  group_index=grouped_result.grouped_contacts_summaries.size();
679  grouped_result.grouped_contacts_representative_ids.push_back(i);
680  grouped_result.grouped_contacts_summaries.push_back(TotalContactDescriptorsSummary());
681  map_of_groups[group_id]=group_index;
682  }
683  else
684  {
685  group_index=it->second;
686  }
687  grouped_result.grouped_contacts_summaries[group_index].add(cds);
688  }
689  }
690  }
691 
692  time_recorder.record_elapsed_miliseconds_and_reset("grouped contacts summaries");
693  }
694 
695  if(!full_result.cells_summaries.empty() && full_result.cells_summaries.size()==grouping_of_spheres.size())
696  {
697  grouped_result.grouped_cells_representative_ids.reserve(full_result.cells_summaries.size()/5);
698  grouped_result.grouped_cells_summaries.reserve(full_result.cells_summaries.size()/5);
699 
700  std::map< int, UnsignedInt > map_of_groups;
701 
702  for(UnsignedInt i=0;i<full_result.cells_summaries.size();i++)
703  {
704  const CellContactDescriptorsSummary& ccds=full_result.cells_summaries[i];
705  if(ccds.stage==2 && ccds.id<grouping_of_spheres.size())
706  {
707  const int group_id=grouping_of_spheres[ccds.id];
708  UnsignedInt group_index=0;
709  std::map< int, UnsignedInt >::const_iterator it=map_of_groups.find(group_id);
710  if(it==map_of_groups.end())
711  {
712  group_index=grouped_result.grouped_cells_summaries.size();
713  grouped_result.grouped_cells_representative_ids.push_back(i);
714  grouped_result.grouped_cells_summaries.push_back(TotalCellContactDescriptorsSummary());
715  map_of_groups[group_id]=group_index;
716  }
717  else
718  {
719  group_index=it->second;
720  }
721  grouped_result.grouped_cells_summaries[group_index].add(ccds);
722  }
723  }
724 
725  time_recorder.record_elapsed_miliseconds_and_reset("grouped cells summaries");
726  }
727  }
728 
729  return (!grouped_result.grouped_contacts_summaries.empty());
730  }
731 };
732 
733 }
734 
735 #endif /* VORONOTALT_RADICAL_TESSELLATION_H_ */
Definition: time_recorder.h:7
Definition: radical_tessellation_contact_construction.h:35
Definition: radical_tessellation.h:234
Definition: radical_tessellation.h:271
Definition: spheres_container.h:11
Definition: periodic_box.h:11
Definition: radical_tessellation.h:266
Definition: basic_types_and_functions.h:19
Definition: radical_tessellation.h:13