ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
oif_global_forces.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-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
20#include "oif_global_forces.hpp"
21
22#include "BoxGeometry.hpp"
23#include "Particle.hpp"
26#include "communication.hpp"
28#include "system/System.hpp"
29
30#include <utils/Vector.hpp>
32
33#include <boost/mpi/collectives/all_reduce.hpp>
34#include <boost/serialization/utility.hpp>
35
36#include <cassert>
37#include <cmath>
38#include <functional>
39#include <span>
40#include <variant>
41
42/** Calculate the mesh volume and area. */
43static auto calc_oif_mesh(int molType, BoxGeometry const &box_geo,
44 CellStructure &cs,
45 BondedInteractionsMap const &bonded_ias) {
46
47 double area = 0.;
48 double volume = 0.;
49
50 cs.bond_loop([&area, &volume, &box_geo, &bonded_ias, molType](
51 Particle &p1, int bond_id, std::span<Particle *> partners) {
52 if (p1.mol_id() != molType)
53 return false;
54
55 if (std::holds_alternative<OifGlobalForcesBond>(*bonded_ias.at(bond_id))) {
56 auto const p11 = box_geo.unfolded_position(p1.pos(), p1.image_box());
57 auto const p22 = p11 + box_geo.get_mi_vector(partners[0]->pos(), p11);
58 auto const p33 = p11 + box_geo.get_mi_vector(partners[1]->pos(), p11);
59
60 auto const VOL_A = Utils::area_triangle(p11, p22, p33);
61 area += VOL_A;
62
64 auto const VOL_dn = VOL_norm.norm();
65 auto const VOL_hz = (1.0 / 3.0) * (p11[2] + p22[2] + p33[2]);
66 volume -= VOL_A * VOL_norm[2] / VOL_dn * VOL_hz;
67 }
68
69 return false;
70 });
71
72 return Utils::Vector2d{{area, volume}};
73}
74
75/** Distribute the OIF global forces to all particles in the mesh. */
76static void add_oif_global_forces(double area, double volume, int molType,
77 BoxGeometry const &box_geo, CellStructure &cs,
78 BondedInteractionsMap const &bonded_ias) {
79
80 cs.bond_loop([&box_geo, &bonded_ias, area, volume, molType](
81 Particle &p1, int bond_id, std::span<Particle *> partners) {
82 if (p1.mol_id() != molType)
83 return false;
84
85 auto const *bond_ptr = bonded_ias.at(bond_id).get();
86 if (auto const *bond = std::get_if<OifGlobalForcesBond>(bond_ptr)) {
87 auto const p11 = box_geo.unfolded_position(p1.pos(), p1.image_box());
88 auto const p22 = p11 + box_geo.get_mi_vector(partners[0]->pos(), p11);
89 auto const p33 = p11 + box_geo.get_mi_vector(partners[1]->pos(), p11);
90
91 // unfolded positions correct
92 // starting code from volume force
94 auto const VOL_A = Utils::area_triangle(p11, p22, p33);
95 auto const VOL_vv = (volume - bond->V0) / bond->V0;
96
97 auto const VOL_force = (1. / 3.) * bond->kv * VOL_vv * VOL_A * VOL_norm;
98
99 auto const h = (1. / 3.) * (p11 + p22 + p33);
100
101 auto const deltaA = (area - bond->A0_g) / bond->A0_g;
102
103 auto const m1 = h - p11;
104 auto const m2 = h - p22;
105 auto const m3 = h - p33;
106
107 auto const m1_length = m1.norm();
108 auto const m2_length = m2.norm();
109 auto const m3_length = m3.norm();
110
111 auto const fac = bond->ka_g * VOL_A * deltaA /
114
115 p1.force() += fac * m1 + VOL_force;
116 partners[0]->force() += fac * m2 + VOL_force;
117 partners[1]->force() += fac * m3 + VOL_force;
118 }
119
120 return false;
121 });
122}
123
124void OifGlobal::run_force_kernel() {
125 auto &system = get_system();
126 auto &box_geo = *system.box_geo;
127 auto &bonded_ias = *system.bonded_ias;
128 auto &cell_structure = *system.cell_structure;
129 for (int i = 0; i < max_oif_objects; ++i) {
130 // There are two global quantities that need to be evaluated:
131 // object's surface and object's volume.
132 auto const local = calc_oif_mesh(i, box_geo, cell_structure, bonded_ias);
133 auto const global = boost::mpi::all_reduce(comm_cart, local, std::plus<>());
134 auto const area = std::abs(global[0]);
135 auto const volume = std::abs(global[1]);
136 if (area < 1e-100 and volume < 1e-100) {
137 break;
138 }
139 add_oif_global_forces(area, volume, i, box_geo, cell_structure, bonded_ias);
140 }
141}
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
container for bonded interactions.
mapped_type at(key_type const &key) const
auto unfolded_position(Utils::Vector3d const &pos, Utils::Vector3i const &image_box) const
Unfold particle coordinates to image box.
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
Describes a cell structure / cell system.
void bond_loop(BondKernel const &bond_kernel)
Bonded pair loop.
Vector & normalize()
Definition Vector.hpp:168
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
boost::mpi::communicator comm_cart
The communicator.
double area_triangle(const Vector3d &P1, const Vector3d &P2, const Vector3d &P3)
Computes the area of triangle between vectors P1,P2,P3, by computing the cross product P1P2 x P1P3 an...
Vector3d get_n_triangle(const Vector3d &P1, const Vector3d &P2, const Vector3d &P3)
Computes the normal vector of a triangle.
static void add_oif_global_forces(double area, double volume, int molType, BoxGeometry const &box_geo, CellStructure &cs, BondedInteractionsMap const &bonded_ias)
Distribute the OIF global forces to all particles in the mesh.
static auto calc_oif_mesh(int molType, BoxGeometry const &box_geo, CellStructure &cs, BondedInteractionsMap const &bonded_ias)
Calculate the mesh volume and area.
Routines to calculate the OIF global forces for a particle triple (triangle from mesh).
Struct holding all information for one particle.
Definition Particle.hpp:450