30#include "communication.hpp"
31#include "system/System.hpp"
37#include <boost/mpi/collectives/all_reduce.hpp>
44#include <unordered_map>
53 std::vector<int> buffer_pid{};
54 std::vector<T> buffer_obs{};
62 if (ptr !=
nullptr and not ptr->is_ghost()) {
63 buffer_pid.emplace_back(pid);
64 buffer_obs.emplace_back(
kernel(*ptr));
69 std::unordered_map<int, T> map{};
73 for (std::size_t i = 0u; i < buffer_pid.size(); ++i) {
74 map[buffer_pid[i]] = buffer_obs[i];
107 int chain_length,
int n_chains) {
110 double dist = 0.0, dist2 = 0.0, dist4 = 0.0;
111 std::array<double, 4> re{};
113 for (
int i = 0; i < n_chains; i++) {
114 auto const pid2 = chain_start + i * chain_length;
115 auto const pid1 = pid2 + chain_length - 1;
116 prefetch.fetch(cell_structure, pid1);
117 prefetch.fetch(cell_structure, pid2);
119 auto const map = prefetch.join();
121 for (
int i = 0; i < n_chains; i++) {
122 auto const pid2 = chain_start + i * chain_length;
123 auto const pid1 = pid2 + chain_length - 1;
124 auto const norm2 = (map.at(pid1) - map.at(pid2)).norm2();
127 dist4 += norm2 * norm2;
129 auto const tmp =
static_cast<double>(n_chains);
132 re[1] = (n_chains == 1) ? 0. : std::sqrt(re[2] -
Utils::sqr(re[0]));
133 re[3] = (n_chains == 1) ? 0. : std::sqrt(dist4 / tmp -
Utils::sqr(re[2]));
139 int chain_length,
int n_chains) {
144 double r_G = 0.0, r_G2 = 0.0, r_G4 = 0.0;
145 std::array<double, 4> rg{};
147 auto has_virtual =
false;
148 for (
int i = 0; i < n_chains * chain_length; ++i) {
149 auto const pid = chain_start + i;
150 auto const ptr = cell_structure.get_local_particle(pid);
151 if (ptr !=
nullptr and not ptr->is_ghost() and ptr->is_virtual()) {
156 if (boost::mpi::all_reduce(
::comm_cart, has_virtual, std::logical_or<>{})) {
157 throw std::runtime_error(
158 "Center of mass is not well-defined for chains including virtual "
159 "sites. Virtual sites do not have a meaningful mass.");
162 for (
int i = 0; i < n_chains * chain_length; ++i) {
163 auto const pid = chain_start + i;
164 prefetch_com.fetch(cell_structure, pid);
165 prefetch_pos.fetch(cell_structure, pid);
166 prefetch_mass.fetch(cell_structure, pid);
169 auto const map_pos = prefetch_pos.join();
170 auto const map_com = prefetch_com.join();
171 auto const map_mass = prefetch_mass.join();
173 for (
int i = 0; i < n_chains; i++) {
176 for (
int j = 0; j < chain_length; j++) {
177 auto const pid = chain_start + i * chain_length + j;
178 r_CM += map_com.
at(pid);
179 M += map_mass.at(pid);
183 for (
int j = 0; j < chain_length; ++j) {
184 auto const pid = chain_start + i * chain_length + j;
185 auto const d = map_pos.at(pid) - r_CM;
188 tmp /=
static_cast<double>(chain_length);
193 auto const tmp =
static_cast<double>(n_chains);
196 rg[1] = (n_chains == 1) ? 0. : std::sqrt(rg[2] -
Utils::sqr(rg[0]));
197 rg[3] = (n_chains == 1) ? 0. : std::sqrt(r_G4 / tmp -
Utils::sqr(rg[2]));
203 int chain_length,
int n_chains) {
204 assert(chain_length >= 2);
207 double r_H = 0.0, r_H2 = 0.0;
208 std::array<double, 2> rh{};
210 auto const chain_l =
static_cast<double>(chain_length);
211 auto const prefac = 0.5 * chain_l * (chain_l - 1.);
212 for (
int p = 0; p < n_chains; p++) {
213 for (
int i = chain_start + chain_length * p;
214 i < chain_start + chain_length * (p + 1); i++) {
215 prefetch.fetch(cell_structure, i);
216 for (
int j = i + 1; j < chain_start + chain_length * (p + 1); j++) {
217 prefetch.fetch(cell_structure, j);
221 auto const map = prefetch.join();
223 for (
int p = 0; p < n_chains; p++) {
225 for (
int i = chain_start + chain_length * p;
226 i < chain_start + chain_length * (p + 1); i++) {
227 for (
int j = i + 1; j < chain_start + chain_length * (p + 1); j++) {
228 ri += 1.0 / (map.at(i) - map.at(j)).norm();
231 auto const tmp = prefac / ri;
235 auto const tmp =
static_cast<double>(n_chains);
237 rh[1] = (n_chains == 1) ? 0. : std::sqrt(r_H2 / tmp -
Utils::sqr(rh[0]));
Vector implementation and trait types for boost qvm interoperability.
auto unfolded_position(Utils::Vector3d const &pos, Utils::Vector3i const &image_box) const noexcept
Unfold particle coordinates to image box.
Describes a cell structure / cell system.
Particle * get_local_particle(int id)
Get a local particle by id.
std::shared_ptr< CellStructure > cell_structure
std::shared_ptr< BoxGeometry > box_geo
DEVICE_QUALIFIER constexpr reference at(size_type i)
boost::mpi::communicator comm_cart
The communicator.
void gather_buffer(std::vector< T, Allocator > &buffer, boost::mpi::communicator const &comm, int root=0)
Gather buffer with different size on each node.
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
std::array< double, 4 > calc_rg(System::System const &system, int chain_start, int chain_length, int n_chains)
Calculate the radius of gyration.
std::array< double, 2 > calc_rh(System::System const &system, int chain_start, int chain_length, int n_chains)
Calculate the hydrodynamic radius (ref.
std::array< double, 4 > calc_re(System::System const &system, int chain_start, int chain_length, int n_chains)
Calculate the end-to-end-distance.
This file contains the code for statistics on chains.
GatherCom(BoxGeometry const &box_geo)
BoxGeometry const & m_box_geo
Utils::Vector3d kernel(Particle const &p) const override
~GatherCom() override=default
~GatherMass() override=default
double kernel(Particle const &p) const override
Gather particle properties (or any derived quantities) on MPI rank 0.
virtual T kernel(Particle const &) const =0
void fetch(CellStructure const &cell_structure, int pid)
virtual ~GatherParticleTraits()=default
BoxGeometry const & m_box_geo
Utils::Vector3d kernel(Particle const &p) const override
~GatherPos() override=default
GatherPos(BoxGeometry const &box_geo)
Struct holding all information for one particle.
constexpr auto const & pos() const
constexpr auto const & mass() const
constexpr auto const & image_box() const