void sort(Master& master, //!< master object const Assigner& assigner, //!< assigner object std::vector<T> Block::* values, //!< all values to sort std::vector<T> Block::* samples, //!< (output) boundaries of blocks size_t num_samples, //!< desired number of samples const Cmp& cmp, //!< comparison function int k = 2, //!< k-ary reduction will be used bool samples_only = false) //!< false: results will be all_to_all exchanged; true: only sort but don't exchange results { bool immediate = master.immediate(); master.set_immediate(false); // NB: although sorter will go out of scope, its member functions sample() // and exchange() will return functors whose copies get saved inside reduce detail::SampleSort<Block,T,Cmp> sorter(values, samples, cmp, num_samples); // swap-reduce to all-gather samples RegularDecomposer<DiscreteBounds> decomposer(1, interval(0,assigner.nblocks()), assigner.nblocks()); RegularSwapPartners partners(decomposer, k); reduce(master, assigner, partners, sorter.sample(), detail::SkipIntermediate(partners.rounds())); // all_to_all to exchange the values if (!samples_only) all_to_all(master, assigner, sorter.exchange(), k); master.set_immediate(immediate); }
void test(int n, int k) { int dim = 2; diy::DiscreteBounds global_bounds(dim); global_bounds.min[0] = global_bounds.min[1] = 0; global_bounds.max[0] = global_bounds.min[1] = 1023; diy::RegularDecomposer<diy::DiscreteBounds> decomposer(dim, global_bounds, n); diy::RegularPartners partners(decomposer, k, false); int kvs_product = 1; for (size_t i = 0; i < partners.rounds(); ++i) kvs_product *= partners.size(i); REQUIRE(kvs_product == n); for (int gid = 0; gid < n; ++gid) for (size_t i = 0; i < partners.rounds(); ++i) { std::vector<int> nbr_gids; partners.fill(i, gid, nbr_gids); for (int nbr_gid : nbr_gids) CHECK(nbr_gid <= n); } }
void kdtree_sampling (Master& master, //!< master object const Assigner& assigner, //!< assigner object int dim, //!< dimensionality const ContinuousBounds& domain, //!< global data extents std::vector<Point> Block::* points, //!< input points to sort into kd-tree size_t samples, //!< number of samples to take in each block bool wrap = false)//!< periodic boundaries in all dimensions { if (assigner.nblocks() & (assigner.nblocks() - 1)) { fprintf(stderr, "KD-tree requires a number of blocks that's a power of 2, got %d\n", assigner.nblocks()); std::abort(); } typedef diy::RegularContinuousLink RCLink; for (size_t i = 0; i < master.size(); ++i) { RCLink* link = static_cast<RCLink*>(master.link(i)); *link = RCLink(dim, domain, domain); if (wrap) // set up the links to self { diy::BlockID self = { master.gid(i), master.communicator().rank() }; for (int j = 0; j < dim; ++j) { diy::Direction dir, wrap_dir; // left dir.x[j] = -1; wrap_dir.x[j] = -1; link->add_neighbor(self); link->add_bounds(domain); link->add_direction(dir); link->add_wrap(wrap_dir); // right dir.x[j] = 1; wrap_dir.x[j] = 1; link->add_neighbor(self); link->add_bounds(domain); link->add_direction(dir); link->add_wrap(wrap_dir); } } } detail::KDTreeSamplingPartition<Block,Point> kdtree_partition(dim, points, samples); detail::KDTreePartners partners(dim, assigner.nblocks(), wrap, domain); reduce(master, assigner, partners, kdtree_partition); // update master.expected to match the links int expected = 0; for (size_t i = 0; i < master.size(); ++i) expected += master.link(i)->size_unique(); master.set_expected(expected); }
// calculates and adds its forces to the current forces of the force field void MMFF94OutOfPlaneBend::updateForces() { const double FC = K0 * 2. * RADIAN_TO_DEGREE * RADIAN_TO_DEGREE; bool us = getForceField()->getUseSelection(); ////////////////////////////////////////////////////////////////// // ids of the non-central atoms for the three runs per out of plane bend: vector<vector<Position> > atom_ids; // Atom i: vector<Position> temp; temp.push_back(0); temp.push_back(0); temp.push_back(1); atom_ids.push_back(temp); // Atom k: temp.clear(); temp.push_back(1); temp.push_back(2); temp.push_back(2); atom_ids.push_back(temp); // Atom l: temp.clear(); temp.push_back(2); temp.push_back(1); temp.push_back(0); atom_ids.push_back(temp); //////////////////////////////////////////////////////////////////////// // all calculations below have to be performed at double precision // otherwise the results are far off, especially for small wilson angles // // temp variables: double length; TVector3<double> delta; // the three atoms bound to the central atom (for the actual plane bend) vector<Atom*> partners(3); // lenght of the vectors from the central atom to outer atoms: vector<double> lengths(3); // normalized bond vectors from central atom to outer atoms: vector<TVector3<double> > nbv(3); // index of the individual atoms in partners and nbv: Position pi, pk, pl; // normal vectors of the three planes: TVector3<double> an, bn, cn; for (Position t = 0; t < bends_.size(); t++) { // the current bend const OutOfPlaneBend& bend = bends_[t]; Atom& ta1 = *bend.i->ptr; Atom& ta2 = *bend.j->ptr; Atom& ta3 = *bend.k->ptr; Atom& ta4 = *bend.l->ptr; // if using selection and no atom is selected: ignore this bend: if (us && !ta1.isSelected() && !ta2.isSelected() && !ta3.isSelected() && !ta4.isSelected()) { continue; } // non central atoms for this bend: partners[0] = &ta1; partners[1] = &ta3; partners[2] = &ta4; Atom& center_atom = ta2; // abort for this bend if two atoms have the same position: bool error = false; // calculate normalized bond vectors from central atom to outer atoms: for (Position p = 0; p < 3; p++) { // transformation from single to double precision: delta.x = partners[p]->getPosition().x - center_atom.getPosition().x; delta.y = partners[p]->getPosition().y - center_atom.getPosition().y; delta.z = partners[p]->getPosition().z - center_atom.getPosition().z; length = delta.getLength(); if (Maths::isZero(length)) { error = true; break; } // normalize the bond vector: delta /= length; // store the normalized bond vector: nbv[p] = delta; // store length of this bond: lengths[p] = length; } // abort if any bond lenght equals zero if (error) continue; // three runs per OOP: for (Position run = 0; run < 3; run++) { // position of the individual atoms in partners[] and nbv[] pi = atom_ids[0][run]; pk = atom_ids[1][run]; pl = atom_ids[2][run]; Atom& i = *partners[pi]; Atom& k = *partners[pk]; Atom& l = *partners[pl]; // normalized vectors from central atom to outer atoms: const TVector3<double>& ji = nbv[pi]; const TVector3<double>& jk = nbv[pk]; const TVector3<double>& jl = nbv[pl]; const double& length_ji = lengths[pi]; const double& length_jk = lengths[pk]; const double& length_jl = lengths[pl]; // the normal vectors of the three planes: an = ji % jk; bn = jk % jl; cn = jl % ji; // Bond angle ji to jk const double cos_theta = ji * jk; const double theta = acos(cos_theta); // If theta equals 180 degree or 0 degree if (Maths::isZero(theta) || Maths::isZero(fabs(theta - Constants::PI))) { continue; } const double sin_theta = sin(theta); const double sin_dl = an * jl / sin_theta; // the wilson angle: const double dl = asin(sin_dl); // In case: wilson angle equals 0 or 180 degree: do nothing if (Maths::isZero(dl) || Maths::isZero(fabs(dl - Constants::PI))) { continue; } const double cos_dl = cos(dl); // if wilson angle equal 90 degree: abort if (cos_dl < 0.0001) { continue; } // scaling factor for all forces: // wilson K0 * this_bend_constant * wilson_angle * DEGREE_TO_RADIAN * DEGREE_TO_RADIAN double c1 = -dl * FC * bend.k_oop * FORCES_FACTOR * Constants::JOULE_PER_CAL; double tmp = cos_dl / c1; /* Log.precision(30); Log.error() << "bond " << theta << std::endl; Log.error() << "wilson " << dl << std::endl; Log.error() << "tan_dl " << tan_dl << std::endl; Log.error() << "cdst " << cdst << std::endl; Log.error() << "tdst " << tdst << std::endl; Log.error() << "c1 " << c1 << std::endl; Log.error() << "abc " << an << bn << cn << std::endl << std::endl << std::endl << std::endl; */ const TVector3<double> d_l = ((an / sin_theta - jl * sin_dl) / length_jl) / tmp; const TVector3<double> d_i = (((bn + (((-ji + jk * cos_theta) * sin_dl) / sin_theta)) / length_ji) / tmp) / sin_theta; const TVector3<double> d_k = (((cn + (((-jk + ji * cos_theta) * sin_dl) / sin_theta)) / length_jk) / tmp) / sin_theta; if (!us || i.isSelected()) AddDV3_(i.getForce(), d_i); if (!us || k.isSelected()) AddDV3_(k.getForce(), d_k); if (!us || l.isSelected()) AddDV3_(l.getForce(), d_l); if (!us || center_atom.isSelected()) AddDV3_(center_atom.getForce(), -(d_i + d_k + d_l)); #ifdef BALL_MMFF94_TEST getForceField()->error() << std::endl << i.getName() << " " << d_i << std::endl << center_atom.getName() << " " << -(d_i +d_k + d_l) << std::endl << k.getName() << " " << d_k << std::endl << l.getName() << " " << d_l << std::endl; #endif } } }