00001 #ifndef CCTBX_GEOMETRY_RESTRAINTS_BOND_H
00002 #define CCTBX_GEOMETRY_RESTRAINTS_BOND_H
00003
00004 #include <cctbx/geometry_restraints/utils.h>
00005 #include <cctbx/geometry_restraints/asu_cache.h>
00006 #include <cctbx/geometry_restraints/sorted_asu_proxies.h>
00007
00008 namespace cctbx { namespace geometry_restraints {
00009
00011 struct bond_params
00012 {
00014 bond_params() {}
00015
00017 bond_params(
00018 double distance_ideal_,
00019 double weight_,
00020 double slack_=0)
00021 :
00022 distance_ideal(distance_ideal_),
00023 weight(weight_),
00024 slack(slack_)
00025 {}
00026
00028 double distance_ideal;
00030 double weight;
00032 double slack;
00033 };
00034
00036 typedef std::map<unsigned, bond_params> bond_params_dict;
00038 typedef af::shared<bond_params_dict> bond_params_table;
00039
00041 struct bond_simple_proxy : bond_params
00042 {
00044 bond_simple_proxy() {}
00045
00047 bond_simple_proxy(
00048 af::tiny<unsigned, 2> const& i_seqs_,
00049 double distance_ideal_,
00050 double weight_,
00051 double slack_=0)
00052 :
00053 bond_params(distance_ideal_, weight_, slack_),
00054 i_seqs(i_seqs_)
00055 {}
00056
00058
00060 bond_simple_proxy(
00061 af::tiny<unsigned, 2> const& i_seqs_,
00062 bond_params const& params)
00063 :
00064 bond_params(params),
00065 i_seqs(i_seqs_)
00066 {}
00067
00069 bond_simple_proxy
00070 sort_i_seqs() const
00071 {
00072 bond_simple_proxy result(*this);
00073 if (result.i_seqs[0] > result.i_seqs[1]) {
00074 std::swap(result.i_seqs[0], result.i_seqs[1]);
00075 }
00076 return result;
00077 }
00078
00080 af::tiny<unsigned, 2> i_seqs;
00081 };
00082
00084 struct bond_sym_proxy : bond_params
00085 {
00087 bond_sym_proxy() {}
00088
00090 bond_sym_proxy(
00091 af::tiny<unsigned, 2> const& i_seqs_,
00092 sgtbx::rt_mx const& rt_mx_ji_,
00093 double distance_ideal_,
00094 double weight_,
00095 double slack_=0)
00096 :
00097 bond_params(distance_ideal_, weight_, slack_),
00098 i_seqs(i_seqs_),
00099 rt_mx_ji(rt_mx_ji_)
00100 {}
00101
00103
00105 bond_sym_proxy(
00106 af::tiny<unsigned, 2> const& i_seqs_,
00107 sgtbx::rt_mx const& rt_mx_ji_,
00108 bond_params const& params)
00109 :
00110 bond_params(params),
00111 i_seqs(i_seqs_),
00112 rt_mx_ji(rt_mx_ji_)
00113 {}
00114
00116 af::tiny<unsigned, 2> i_seqs;
00117
00119
00122 sgtbx::rt_mx rt_mx_ji;
00123 };
00124
00126 struct bond_asu_proxy : bond_params, asu_mapping_index_pair
00127 {
00129 bond_asu_proxy() {}
00130
00132 bond_asu_proxy(
00133 asu_mapping_index_pair const& pair_,
00134 double distance_ideal_,
00135 double weight_,
00136 double slack_=0)
00137 :
00138 bond_params(distance_ideal_, weight_, slack_),
00139 asu_mapping_index_pair(pair_)
00140 {}
00141
00143 bond_asu_proxy(
00144 asu_mapping_index_pair const& pair_,
00145 bond_params const& params)
00146 :
00147 bond_params(params),
00148 asu_mapping_index_pair(pair_)
00149 {}
00150
00152 bond_simple_proxy
00153 as_simple_proxy() const
00154 {
00155 return bond_simple_proxy(
00156 af::tiny<unsigned, 2>(i_seq, j_seq),
00157 distance_ideal,
00158 weight,
00159 slack);
00160 }
00161 };
00162
00164 class bond : public bond_params
00165 {
00166 public:
00168 typedef scitbx::vec3<double> vec3;
00169
00171 bond() {}
00172
00174 bond(
00175 af::tiny<scitbx::vec3<double>, 2> const& sites_,
00176 double distance_ideal_,
00177 double weight_,
00178 double slack_=0)
00179 :
00180 bond_params(distance_ideal_, weight_, slack_),
00181 sites(sites_)
00182 {
00183 init_distance_model();
00184 }
00185
00189 bond(
00190 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00191 bond_simple_proxy const& proxy)
00192 :
00193 bond_params(proxy.distance_ideal, proxy.weight, proxy.slack)
00194 {
00195 for(int i=0;i<2;i++) {
00196 std::size_t i_seq = proxy.i_seqs[i];
00197 CCTBX_ASSERT(i_seq < sites_cart.size());
00198 sites[i] = sites_cart[i_seq];
00199 }
00200 init_distance_model();
00201 }
00202
00207 bond(
00208 uctbx::unit_cell const& unit_cell,
00209 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00210 bond_sym_proxy const& proxy)
00211 :
00212 bond_params(proxy.distance_ideal, proxy.weight, proxy.slack)
00213 {
00214 for(int i=0;i<2;i++) {
00215 std::size_t i_seq = proxy.i_seqs[i];
00216 CCTBX_ASSERT(i_seq < sites_cart.size());
00217 sites[i] = sites_cart[i_seq];
00218 }
00219 sites[1] = unit_cell.orthogonalize(
00220 proxy.rt_mx_ji * unit_cell.fractionalize(sites[1]));
00221 init_distance_model();
00222 }
00223
00227 bond(
00228 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00229 direct_space_asu::asu_mappings<> const& asu_mappings,
00230 bond_asu_proxy const& proxy)
00231 :
00232 bond_params(proxy.distance_ideal, proxy.weight, proxy.slack)
00233 {
00234 sites[0] = asu_mappings.map_moved_site_to_asu(
00235 sites_cart[proxy.i_seq], proxy.i_seq, 0);
00236 sites[1] = asu_mappings.map_moved_site_to_asu(
00237 sites_cart[proxy.j_seq], proxy.j_seq, proxy.j_sym);
00238 init_distance_model();
00239 }
00240
00242 bond(
00243 asu_cache<> const& cache,
00244 bond_asu_proxy const& proxy)
00245 :
00246 bond_params(proxy.distance_ideal, proxy.weight, proxy.slack)
00247 {
00248 sites[0] = cache.sites[proxy.i_seq][0];
00249 sites[1] = cache.sites[proxy.j_seq][proxy.j_sym];
00250 init_distance_model();
00251 }
00252
00254
00256 double
00257 residual() const { return weight * scitbx::fn::pow2(delta_slack); }
00258
00260
00262 scitbx::vec3<double>
00263 gradient_0(double epsilon=1.e-100) const
00264 {
00265 if (distance_model < epsilon) return scitbx::vec3<double>(0,0,0);
00266 if (delta < -slack || delta > slack) {
00267 return -weight * 2 * delta_slack
00268 / distance_model * (sites[0] - sites[1]);
00269 }
00270 return scitbx::vec3<double>(0,0,0);
00271 }
00272
00274 af::tiny<scitbx::vec3<double>, 2>
00275 gradients() const
00276 {
00277 af::tiny<vec3, 2> result;
00278 result[0] = gradient_0();
00279 result[1] = -result[0];
00280 return result;
00281 }
00282
00284
00286 void
00287 add_gradients(
00288 af::ref<scitbx::vec3<double> > const& gradient_array,
00289 af::tiny<unsigned, 2> const& i_seqs) const
00290 {
00291 vec3 g0 = gradient_0();
00292 gradient_array[i_seqs[0]] += g0;
00293 gradient_array[i_seqs[1]] += -g0;
00294 }
00295
00297
00299 void
00300 add_gradients(
00301 af::ref<scitbx::vec3<double> > const& gradient_array,
00302 direct_space_asu::asu_mappings<> const& asu_mappings,
00303 asu_mapping_index_pair const& pair) const
00304 {
00305 vec3 grad_asu = gradient_0();
00306 vec3 grad_i_seq = asu_mappings.r_inv_cart(pair.i_seq, 0) * grad_asu;
00307 gradient_array[pair.i_seq] += grad_i_seq;
00308 if (pair.j_sym == 0) {
00309 vec3 grad_j_seq = asu_mappings.r_inv_cart(pair.j_seq, 0) * grad_asu;
00310 gradient_array[pair.j_seq] -= grad_j_seq;
00311 }
00312 }
00313
00315
00317 void
00318 add_gradients(
00319 asu_cache<>& cache,
00320 asu_mapping_index_pair const& pair) const
00321 {
00322 vec3 grad_asu = gradient_0();
00323 cache.gradients[pair.i_seq] += grad_asu;
00324 if (pair.j_sym == 0) {
00325 cache.gradients[pair.j_seq] -= grad_asu;
00326 }
00327 }
00328
00330 af::tiny<scitbx::vec3<double>, 2> sites;
00332 double distance_model;
00334 double delta;
00336 double delta_slack;
00337
00338 protected:
00339 void
00340 init_distance_model()
00341 {
00342 distance_model = (sites[0] - sites[1]).length();
00343 delta = distance_ideal - distance_model;
00344 CCTBX_ASSERT(slack >= 0);
00345 if (delta > slack) {
00346 delta_slack = delta - slack;
00347 }
00348 else if (delta >= -slack) {
00349 delta_slack = 0;
00350 }
00351 else {
00352 delta_slack = delta + slack;
00353 }
00354 }
00355 };
00356
00358 inline
00359 bond_params_table
00360 extract_bond_params(
00361 std::size_t n_seq,
00362 af::const_ref<bond_simple_proxy> const& bond_simple_proxies)
00363 {
00364 bond_params_table tab(n_seq);
00365 af::ref<bond_params_dict> tab_ref = tab.ref();
00366 for(std::size_t i_proxy=0;i_proxy<bond_simple_proxies.size();i_proxy++) {
00367 af::tiny<unsigned, 2> const& i_seqs=bond_simple_proxies[i_proxy].i_seqs;
00368 CCTBX_ASSERT(i_seqs[0] < tab_ref.size());
00369 CCTBX_ASSERT(i_seqs[1] < tab_ref.size());
00370 if (i_seqs[0] < i_seqs[1]) {
00371 tab_ref[i_seqs[0]][i_seqs[1]] = bond_simple_proxies[i_proxy];
00372 }
00373 else {
00374 tab_ref[i_seqs[1]][i_seqs[0]] = bond_simple_proxies[i_proxy];
00375 }
00376 }
00377 return tab;
00378 }
00379
00381 inline
00382 af::shared<double>
00383 bond_distances_model(
00384 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00385 af::const_ref<bond_simple_proxy> const& proxies)
00386 {
00387 af::shared<double> result((af::reserve(proxies.size())));
00388 for(std::size_t i=0;i<proxies.size();i++) {
00389 bond restraint(sites_cart, proxies[i]);
00390 result.push_back(restraint.distance_model);
00391 }
00392 return result;
00393 }
00394
00396 inline
00397 af::shared<double>
00398 bond_deltas(
00399 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00400 af::const_ref<bond_simple_proxy> const& proxies)
00401 {
00402 return detail::generic_deltas<bond_simple_proxy, bond>::get(
00403 sites_cart, proxies);
00404 }
00405
00407 inline
00408 af::shared<double>
00409 bond_residuals(
00410 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00411 af::const_ref<bond_simple_proxy> const& proxies)
00412 {
00413 return detail::generic_residuals<bond_simple_proxy, bond>::get(
00414 sites_cart, proxies);
00415 }
00416
00426 inline
00427 double
00428 bond_residual_sum(
00429 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00430 af::const_ref<bond_simple_proxy> const& proxies,
00431 af::ref<scitbx::vec3<double> > const& gradient_array)
00432 {
00433 return detail::generic_residual_sum<bond_simple_proxy, bond>::get(
00434 sites_cart, proxies, gradient_array);
00435 }
00436
00438 typedef sorted_asu_proxies<bond_simple_proxy, bond_asu_proxy>
00439 bond_sorted_asu_proxies_base;
00440
00442 inline
00443 af::shared<double>
00444 bond_distances_model(
00445 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00446 bond_sorted_asu_proxies_base const& sorted_asu_proxies)
00447 {
00448 af::shared<double> result = bond_distances_model(
00449 sites_cart, sorted_asu_proxies.simple.const_ref());
00450 af::const_ref<bond_asu_proxy> sym = sorted_asu_proxies.asu.const_ref();
00451 if (sym.size() > 0) {
00452 result.reserve(sorted_asu_proxies.simple.size() + sym.size());
00453 direct_space_asu::asu_mappings<> const&
00454 asu_mappings = *sorted_asu_proxies.asu_mappings();
00455 for(std::size_t i=0;i<sym.size();i++) {
00456 bond restraint(sites_cart, asu_mappings, sym[i]);
00457 result.push_back(restraint.distance_model);
00458 }
00459 }
00460 return result;
00461 }
00462
00464 inline
00465 af::shared<double>
00466 bond_deltas(
00467 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00468 bond_sorted_asu_proxies_base const& sorted_asu_proxies)
00469 {
00470 af::shared<double> result = bond_deltas(
00471 sites_cart, sorted_asu_proxies.simple.const_ref());
00472 af::const_ref<bond_asu_proxy> sym = sorted_asu_proxies.asu.const_ref();
00473 if (sym.size() > 0) {
00474 result.reserve(sorted_asu_proxies.simple.size() + sym.size());
00475 direct_space_asu::asu_mappings<> const&
00476 asu_mappings = *sorted_asu_proxies.asu_mappings();
00477 for(std::size_t i=0;i<sym.size();i++) {
00478 bond restraint(sites_cart, asu_mappings, sym[i]);
00479 result.push_back(restraint.delta);
00480 }
00481 }
00482 return result;
00483 }
00484
00486 inline
00487 af::shared<double>
00488 bond_residuals(
00489 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00490 bond_sorted_asu_proxies_base const& sorted_asu_proxies)
00491 {
00492 af::shared<double> result = bond_residuals(
00493 sites_cart, sorted_asu_proxies.simple.const_ref());
00494 af::const_ref<bond_asu_proxy> sym = sorted_asu_proxies.asu.const_ref();
00495 if (sym.size() > 0) {
00496 result.reserve(sorted_asu_proxies.simple.size() + sym.size());
00497 direct_space_asu::asu_mappings<> const&
00498 asu_mappings = *sorted_asu_proxies.asu_mappings();
00499 for(std::size_t i=0;i<sym.size();i++) {
00500 bond restraint(sites_cart, asu_mappings, sym[i]);
00501 result.push_back(restraint.residual());
00502 }
00503 }
00504 return result;
00505 }
00506
00507 namespace detail {
00508
00509 inline
00510 double
00511 bond_residual_sum(
00512 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00513 direct_space_asu::asu_mappings<> const& asu_mappings,
00514 af::const_ref<bond_asu_proxy> const& proxies,
00515 std::vector<bool> const& sym_active_flags,
00516 af::ref<scitbx::vec3<double> > const& gradient_array,
00517 bool disable_cache=false)
00518 {
00519 double result = 0;
00520 if (!disable_cache) {
00521 asu_cache<> cache(
00522 sites_cart,
00523 asu_mappings,
00524 sym_active_flags,
00525 gradient_array.size() != 0);
00526 for(std::size_t i=0;i<proxies.size();i++) {
00527 bond restraint(cache, proxies[i]);
00528 if (proxies[i].j_sym == 0) result += restraint.residual();
00529 else result += restraint.residual()*.5;
00530 if (gradient_array.size() != 0) {
00531 restraint.add_gradients(cache, proxies[i]);
00532 }
00533 }
00534 if (gradient_array.size() != 0) {
00535 cache.add_gradients(gradient_array, asu_mappings);
00536 }
00537 }
00538 else {
00539 for(std::size_t i=0;i<proxies.size();i++) {
00540 bond restraint(sites_cart, asu_mappings, proxies[i]);
00541 if (proxies[i].j_sym == 0) result += restraint.residual();
00542 else result += restraint.residual()*.5;
00543 if (gradient_array.size() != 0) {
00544 restraint.add_gradients(gradient_array, asu_mappings, proxies[i]);
00545 }
00546 }
00547 }
00548 return result;
00549 }
00550
00551 }
00552
00567 inline
00568 double
00569 bond_residual_sum(
00570 af::const_ref<scitbx::vec3<double> > const& sites_cart,
00571 bond_sorted_asu_proxies_base const& sorted_asu_proxies,
00572 af::ref<scitbx::vec3<double> > const& gradient_array,
00573 bool disable_cache=false)
00574 {
00575 double result = bond_residual_sum(
00576 sites_cart,
00577 sorted_asu_proxies.simple.const_ref(),
00578 gradient_array);
00579 if (sorted_asu_proxies.asu.size() > 0) {
00580 result += detail::bond_residual_sum(
00581 sites_cart,
00582 *sorted_asu_proxies.asu_mappings(),
00583 sorted_asu_proxies.asu.const_ref(),
00584 sorted_asu_proxies.asu_active_flags,
00585 gradient_array,
00586 disable_cache);
00587 }
00588 return result;
00589 }
00590
00591 }}
00592
00593 #endif // CCTBX_GEOMETRY_RESTRAINTS_BOND_H