1 #ifndef VORONOTALT_RADICAL_TESSELLATION_H_ 2 #define VORONOTALT_RADICAL_TESSELLATION_H_ 6 #include "spheres_container.h" 7 #include "radical_tessellation_contact_construction.h" 8 #include "time_recorder.h" 22 Float pyramid_volume_a;
23 Float pyramid_volume_b;
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)),
45 if(cd.area>FLOATCONST(0.0))
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;
60 void ensure_ids_ordered() noexcept
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);
81 std::vector<Float> level_areas;
88 Float explained_solid_angle_positive;
89 Float explained_solid_angle_negative;
90 Float explained_pyramid_volume_positive;
91 Float explained_pyramid_volume_negative;
93 Float sas_inside_volume;
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)),
115 if(cds.area>FLOATCONST(0.0) && (cds.id_a==
id || cds.id_b==
id))
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));
130 if(cds.area>FLOATCONST(0.0))
140 void compute_sas(
const Float r) noexcept
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))
148 if(explained_solid_angle_positive>explained_solid_angle_negative)
150 sas_area=((FLOATCONST(4.0)*PIVALUE)-std::max(FLOATCONST(0.0), explained_solid_angle_positive-explained_solid_angle_negative))*(r*r);
152 else if(explained_solid_angle_negative>explained_solid_angle_positive)
154 sas_area=(std::max(FLOATCONST(0.0), explained_solid_angle_negative-explained_solid_angle_positive))*(r*r);
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))
159 sas_area=FLOATCONST(0.0);
160 sas_inside_volume=explained_pyramid_volume_positive-explained_pyramid_volume_negative;
165 sas_inside_volume=explained_pyramid_volume_positive-explained_pyramid_volume_negative;
171 void compute_sas_detached(
const UnsignedInt new_id,
const Float r) noexcept
176 sas_area=(FLOATCONST(4.0)*PIVALUE)*(r*r);
177 sas_inside_volume=(sas_area*r/FLOATCONST(3.0));
191 area(FLOATCONST(0.0)),
192 arc_length(FLOATCONST(0.0)),
193 distance(FLOATCONST(-1.0)),
200 if(cds.area>FLOATCONST(0.0))
204 arc_length+=cds.arc_length;
205 distance=((distance<FLOATCONST(0.0)) ? cds.distance : std::min(distance, cds.distance));
213 Float sas_inside_volume;
217 sas_area(FLOATCONST(0.0)),
218 sas_inside_volume(FLOATCONST(0.0)),
228 sas_area+=ccds.sas_area;
229 sas_inside_volume+=ccds.sas_inside_volume;
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;
242 std::vector<CellContactDescriptorsSummary> cells_summaries;
244 std::vector<ContactDescriptorSummary> contacts_summaries_with_redundancy_in_periodic_box;
245 std::vector<UnsignedInt> contacts_canonical_ids_with_redundancy_in_periodic_box;
247 Result() noexcept : total_spheres(0), total_collisions(0), total_relevant_collisions(0)
251 void clear() noexcept
255 total_relevant_collisions=0;
256 contacts_summaries.clear();
257 adjuncts_for_contacts_summaries.clear();
259 cells_summaries.clear();
261 contacts_summaries_with_redundancy_in_periodic_box.clear();
262 contacts_canonical_ids_with_redundancy_in_periodic_box.clear();
268 std::vector<RadicalTessellationContactConstruction::ContactDescriptorGraphics> contacts_graphics;
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;
278 void clear() noexcept
280 grouped_contacts_representative_ids.clear();
281 grouped_contacts_summaries.clear();
282 grouped_cells_representative_ids.clear();
283 grouped_cells_summaries.clear();
287 static void construct_full_tessellation(
288 const std::vector<SimpleSphere>& input_spheres,
293 spheres_container.init(input_spheres, time_recorder);
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);
298 static void construct_full_tessellation(
299 const std::vector<SimpleSphere>& input_spheres,
300 const std::vector<int>& grouping_of_spheres,
305 spheres_container.init(input_spheres, time_recorder);
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);
310 static void construct_full_tessellation(
311 const std::vector<SimpleSphere>& input_spheres,
317 spheres_container.init(input_spheres, periodic_box, time_recorder);
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);
322 static void construct_full_tessellation(
323 const std::vector<SimpleSphere>& input_spheres,
324 const std::vector<int>& grouping_of_spheres,
330 spheres_container.init(input_spheres, periodic_box, time_recorder);
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);
335 static void construct_full_tessellation(
337 const std::vector<int>& grouping_of_spheres,
338 const bool with_graphics,
339 const bool summarize_cells,
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);
347 static void construct_full_tessellation(
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,
359 time_recorder.reset();
364 spheres_container.prepare_for_tessellation(involvement_of_spheres, grouping_of_spheres, preparation_result, time_recorder);
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();
372 std::vector<ContactDescriptorSummary> possible_contacts_summaries(preparation_result.relevant_collision_ids.size());
374 std::vector<RadicalTessellationContactConstruction::ContactDescriptorGraphics> possible_contacts_graphics;
377 possible_contacts_graphics.resize(possible_contacts_summaries.size());
380 time_recorder.record_elapsed_miliseconds_and_reset(
"allocate possible contact summaries");
382 #ifdef VORONOTALT_OPENMP 387 cd.contour.reserve(12);
389 #ifdef VORONOTALT_OPENMP 392 for(UnsignedInt i=0;i<preparation_result.relevant_collision_ids.size();i++)
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(),
401 spheres_container.all_colliding_ids()[id_a],
402 max_circle_radius_restriction,
405 possible_contacts_summaries[i].set(cd);
408 RadicalTessellationContactConstruction::construct_contact_descriptor_graphics(cd, 0.2, possible_contacts_graphics[i]);
414 time_recorder.record_elapsed_miliseconds_and_reset(
"construct contacts");
416 UnsignedInt number_of_valid_contact_summaries=0;
417 for(UnsignedInt i=0;i<possible_contacts_summaries.size();i++)
419 if(possible_contacts_summaries[i].area>FLOATCONST(0.0))
421 number_of_valid_contact_summaries++;
425 time_recorder.record_elapsed_miliseconds_and_reset(
"count valid contact summaries");
427 std::vector<UnsignedInt> ids_of_valid_pairs;
428 ids_of_valid_pairs.reserve(number_of_valid_contact_summaries);
430 for(UnsignedInt i=0;i<possible_contacts_summaries.size();i++)
432 if(possible_contacts_summaries[i].area>FLOATCONST(0.0))
434 ids_of_valid_pairs.push_back(i);
438 time_recorder.record_elapsed_miliseconds_and_reset(
"collect indices of valid contact summaries");
440 result.contacts_summaries.resize(ids_of_valid_pairs.size());
443 #ifdef VORONOTALT_OPENMP 444 #pragma omp parallel for 446 for(UnsignedInt i=0;i<ids_of_valid_pairs.size();i++)
448 result.contacts_summaries[i]=possible_contacts_summaries[ids_of_valid_pairs[i]];
449 result.contacts_summaries[i].ensure_ids_ordered();
453 if(!adjunct_max_circle_radius_restrictions.empty())
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()));
458 #ifdef VORONOTALT_OPENMP 463 cd.contour.reserve(12);
465 #ifdef VORONOTALT_OPENMP 468 for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
471 if(cds.area>FLOATCONST(0.0))
474 Float prev_circle_radius_restriction=0.0;
475 for(UnsignedInt j=0;j<adjunct_max_circle_radius_restrictions.size();j++)
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)))
481 if(RadicalTessellationContactConstruction::construct_contact_descriptor(
482 spheres_container.populated_spheres(),
483 spheres_container.all_exclusion_statuses(),
486 spheres_container.all_colliding_ids()[cds.id_a],
487 circle_radius_restriction,
490 cdsa.level_areas[j]=cd.area;
493 prev_circle_radius_restriction=circle_radius_restriction;
500 time_recorder.record_elapsed_miliseconds_and_reset(
"copy valid contact summaries");
504 result_graphics.contacts_graphics.resize(ids_of_valid_pairs.size());
506 for(UnsignedInt i=0;i<ids_of_valid_pairs.size();i++)
508 result_graphics.contacts_graphics[i]=possible_contacts_graphics[ids_of_valid_pairs[i]];
511 time_recorder.record_elapsed_miliseconds_and_reset(
"copy valid contacts graphics");
514 if(spheres_container.periodic_box().enabled())
516 std::vector< std::vector<UnsignedInt> > map_of_spheres_to_boundary_contacts(result.total_spheres);
518 for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
521 if(cds.id_a>=result.total_spheres || cds.id_b>=result.total_spheres)
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);
528 result.contacts_canonical_ids_with_redundancy_in_periodic_box.resize(result.contacts_summaries.size());
530 UnsignedInt count_of_redundant_contacts_in_periodic_box=0;
532 for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
534 result.contacts_canonical_ids_with_redundancy_in_periodic_box[i]=i;
536 if(cds.id_a>=result.total_spheres || cds.id_b>=result.total_spheres)
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++)
546 const UnsignedInt candidate_id=candidate_ids[j];
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))
553 selected_id=candidate_id;
556 if(selected_id<result.contacts_summaries.size())
558 result.contacts_canonical_ids_with_redundancy_in_periodic_box[i]=selected_id;
561 count_of_redundant_contacts_in_periodic_box++;
567 if(count_of_redundant_contacts_in_periodic_box>0)
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++)
573 if(i>=result.contacts_canonical_ids_with_redundancy_in_periodic_box.size() || result.contacts_canonical_ids_with_redundancy_in_periodic_box[i]==i)
575 result.contacts_summaries.push_back(result.contacts_summaries_with_redundancy_in_periodic_box[i]);
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();
584 time_recorder.record_elapsed_miliseconds_and_reset(
"reassign ids in contacts at boundaries");
587 for(UnsignedInt i=0;i<result.contacts_summaries.size();i++)
589 result.total_contacts_summary.add(result.contacts_summaries[i]);
592 time_recorder.record_elapsed_miliseconds_and_reset(
"accumulate total contacts summary");
594 if(summarize_cells && grouping_of_spheres.empty())
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);
598 result.cells_summaries.resize(result.total_spheres);
600 for(UnsignedInt i=0;i<all_contacts_summaries.size();i++)
603 if(cds.id_a<result.total_spheres)
605 result.cells_summaries[cds.id_a].add(cds.id_a, cds);
607 if(cds.id_b<result.total_spheres)
609 result.cells_summaries[cds.id_b].add(cds.id_b, cds);
613 time_recorder.record_elapsed_miliseconds_and_reset(
"accumulate cell summaries");
615 for(UnsignedInt i=0;i<result.cells_summaries.size();i++)
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())
620 result.cells_summaries[i].compute_sas_detached(i, spheres_container.populated_spheres()[i].r);
624 time_recorder.record_elapsed_miliseconds_and_reset(
"compute sas for cell summaries");
626 for(UnsignedInt i=0;i<result.cells_summaries.size();i++)
628 result.total_cells_summary.add(result.cells_summaries[i]);
631 time_recorder.record_elapsed_miliseconds_and_reset(
"accumulate total cells summary");
635 static bool group_results(
636 const Result& full_result,
637 const std::vector<int>& grouping_of_spheres,
641 return group_results(full_result, grouping_of_spheres, grouped_result, time_recorder);
644 static bool group_results(
645 const Result& full_result,
646 const std::vector<int>& grouping_of_spheres,
650 time_recorder.reset();
652 grouped_result.clear();
654 if(!grouping_of_spheres.empty() && grouping_of_spheres.size()==full_result.total_spheres)
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);
660 std::map< std::pair<int, int>, UnsignedInt > map_of_groups;
662 for(UnsignedInt i=0;i<full_result.contacts_summaries.size();i++)
665 if(cds.id_a<grouping_of_spheres.size() && cds.id_b<grouping_of_spheres.size())
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)
670 if(group_id.first>group_id.second)
672 std::swap(group_id.first, group_id.second);
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())
678 group_index=grouped_result.grouped_contacts_summaries.size();
679 grouped_result.grouped_contacts_representative_ids.push_back(i);
681 map_of_groups[group_id]=group_index;
685 group_index=it->second;
687 grouped_result.grouped_contacts_summaries[group_index].add(cds);
692 time_recorder.record_elapsed_miliseconds_and_reset(
"grouped contacts summaries");
695 if(!full_result.cells_summaries.empty() && full_result.cells_summaries.size()==grouping_of_spheres.size())
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);
700 std::map< int, UnsignedInt > map_of_groups;
702 for(UnsignedInt i=0;i<full_result.cells_summaries.size();i++)
705 if(ccds.stage==2 && ccds.id<grouping_of_spheres.size())
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())
712 group_index=grouped_result.grouped_cells_summaries.size();
713 grouped_result.grouped_cells_representative_ids.push_back(i);
715 map_of_groups[group_id]=group_index;
719 group_index=it->second;
721 grouped_result.grouped_cells_summaries[group_index].add(ccds);
725 time_recorder.record_elapsed_miliseconds_and_reset(
"grouped cells summaries");
729 return (!grouped_result.grouped_contacts_summaries.empty());
Definition: time_recorder.h:7
Definition: radical_tessellation.h:234
Definition: spheres_container.h:14
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