ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
RDF.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include "RDF.hpp"
20
21#include "BoxGeometry.hpp"
22#include "fetch_particles.hpp"
23#include "system/System.hpp"
24
25#include <utils/Vector.hpp>
28
29#include <boost/mpi/communicator.hpp>
30#include <boost/range/combine.hpp>
31
32#include <algorithm>
33#include <cmath>
34#include <cstddef>
35#include <numbers>
36#include <vector>
37
38namespace Observables {
39std::vector<double>
40RDF::operator()(boost::mpi::communicator const &comm) const {
41 auto const &local_particles_1 = fetch_particles(ids1());
42
43 if (ids2().empty()) {
44 return this->evaluate(comm, local_particles_1, {}, {});
45 }
46
47 auto const &local_particles_2 = fetch_particles(ids2());
48
49 return this->evaluate(comm, local_particles_1, local_particles_2, {});
50}
51
52std::vector<double>
53RDF::evaluate(boost::mpi::communicator const &comm,
57 auto const positions_1 = detail::get_all_particle_positions(
58 comm, local_particles_1, ids1(), traits, false);
59 auto const positions_2 = detail::get_all_particle_positions(
60 comm, local_particles_2, ids2(), traits, false);
61
62 if (comm.rank() != 0) {
63 return {};
64 }
65
66 auto const &box_geo = *System::get_system().box_geo;
67 auto const bin_width = (max_r - min_r) / static_cast<double>(n_r_bins);
68 auto const inv_bin_width = 1.0 / bin_width;
69 std::vector<double> res(n_r_bins, 0.0);
70 long int cnt = 0;
71 auto op = [this, inv_bin_width, &cnt, &res, &box_geo](auto const &pos1,
72 auto const &pos2) {
73 auto const dist = box_geo.get_mi_vector(pos1, pos2).norm();
74 if (dist > min_r && dist < max_r) {
75 auto ind = static_cast<long>(std::floor((dist - min_r) * inv_bin_width));
76 ind = std::clamp(ind, 0l, static_cast<long>(n_r_bins) - 1l);
77 res[ind]++;
78 }
79 cnt++;
80 };
81
82 if (local_particles_2.empty()) {
84 } else {
85 auto const combine_1 = boost::combine(ids1(), positions_1);
86 auto const combine_2 = boost::combine(ids2(), positions_2);
87
88 auto op2 = [&op](auto const &it1, auto const &it2) {
89 auto const &[id1, pos1] = it1;
90 auto const &[id2, pos2] = it2;
91
92 op(pos1, pos2);
93 };
94
95 auto cmp = [](auto const &it1, auto const &it2) {
96 auto const &[id1, pos1] = it1;
97 auto const &[id2, pos2] = it2;
98
99 return id1 != id2;
100 };
102 }
103 if (cnt == 0)
104 return res;
105 // normalization
106 auto const volume = box_geo.volume();
107 for (std::size_t i = 0u; i < res.size(); ++i) {
108 auto const r_in = static_cast<double>(i) * bin_width + min_r;
109 auto const r_out = r_in + bin_width;
110 auto const bin_volume =
111 (4. / 3.) * std::numbers::pi *
112 (Utils::int_pow<3>(r_out) - Utils::int_pow<3>(r_in));
113 res[i] *= volume / (bin_volume * static_cast<double>(cnt));
114 }
115
116 return res;
117}
118} // namespace Observables
Vector implementation and trait types for boost qvm interoperability.
std::vector< int > & ids2()
std::vector< int > & ids1()
std::vector< double > operator()(boost::mpi::communicator const &comm) const final
Definition RDF.cpp:40
std::shared_ptr< BoxGeometry > box_geo
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
auto fetch_particles(std::vector< int > const &ids)
Fetch a group of particles.
std::vector< std::reference_wrapper< Particle const > > ParticleReferenceRange
System & get_system()
void for_each_pair(ForwardIterator first, ForwardIterator last, BinaryOp op)
Execute op for each pair of elements in [first, last) once.
void for_each_cartesian_pair_if(ForwardIterator first1, ForwardIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryOp op, BinaryCmp cmp)
Execute op for each pair of elements between [first1, last1) and [first2, last2) if a condition is sa...