00001 #ifndef CCTBX_CRYSTAL_NEIGHBORS_FAST_H
00002 #define CCTBX_CRYSTAL_NEIGHBORS_FAST_H
00003
00004 #include <cctbx/crystal/neighbors_simple.h>
00005 #include <scitbx/cubicles.h>
00006
00007 namespace cctbx { namespace crystal { namespace neighbors {
00008
00010 template <typename FloatType=double, typename IntShiftType=int>
00011 class fast_pair_generator
00012 :
00013 public simple_pair_generator<FloatType, IntShiftType>
00014 {
00015 public:
00017 typedef simple_pair_generator<FloatType, IntShiftType> base_t;
00019 typedef typename base_t::asu_mappings_t asu_mappings_t;
00020
00022 fast_pair_generator() {}
00023
00025
00045 fast_pair_generator(
00046 boost::shared_ptr<
00047 direct_space_asu::asu_mappings<
00048 FloatType, IntShiftType> > const& asu_mappings,
00049 FloatType const& distance_cutoff,
00050 bool minimal=false,
00051 FloatType const& min_cubicle_edge=5,
00052 FloatType const& epsilon=1.e-6)
00053 :
00054 epsilon_(epsilon),
00055 cubicles_(
00056 asu_mappings.get()->mapped_sites_min(),
00057 asu_mappings.get()->mapped_sites_span(),
00058 std::max(distance_cutoff, min_cubicle_edge),
00059 epsilon),
00060 n_boxes_(cubicles_.ref.accessor())
00061 {
00062 CCTBX_ASSERT(epsilon > 0);
00063 CCTBX_ASSERT(epsilon < 0.01);
00064 this->asu_mappings_owner_ = asu_mappings;
00065 this->asu_mappings_ = asu_mappings.get();
00066 this->distance_cutoff_sq_ = distance_cutoff*distance_cutoff;
00067 this->minimal_ = minimal;
00068 af::const_ref<typename asu_mappings_t::array_of_mappings_for_one_site>
00069 const& mappings = this->asu_mappings_->mappings_const_ref();
00070 direct_space_asu::asu_mapping_index mi;
00071 for(mi.i_seq=0;mi.i_seq<mappings.size();mi.i_seq++) {
00072 for(mi.i_sym=0; mi.i_sym<mappings[mi.i_seq].size(); mi.i_sym++) {
00073 std::size_t i1d_cub = cubicles_.ref.accessor()(
00074 cubicles_.i_cubicle(mappings[mi.i_seq][mi.i_sym].mapped_site()));
00075 cubicles_.ref[i1d_cub].push_back(mi);
00076 }
00077 }
00078 restart();
00079 }
00080
00082 FloatType
00083 epsilon() const { return epsilon_; }
00084
00086 scitbx::vec3<unsigned> const&
00087 n_boxes() const { return n_boxes_; }
00088
00090
00092 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType>
00093 next()
00094 {
00095 CCTBX_ASSERT(!this->at_end_);
00096 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType>
00097 result = this->pair_;
00098 incr(false);
00099 while ( !this->at_end_
00100 && this->pair_.dist_sq > this->distance_cutoff_sq_) {
00101 incr(false);
00102 }
00103 return result;
00104 }
00105
00107 void
00108 restart()
00109 {
00110 this->at_end_ = false;
00111 incr(true);
00112 while ( !this->at_end_
00113 && this->pair_.dist_sq > this->distance_cutoff_sq_) {
00114 incr(false);
00115 }
00116 }
00117
00119 std::size_t
00120 count_pairs()
00121 {
00122 std::size_t result = 0;
00123 while (!this->at_end_) {
00124 next();
00125 result++;
00126 }
00127 return result;
00128 }
00129
00131 FloatType
00132 max_distance_sq()
00133 {
00134 FloatType result = -1;
00135 while (!this->at_end_) {
00136 result = std::max(result, next().dist_sq);
00137 }
00138 return result;
00139 }
00140
00146 af::shared<bool>
00147 neighbors_of(af::const_ref<bool> const& primary_selection)
00148 {
00149 CCTBX_ASSERT(primary_selection.size()
00150 == this->asu_mappings_->mappings_const_ref().size());
00151 af::shared<bool> result(
00152 primary_selection.begin(),
00153 primary_selection.end());
00154 af::ref<bool> result_ = result.ref();
00155 while (!this->at_end_) {
00156 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType>
00157 pair = next();
00158 if (primary_selection[pair.i_seq]) result_[pair.j_seq] = true;
00159 else if (primary_selection[pair.j_seq]) result_[pair.i_seq] = true;
00160 }
00161 return result;
00162 }
00163
00164 protected:
00165 FloatType epsilon_;
00166 typedef std::vector<direct_space_asu::asu_mapping_index> box_content_t;
00167 scitbx::cubicles<box_content_t, FloatType> cubicles_;
00168
00169 scitbx::vec3<unsigned> n_boxes_;
00170 scitbx::vec3<unsigned> i_box_;
00171 const box_content_t* boxes_i_;
00172 typename box_content_t::const_iterator boxes_ii_;
00173 scitbx::vec3<unsigned> j_box_min_;
00174 scitbx::vec3<unsigned> j_box_max_;
00175 scitbx::vec3<unsigned> j_box_;
00176 const box_content_t* boxes_j_;
00177 typename box_content_t::const_iterator boxes_ji_;
00178
00179 void
00180 incr(bool start);
00181
00182 bool
00183 is_active_pair(
00184 unsigned i_seq,
00185 direct_space_asu::asu_mapping_index const& other) const
00186 {
00187 if (other.i_seq > i_seq) return true;
00188 if (other.i_seq == i_seq) return (other.i_sym != 0);
00189 return (!this->minimal_ && other.i_sym != 0);
00190 }
00191 };
00192
00193 template <typename FloatType, typename IntShiftType>
00194 void
00195 fast_pair_generator<FloatType, IntShiftType>::
00196 incr(bool start)
00197 {
00198 af::const_ref<typename asu_mappings_t::array_of_mappings_for_one_site>
00199 const& mappings = this->asu_mappings_->mappings_const_ref();
00200 if (!start) goto continue_after_return;
00201 this->pair_.dist_sq = -1;
00202 this->pair_.diff_vec = cartesian<FloatType>(0,0,0);
00203 boxes_i_ = cubicles_.ref.begin();
00204 for(i_box_[0]=0;i_box_[0]<n_boxes_[0];i_box_[0]++) {
00205 j_box_min_[0] = (i_box_[0] == 0 ? 0 : i_box_[0]-1);
00206 j_box_max_[0] = (i_box_[0] == n_boxes_[0]-1 ? i_box_[0] : i_box_[0]+1);
00207 for(i_box_[1]=0;i_box_[1]<n_boxes_[1];i_box_[1]++) {
00208 j_box_min_[1] = (i_box_[1] == 0 ? 0 : i_box_[1]-1);
00209 j_box_max_[1] = (i_box_[1] == n_boxes_[1]-1 ? i_box_[1] : i_box_[1]+1);
00210 for(i_box_[2]=0;i_box_[2]<n_boxes_[2];i_box_[2]++, boxes_i_++) {
00211 j_box_min_[2] = (i_box_[2] == 0 ? 0 : i_box_[2]-1);
00212 j_box_max_[2] = (i_box_[2] == n_boxes_[2]-1 ? i_box_[2] : i_box_[2]+1);
00213 for(boxes_ii_=boxes_i_->begin();
00214 boxes_ii_!=boxes_i_->end();
00215 boxes_ii_++) {
00216 if (boxes_ii_->i_sym != 0) continue;
00217 for(j_box_[0]=j_box_min_[0];j_box_[0]<=j_box_max_[0];j_box_[0]++) {
00218 for(j_box_[1]=j_box_min_[1];j_box_[1]<=j_box_max_[1];j_box_[1]++) {
00219 for(j_box_[2]=j_box_min_[2];j_box_[2]<=j_box_max_[2];j_box_[2]++) {
00220 boxes_j_ = &cubicles_.ref(j_box_);
00221 for(boxes_ji_=boxes_j_->begin();
00222 boxes_ji_!=boxes_j_->end();
00223 boxes_ji_++) {
00224 if (!is_active_pair(boxes_ii_->i_seq, *boxes_ji_)) continue;
00225 this->pair_.i_seq = boxes_ii_->i_seq;
00226 this->pair_.j_seq = boxes_ji_->i_seq;
00227 this->pair_.j_sym = boxes_ji_->i_sym;
00228 this->pair_.diff_vec =
00229 mappings[this->pair_.j_seq][this->pair_.j_sym].mapped_site()
00230 - mappings[this->pair_.i_seq][0].mapped_site();
00231 this->pair_.dist_sq = this->pair_.diff_vec.length_sq();
00232 return;
00233 continue_after_return:;
00234 }
00235 }}}
00236 }
00237 }}}
00238 this->at_end_ = true;
00239 }
00240
00241 }}}
00242
00243 #endif // CCTBX_CRYSTAL_NEIGHBORS_FAST_H