1 #ifndef VORONOTALT_SPHERES_CONTAINER_H_ 2 #define VORONOTALT_SPHERES_CONTAINER_H_ 4 #include "spheres_searcher.h" 5 #include "periodic_box.h" 6 #include "time_recorder.h" 16 std::vector< std::pair<UnsignedInt, UnsignedInt> > relevant_collision_ids;
27 void init(
const std::vector<SimpleSphere>& input_spheres,
TimeRecorder& time_recorder) noexcept
32 void init(
const std::vector<SimpleSphere>& input_spheres,
const PeriodicBox& periodic_box,
TimeRecorder& time_recorder) noexcept
34 time_recorder.reset();
36 periodic_box_=periodic_box;
37 input_spheres_=input_spheres;
39 if(periodic_box_.enabled())
41 populated_spheres_.resize(input_spheres_.size()*27);
42 std::vector<UnsignedInt> collected_indices;
43 for(UnsignedInt i=0;i<input_spheres_.size();i++)
45 set_sphere_periodic_instances(i,
false, collected_indices);
50 populated_spheres_=input_spheres_;
53 all_exclusion_statuses_.resize(populated_spheres_.size(), 0);
55 time_recorder.record_elapsed_miliseconds_and_reset(
"populate spheres");
57 spheres_searcher_.init(populated_spheres_);
59 time_recorder.record_elapsed_miliseconds_and_reset(
"init spheres searcher");
61 all_colliding_ids_.resize(input_spheres_.size());
64 #ifdef VORONOTALT_OPENMP 65 #pragma omp parallel for 67 for(UnsignedInt i=0;i<input_spheres_.size();i++)
69 all_colliding_ids_[i].reserve(100);
70 spheres_searcher_.find_colliding_ids(i, all_colliding_ids_[i],
true, all_exclusion_statuses_[i]);
74 if(periodic_box_.enabled())
76 for(UnsignedInt i=0;i<input_spheres_.size();i++)
78 set_exclusion_status_periodic_instances(i);
82 time_recorder.record_elapsed_miliseconds_and_reset(
"detect all collisions");
86 for(UnsignedInt i=0;i<all_colliding_ids_.size();i++)
88 total_collisions_+=all_colliding_ids_[i].size();
91 total_collisions_=total_collisions_/2;
93 time_recorder.record_elapsed_miliseconds_and_reset(
"count all collisions");
97 const std::vector<SimpleSphere>& new_input_spheres,
98 const std::vector<UnsignedInt>& provided_ids_of_changed_input_spheres,
99 const bool trust_provided_ids_of_changed_input_spheres,
100 std::vector<UnsignedInt>& ids_of_changed_input_spheres,
101 std::vector<UnsignedInt>& ids_of_affected_input_spheres,
104 time_recorder.reset();
106 ids_of_changed_input_spheres.clear();
107 ids_of_affected_input_spheres.clear();
109 if(new_input_spheres.size()!=input_spheres_.size())
111 reinit(new_input_spheres, ids_of_changed_input_spheres, ids_of_affected_input_spheres, time_recorder);
115 if(trust_provided_ids_of_changed_input_spheres)
117 ids_of_changed_input_spheres=provided_ids_of_changed_input_spheres;
121 for(UnsignedInt i=0;i<new_input_spheres.size();i++)
123 if(!sphere_equals_sphere(new_input_spheres[i], input_spheres_[i]))
125 if(ids_of_changed_input_spheres.size()<size_threshold_for_full_reinit())
127 ids_of_changed_input_spheres.push_back(i);
131 reinit(new_input_spheres, ids_of_changed_input_spheres, ids_of_affected_input_spheres, time_recorder);
137 time_recorder.record_elapsed_miliseconds_and_reset(
"identify changed spheres ids for update");
140 if(ids_of_changed_input_spheres.empty())
145 if(ids_of_changed_input_spheres.size()>size_threshold_for_full_reinit())
147 reinit(new_input_spheres, ids_of_changed_input_spheres, ids_of_affected_input_spheres, time_recorder);
151 for(UnsignedInt i=0;i<ids_of_changed_input_spheres.size();i++)
153 if(ids_of_changed_input_spheres[i]>=input_spheres_.size())
155 reinit(new_input_spheres, ids_of_changed_input_spheres, ids_of_affected_input_spheres, time_recorder);
161 bool update_needed=
false;
162 for(UnsignedInt i=0;!update_needed && i<ids_of_changed_input_spheres.size();i++)
164 const UnsignedInt sphere_id=ids_of_changed_input_spheres[i];
165 if(!sphere_equals_sphere(new_input_spheres[sphere_id], input_spheres_[sphere_id]))
177 ids_of_affected_input_spheres=ids_of_changed_input_spheres;
178 std::sort(ids_of_affected_input_spheres.begin(), ids_of_affected_input_spheres.end());
180 for(UnsignedInt i=0;i<ids_of_changed_input_spheres.size();i++)
182 const UnsignedInt sphere_id=ids_of_changed_input_spheres[i];
183 for(UnsignedInt j=0;j<all_colliding_ids_[sphere_id].size();j++)
185 if(ids_of_affected_input_spheres.size()<size_threshold_for_full_reinit())
187 const UnsignedInt affected_sphere_id=all_colliding_ids_[sphere_id][j].index%input_spheres_.size();
188 std::vector<UnsignedInt>::iterator it=std::lower_bound(ids_of_affected_input_spheres.begin(), ids_of_affected_input_spheres.end(), affected_sphere_id);
189 if(it==ids_of_affected_input_spheres.end() || (*it)!=affected_sphere_id)
191 ids_of_affected_input_spheres.insert(it, affected_sphere_id);
196 reinit(new_input_spheres, ids_of_changed_input_spheres, ids_of_affected_input_spheres, time_recorder);
203 time_recorder.record_elapsed_miliseconds_and_reset(
"gather affected spheres ids for update");
206 if(periodic_box_.enabled())
208 std::vector<UnsignedInt> ids_of_changed_populated_spheres;
209 ids_of_changed_populated_spheres.reserve(ids_of_changed_input_spheres.size()*27);
210 for(UnsignedInt i=0;i<ids_of_changed_input_spheres.size();i++)
212 const UnsignedInt sphere_id=ids_of_changed_input_spheres[i];
213 input_spheres_[sphere_id]=new_input_spheres[sphere_id];
214 if(periodic_box_.enabled())
216 set_sphere_periodic_instances(sphere_id,
true, ids_of_changed_populated_spheres);
219 spheres_searcher_.update(populated_spheres_, ids_of_changed_populated_spheres);
223 for(UnsignedInt i=0;i<ids_of_changed_input_spheres.size();i++)
225 const UnsignedInt sphere_id=ids_of_changed_input_spheres[i];
226 input_spheres_[sphere_id]=new_input_spheres[sphere_id];
227 populated_spheres_[sphere_id]=input_spheres_[sphere_id];
229 spheres_searcher_.update(input_spheres_, ids_of_changed_input_spheres);
232 time_recorder.record_elapsed_miliseconds_and_reset(
"update spheres searcher");
235 #ifdef VORONOTALT_OPENMP 236 #pragma omp parallel for 238 for(UnsignedInt i=0;i<ids_of_affected_input_spheres.size();i++)
240 const UnsignedInt sphere_id=ids_of_affected_input_spheres[i];
241 all_colliding_ids_[sphere_id].clear();
242 spheres_searcher_.find_colliding_ids(sphere_id, all_colliding_ids_[sphere_id],
true, all_exclusion_statuses_[sphere_id]);
246 if(periodic_box_.enabled())
248 for(UnsignedInt i=0;i<ids_of_affected_input_spheres.size();i++)
250 const UnsignedInt sphere_id=ids_of_affected_input_spheres[i];
251 set_exclusion_status_periodic_instances(sphere_id);
255 buffered_temporary_storage_.clear();
257 for(UnsignedInt i=0;i<ids_of_changed_input_spheres.size();i++)
259 const UnsignedInt sphere_id=ids_of_changed_input_spheres[i];
260 for(UnsignedInt j=0;j<all_colliding_ids_[sphere_id].size();j++)
262 const UnsignedInt affected_sphere_id=all_colliding_ids_[sphere_id][j].index%input_spheres_.size();
263 std::vector<UnsignedInt>::iterator it=std::lower_bound(buffered_temporary_storage_.more_ids_of_affected_input_spheres.begin(), buffered_temporary_storage_.more_ids_of_affected_input_spheres.end(), affected_sphere_id);
264 if(it==buffered_temporary_storage_.more_ids_of_affected_input_spheres.end() || (*it)!=affected_sphere_id)
266 if(!std::binary_search(ids_of_affected_input_spheres.begin(), ids_of_affected_input_spheres.end(), affected_sphere_id))
268 buffered_temporary_storage_.more_ids_of_affected_input_spheres.insert(it, affected_sphere_id);
274 if(!buffered_temporary_storage_.more_ids_of_affected_input_spheres.empty())
277 #ifdef VORONOTALT_OPENMP 278 #pragma omp parallel for 280 for(UnsignedInt i=0;i<buffered_temporary_storage_.more_ids_of_affected_input_spheres.size();i++)
282 const UnsignedInt sphere_id=buffered_temporary_storage_.more_ids_of_affected_input_spheres[i];
283 all_colliding_ids_[sphere_id].clear();
284 spheres_searcher_.find_colliding_ids(sphere_id, all_colliding_ids_[sphere_id],
true, all_exclusion_statuses_[sphere_id]);
288 if(periodic_box_.enabled())
290 for(UnsignedInt i=0;i<ids_of_affected_input_spheres.size();i++)
292 const UnsignedInt sphere_id=ids_of_affected_input_spheres[i];
293 set_exclusion_status_periodic_instances(sphere_id);
297 buffered_temporary_storage_.merged_ids_of_affected_input_spheres.resize(ids_of_affected_input_spheres.size()+buffered_temporary_storage_.more_ids_of_affected_input_spheres.size());
299 std::merge(ids_of_affected_input_spheres.begin(), ids_of_affected_input_spheres.end(),
300 buffered_temporary_storage_.more_ids_of_affected_input_spheres.begin(), buffered_temporary_storage_.more_ids_of_affected_input_spheres.end(),
301 buffered_temporary_storage_.merged_ids_of_affected_input_spheres.begin());
303 ids_of_affected_input_spheres.swap(buffered_temporary_storage_.merged_ids_of_affected_input_spheres);
306 time_recorder.record_elapsed_miliseconds_and_reset(
"update relevant collisions");
310 for(UnsignedInt i=0;i<all_colliding_ids_.size();i++)
312 total_collisions_+=all_colliding_ids_[i].size();
315 total_collisions_=total_collisions_/2;
317 time_recorder.record_elapsed_miliseconds_and_reset(
"recount all collisions");
323 bool update_by_setting_exclusion_status(
const UnsignedInt id_of_masked_input_sphere,
const bool new_exclusion_status) noexcept
325 if(id_of_masked_input_sphere>=input_spheres_.size() || id_of_masked_input_sphere>=all_exclusion_statuses_.size() || (new_exclusion_status ? all_exclusion_statuses_[id_of_masked_input_sphere]>0 : all_exclusion_statuses_[id_of_masked_input_sphere]<1))
330 all_exclusion_statuses_[id_of_masked_input_sphere]=(new_exclusion_status ? 1 : 0);
332 if(periodic_box_.enabled())
334 set_exclusion_status_periodic_instances(id_of_masked_input_sphere);
340 bool update_by_setting_exclusion_status(
const UnsignedInt id_of_masked_input_sphere,
const bool new_exclusion_status, std::vector<UnsignedInt>& ids_of_changed_input_spheres, std::vector<UnsignedInt>& ids_of_affected_input_spheres) noexcept
342 ids_of_changed_input_spheres.clear();
343 ids_of_affected_input_spheres.clear();
345 if(id_of_masked_input_sphere>=input_spheres_.size() || id_of_masked_input_sphere>=all_exclusion_statuses_.size() || (new_exclusion_status ? all_exclusion_statuses_[id_of_masked_input_sphere]>0 : all_exclusion_statuses_[id_of_masked_input_sphere]<1))
350 ids_of_changed_input_spheres.push_back(id_of_masked_input_sphere);
351 ids_of_affected_input_spheres.push_back(id_of_masked_input_sphere);
353 for(std::size_t j=0;j<all_colliding_ids_[id_of_masked_input_sphere].size();j++)
355 const UnsignedInt affected_sphere_id=all_colliding_ids_[id_of_masked_input_sphere][j].index%input_spheres_.size();
356 std::vector<UnsignedInt>::iterator it=std::lower_bound(ids_of_affected_input_spheres.begin(), ids_of_affected_input_spheres.end(), affected_sphere_id);
357 if(it==ids_of_affected_input_spheres.end() || (*it)!=affected_sphere_id)
359 ids_of_affected_input_spheres.insert(it, affected_sphere_id);
363 all_exclusion_statuses_[id_of_masked_input_sphere]=(new_exclusion_status ? 1 : 0);
365 if(periodic_box_.enabled())
367 set_exclusion_status_periodic_instances(id_of_masked_input_sphere);
375 periodic_box_=obj.periodic_box_;
376 total_collisions_=obj.total_collisions_;
378 spheres_searcher_.assign(obj.spheres_searcher_);
380 input_spheres_.resize(obj.input_spheres_.size());
381 populated_spheres_.resize(obj.populated_spheres_.size());
382 all_exclusion_statuses_.resize(obj.all_exclusion_statuses_.size());
383 all_colliding_ids_.resize(obj.all_colliding_ids_.size());
386 #ifdef VORONOTALT_OPENMP 387 #pragma omp parallel for 389 for(UnsignedInt i=0;i<obj.input_spheres_.size();i++)
391 input_spheres_[i]=obj.input_spheres_[i];
396 #ifdef VORONOTALT_OPENMP 397 #pragma omp parallel for 399 for(UnsignedInt i=0;i<obj.populated_spheres_.size();i++)
401 populated_spheres_[i]=obj.populated_spheres_[i];
406 #ifdef VORONOTALT_OPENMP 407 #pragma omp parallel for 409 for(UnsignedInt i=0;i<obj.all_exclusion_statuses_.size();i++)
411 all_exclusion_statuses_[i]=obj.all_exclusion_statuses_[i];
416 #ifdef VORONOTALT_OPENMP 417 #pragma omp parallel for 419 for(UnsignedInt i=0;i<obj.all_colliding_ids_.size();i++)
421 all_colliding_ids_[i]=obj.all_colliding_ids_[i];
426 void assign(
const SpheresContainer& obj,
const std::vector<UnsignedInt>& subset_of_ids) noexcept
428 if(subset_of_ids.empty()
429 || obj.input_spheres_.empty()
430 || !periodic_box_.equals(obj.periodic_box_)
431 || input_spheres_.size()!=obj.input_spheres_.size()
432 || populated_spheres_.size()!=obj.populated_spheres_.size()
433 || all_exclusion_statuses_.size()!=obj.all_exclusion_statuses_.size()
434 || all_colliding_ids_.size()!=obj.all_colliding_ids_.size()
435 || subset_of_ids.size()>=size_threshold_for_full_reinit())
441 for(UnsignedInt i=0;i<subset_of_ids.size();i++)
443 const UnsignedInt sphere_id=subset_of_ids[i];
444 if(sphere_id>=input_spheres_.size())
451 periodic_box_=obj.periodic_box_;
452 total_collisions_=obj.total_collisions_;
454 spheres_searcher_.assign(obj.spheres_searcher_);
457 #ifdef VORONOTALT_OPENMP 458 #pragma omp parallel for 460 for(UnsignedInt i=0;i<subset_of_ids.size();i++)
462 const UnsignedInt sphere_id=subset_of_ids[i];
463 input_spheres_[sphere_id]=obj.input_spheres_[sphere_id];
464 populated_spheres_[sphere_id]=obj.populated_spheres_[sphere_id];
465 all_exclusion_statuses_[sphere_id]=obj.all_exclusion_statuses_[sphere_id];
466 all_colliding_ids_[sphere_id]=obj.all_colliding_ids_[sphere_id];
470 if(periodic_box_.enabled() && populated_spheres_.size()==input_spheres_.size()*27 && all_exclusion_statuses_.size()==all_exclusion_statuses_.size()*27)
472 #ifdef VORONOTALT_OPENMP 473 #pragma omp parallel for 475 for(UnsignedInt i=0;i<subset_of_ids.size();i++)
477 const UnsignedInt sphere_id=subset_of_ids[i];
478 for(UnsignedInt m=1;m<27;m++)
480 const UnsignedInt shifted_sphere_id=(m*input_spheres_.size()+sphere_id);
481 populated_spheres_[shifted_sphere_id]=obj.populated_spheres_[sphere_id];
482 all_exclusion_statuses_[shifted_sphere_id]=all_exclusion_statuses_[sphere_id];
491 return periodic_box_;
494 const std::vector<SimpleSphere>& input_spheres()
const noexcept
496 return input_spheres_;
499 const std::vector<SimpleSphere>& populated_spheres()
const noexcept
501 return populated_spheres_;
504 const std::vector<int>& all_exclusion_statuses()
const noexcept
506 return all_exclusion_statuses_;
509 const std::vector< std::vector<ValuedID> >& all_colliding_ids()
const noexcept
511 return all_colliding_ids_;
514 UnsignedInt total_collisions()
const noexcept
516 return total_collisions_;
521 return prepare_for_tessellation(std::vector<int>(), grouping_of_spheres, result, time_recorder);
526 time_recorder.reset();
528 result.relevant_collision_ids.clear();
530 if(populated_spheres_.empty())
535 result.relevant_collision_ids.reserve(total_collisions_);
537 for(UnsignedInt id_a=0;id_a<input_spheres_.size();id_a++)
539 if((involvement_of_spheres.empty() || id_a>=involvement_of_spheres.size() || involvement_of_spheres[id_a]>0) && all_exclusion_statuses_[id_a]==0)
541 for(UnsignedInt j=0;j<all_colliding_ids_[id_a].size();j++)
543 const UnsignedInt id_b=all_colliding_ids_[id_a][j].index;
544 const UnsignedInt id_b_canonical=(id_b%input_spheres_.size());
545 if((involvement_of_spheres.empty() || id_b_canonical>=involvement_of_spheres.size() || involvement_of_spheres[id_b_canonical]>0) && all_exclusion_statuses_[id_b_canonical]==0)
547 if(id_b>=input_spheres_.size() || (all_colliding_ids_[id_a].size()<all_colliding_ids_[id_b_canonical].size()) || (id_a<id_b && all_colliding_ids_[id_a].size()==all_colliding_ids_[id_b_canonical].size()))
549 if(grouping_of_spheres.empty() || id_a>=grouping_of_spheres.size() || id_b_canonical>=grouping_of_spheres.size() || grouping_of_spheres[id_a]!=grouping_of_spheres[id_b_canonical])
551 result.relevant_collision_ids.push_back(std::pair<UnsignedInt, UnsignedInt>(id_a, id_b));
559 time_recorder.record_elapsed_miliseconds_and_reset(
"collect relevant collision indices");
565 struct BufferedTemporaryStorage
567 std::vector<UnsignedInt> more_ids_of_affected_input_spheres;
568 std::vector<UnsignedInt> merged_ids_of_affected_input_spheres;
570 void clear() noexcept
572 more_ids_of_affected_input_spheres.clear();
573 merged_ids_of_affected_input_spheres.clear();
577 UnsignedInt size_threshold_for_full_reinit()
const noexcept
579 return static_cast<UnsignedInt
>(input_spheres_.size()/2);
582 void reinit(
const std::vector<SimpleSphere>& new_input_spheres, std::vector<UnsignedInt>& ids_of_changed_input_spheres, std::vector<UnsignedInt>& ids_of_affected_input_spheres,
TimeRecorder& time_recorder) noexcept
584 init(new_input_spheres, periodic_box_, time_recorder);
585 ids_of_changed_input_spheres.clear();
586 ids_of_affected_input_spheres.clear();
589 void set_sphere_periodic_instances(
const UnsignedInt i,
const bool collect_indices, std::vector<UnsignedInt>& collected_indices) noexcept
591 if(i<input_spheres_.size())
594 if(!periodic_box_.enabled())
596 if(populated_spheres_.size()!=input_spheres_.size())
598 populated_spheres_.resize(input_spheres_.size());
600 populated_spheres_[i]=o;
603 collected_indices.push_back(i);
608 if(populated_spheres_.size()!=(input_spheres_.size()*27))
610 populated_spheres_.resize(input_spheres_.size()*27);
612 populated_spheres_[i]=o;
615 collected_indices.push_back(i);
618 for(
int sx=-1;sx<=1;sx++)
620 for(
int sy=-1;sy<=1;sy++)
622 for(
int sz=-1;sz<=1;sz++)
624 if(sx!=0 || sy!=0 || sz!=0)
626 const UnsignedInt mi=(g*input_spheres_.size()+i);
627 populated_spheres_[mi]=periodic_box_.shift_by_weighted_directions(o, static_cast<Float>(sx), static_cast<Float>(sy), static_cast<Float>(sz));
630 collected_indices.push_back(mi);
641 void set_exclusion_status_periodic_instances(
const UnsignedInt i) noexcept
643 if(i<input_spheres_.size() && all_exclusion_statuses_.size()==input_spheres_.size()*27)
645 for(UnsignedInt m=1;m<27;m++)
647 all_exclusion_statuses_[m*input_spheres_.size()+i]=all_exclusion_statuses_[i];
653 std::vector<SimpleSphere> input_spheres_;
654 std::vector<SimpleSphere> populated_spheres_;
655 std::vector<int> all_exclusion_statuses_;
657 std::vector< std::vector<ValuedID> > all_colliding_ids_;
658 UnsignedInt total_collisions_;
659 BufferedTemporaryStorage buffered_temporary_storage_;
Definition: time_recorder.h:7
Definition: spheres_searcher.h:12
Definition: spheres_container.h:14
Definition: spheres_container.h:11
Definition: periodic_box.h:11
Definition: basic_types_and_functions.h:19
Definition: basic_types_and_functions.h:49