00001 #ifndef CCTBX_CRYSTAL_COORDINATION_SEQUENCES_H
00002 #define CCTBX_CRYSTAL_COORDINATION_SEQUENCES_H
00003
00004 #include <cctbx/crystal/direct_space_asu.h>
00005 #include <cctbx/crystal/pair_tables.h>
00006
00007 namespace cctbx { namespace crystal {
00008
00010 namespace coordination_sequences {
00011
00015 struct node
00016 {
00018 node() {}
00019
00021 node(
00022 direct_space_asu::asu_mappings<> const& asu_mappings,
00023 unsigned i_seq,
00024 sgtbx::rt_mx const& rt_mx_)
00025 :
00026 rt_mx(rt_mx_),
00027 rt_mx_unique(rt_mx_.multiply(asu_mappings.special_op(i_seq)))
00028 {}
00029
00031 sgtbx::rt_mx rt_mx;
00033 sgtbx::rt_mx rt_mx_unique;
00034 };
00035
00037 struct three_shells
00038 {
00040 three_shells()
00041 {
00042 prev = &all[0];
00043 middle = &all[1];
00044 next = &all[2];
00045 }
00046
00048
00051 void
00052 clear(
00053 direct_space_asu::asu_mappings<> const& asu_mappings,
00054 unsigned i_seq_pivot)
00055 {
00056 prev->clear();
00057 middle->clear();
00058 next->clear();
00059 (*next)[i_seq_pivot].push_back(
00060 node(asu_mappings, i_seq_pivot, sgtbx::rt_mx(1,1)));
00061 }
00062
00064 void
00065 shift()
00066 {
00067 std::map<unsigned, std::vector<node> >* tmp = prev;
00068 prev = middle;
00069 middle = next;
00070 next = tmp;
00071 next->clear();
00072 }
00073
00075 unsigned
00076 count_next() const
00077 {
00078 unsigned result = 0;
00079 for(std::map<unsigned, std::vector<node> >::const_iterator
00080 item_n=next->begin();
00081 item_n!=next->end();
00082 item_n++) {
00083 result += item_n->second.size();
00084 }
00085 return result;
00086 }
00087
00089
00091 bool
00092 find_node(unsigned j_seq, node const& test_node) const
00093 {
00094 for(unsigned i_shell=0;i_shell<3;i_shell++) {
00095 std::map<unsigned, std::vector<node> > const& shell = all[i_shell];
00096 std::map<unsigned, std::vector<node> >::const_iterator
00097 item = shell.find(j_seq);
00098 if (item == shell.end()) continue;
00099 std::vector<node> const& list_nodes = item->second;
00100 for(std::vector<node>::const_iterator
00101 list_node=list_nodes.begin();
00102 list_node!=list_nodes.end();
00103 list_node++) {
00104 if (list_node->rt_mx_unique == test_node.rt_mx_unique) {
00105 return true;
00106 }
00107 }
00108 }
00109 return false;
00110 }
00111
00113 af::tiny<std::map<unsigned, std::vector<node> >, 3> all;
00115 std::map<unsigned, std::vector<node> >* prev;
00117 std::map<unsigned, std::vector<node> >* middle;
00119 std::map<unsigned, std::vector<node> >* next;
00120 };
00121
00123 template <typename Actions>
00124 struct core : Actions
00125 {
00127 core(
00128 crystal::pair_asu_table<> const& pair_asu_table,
00129 unsigned max_shell)
00130 :
00131 Actions(pair_asu_table, max_shell)
00132 {
00133 direct_space_asu::asu_mappings<> const&
00134 asu_mappings = *pair_asu_table.asu_mappings().get();
00135 af::const_ref<pair_asu_dict>
00136 asu_table_ref = pair_asu_table.table().const_ref();
00137 CCTBX_ASSERT(asu_mappings.mappings_const_ref().size()
00138 == asu_table_ref.size());
00139 unsigned n_seq = asu_table_ref.size();
00140 three_shells shells;
00141 for(this->i_seq_pivot=0; this->i_seq_pivot<n_seq; this->i_seq_pivot++) {
00142 sgtbx::rt_mx rt_mx_pivot = asu_mappings.get_rt_mx(this->i_seq_pivot,0);
00143 shells.clear(asu_mappings, this->i_seq_pivot);
00144 for(this->i_shell_minus_1=0;
00145 this->i_shell_minus_1<max_shell;
00146 this->i_shell_minus_1++) {
00147 shells.shift();
00148 for(std::map<unsigned, std::vector<node> >::const_iterator
00149 items_m=shells.middle->begin();
00150 items_m!=shells.middle->end();
00151 items_m++) {
00152 unsigned i_seq_m = items_m->first;
00153 std::vector<node> const& nodes_middle = items_m->second;
00154 sgtbx::rt_mx
00155 rt_mx_i_inv = asu_mappings.get_rt_mx(i_seq_m, 0).inverse();
00156 for(unsigned i_node_m=0;i_node_m<nodes_middle.size();i_node_m++) {
00157 node node_m = nodes_middle[i_node_m];
00158 sgtbx::rt_mx rt_mx_ni = node_m.rt_mx.multiply(rt_mx_i_inv);
00159 pair_asu_dict::const_iterator
00160 pair_asu_dict_end = asu_table_ref[i_seq_m].end();
00161 for(pair_asu_dict::const_iterator
00162 pair_asu_dict_i = asu_table_ref[i_seq_m].begin();
00163 pair_asu_dict_i != pair_asu_dict_end;
00164 pair_asu_dict_i++) {
00165 unsigned j_seq = pair_asu_dict_i->first;
00166 pair_asu_j_sym_groups const&
00167 j_sym_groups=pair_asu_dict_i->second;
00168 for(unsigned i_group=0;
00169 i_group<j_sym_groups.size();
00170 i_group++) {
00171 pair_asu_j_sym_group j_sym_group = j_sym_groups[i_group];
00172 pair_asu_j_sym_group::const_iterator
00173 j_sym_group_end = j_sym_group.end();
00174 for(pair_asu_j_sym_group::const_iterator
00175 j_sym_group_i = j_sym_group.begin();
00176 j_sym_group_i != j_sym_group_end;
00177 j_sym_group_i++) {
00178 unsigned j_sym = *j_sym_group_i;
00179 sgtbx::rt_mx
00180 rt_mx_j = asu_mappings.get_rt_mx(j_seq, j_sym);
00181 node new_node(
00182 asu_mappings, j_seq, rt_mx_ni.multiply(rt_mx_j));
00183 if (!shells.find_node(j_seq, new_node)) {
00184 (*shells.next)[j_seq].push_back(new_node);
00185 }
00186 }
00187 }
00188 }
00189 }
00190 }
00191 this->shell_complete(shells);
00192 }
00193 this->pivot_complete();
00194 }
00195 }
00196 };
00197
00199 struct term_table_actions
00200 {
00202 term_table_actions(
00203 crystal::pair_asu_table<> const& pair_asu_table,
00204 unsigned )
00205 :
00206 terms(0)
00207 {
00208 term_table.reserve(pair_asu_table.table().size());
00209 }
00210
00212 void
00213 shell_complete(three_shells const& shells)
00214 {
00215 if (terms == 0) {
00216 term_table.push_back(std::vector<unsigned>());
00217 terms = &term_table.back();
00218 terms->push_back(1);
00219 }
00220 terms->push_back(shells.count_next());
00221 }
00222
00224 void
00225 pivot_complete() { terms = 0; }
00226
00228 unsigned i_seq_pivot;
00230 unsigned i_shell_minus_1;
00232 af::shared<std::vector<unsigned> > term_table;
00234 std::vector<unsigned>* terms;
00235 };
00236
00238 af::shared<std::vector<unsigned> >
00239 simple(
00240 crystal::pair_asu_table<> const& pair_asu_table,
00241 unsigned max_shell)
00242 {
00243 return core<term_table_actions>(pair_asu_table, max_shell).term_table;
00244 }
00245
00247 struct shell_asu_tables_actions
00248 {
00250 shell_asu_tables_actions(
00251 crystal::pair_asu_table<> const& pair_asu_table,
00252 unsigned max_shell)
00253 {
00254 shell_asu_tables.reserve(max_shell);
00255 if (max_shell > 0) {
00256 shell_asu_tables.push_back(pair_asu_table);
00257 for(i_shell_minus_1=1;
00258 i_shell_minus_1<max_shell;
00259 i_shell_minus_1++) {
00260 shell_asu_tables.push_back(
00261 crystal::pair_asu_table<>(pair_asu_table.asu_mappings()));
00262 }
00263 }
00264 }
00265
00267 void
00268 shell_complete(three_shells const& shells)
00269 {
00270 if (i_shell_minus_1 == 0) return;
00271 pair_asu_table<>& shell_asu_table = shell_asu_tables[i_shell_minus_1];
00272 direct_space_asu::asu_mappings<>*
00273 asu_mappings = shell_asu_table.asu_mappings().get();
00274 sgtbx::rt_mx rt_mx_i = asu_mappings->get_rt_mx(i_seq_pivot, 0);
00275 for(std::map<unsigned, std::vector<node> >::const_iterator
00276 items_n=shells.next->begin();
00277 items_n!=shells.next->end();
00278 items_n++) {
00279 unsigned i_seq_node = items_n->first;
00280 std::vector<node> const& nodes = items_n->second;
00281 for(unsigned i_node=0;i_node<nodes.size();i_node++) {
00282 node const& node_ = nodes[i_node];
00283 sgtbx::rt_mx rt_mx_j = rt_mx_i.multiply(node_.rt_mx);
00284 int j_sym = asu_mappings->find_i_sym(i_seq_node, rt_mx_j);
00285 if (j_sym < 0) continue;
00286 shell_asu_table.process_pair(
00287 i_seq_pivot,
00288 i_seq_node,
00289 node_.rt_mx,
00290 rt_mx_i,
00291 j_sym);
00292 }
00293 }
00294 }
00295
00297 void
00298 pivot_complete() {}
00299
00301 unsigned i_seq_pivot;
00303 unsigned i_shell_minus_1;
00305 std::vector<pair_asu_table<> > shell_asu_tables;
00306 };
00307
00309 std::vector<pair_asu_table<> >
00310 shell_asu_tables(
00311 crystal::pair_asu_table<> const& pair_asu_table,
00312 unsigned max_shell)
00313 {
00314 return core<shell_asu_tables_actions>(pair_asu_table, max_shell)
00315 .shell_asu_tables;
00316 }
00317
00318 }}}
00319
00320 #endif // CCTBX_CRYSTAL_COORDINATION_SEQUENCES_H