15#ifndef SEAMS_GENERIC_H_
16#define SEAMS_GENERIC_H_
29#ifdef SEAMS_HAS_MINIMAGE
64constexpr double pi = std::numbers::pi;
88 int n = (*input).size();
92 std::vector<double> sorted = *input;
93 std::sort(sorted.begin(), sorted.end());
98 median = 0.5 * (sorted[n / 2] + sorted[n / 2 - 1]);
100 median = sorted[(n + 1) / 2 - 1];
106#ifdef SEAMS_HAS_MINIMAGE
108inline mi_cell pointCloudCell(
110 const auto &box = yCloud.box;
111 const auto &boxLow = yCloud.boxLow;
112 const double xlo_b = boxLow.size() > 0 ? boxLow[0] : 0.0;
113 const double ylo_b = boxLow.size() > 1 ? boxLow[1] : 0.0;
114 const double zlo_b = boxLow.size() > 2 ? boxLow[2] : 0.0;
115 mi_cell c = mi_cell_ortho(0.0, 0.0, 0.0);
116 if (box.size() >= 6) {
117 mi_cell_from_lammps_bounds(box[0], box[1], box[2], box[3], box[4], box[5],
118 xlo_b, ylo_b, zlo_b, &c);
119 }
else if (box.size() >= 3) {
120 c = mi_cell_ortho(box[0], box[1], box[2]);
136 double yi,
double zi,
double xj,
double yj,
double zj) {
137#ifdef SEAMS_HAS_MINIMAGE
138 const mi_cell cell = pointCloudCell(yCloud);
139 const double p[3] = {xj, yj, zj};
140 const double q[3] = {xi, yi, zi};
141 double dr[3] = {0.0, 0.0, 0.0};
142 mi_displacement(&cell, p, q, dr);
143 return {dr[0], dr[1], dr[2]};
145 const auto &box = yCloud.box;
146 const auto &boxLow = yCloud.boxLow;
147 const double xspan = box[0];
148 const double yspan = box[1];
149 const double zspan = box[2];
150 const double xlo_b = boxLow.size() > 0 ? boxLow[0] : 0.0;
151 const double ylo_b = boxLow.size() > 1 ? boxLow[1] : 0.0;
152 const double zlo_b = boxLow.size() > 2 ? boxLow[2] : 0.0;
153 const double xy = box[3];
154 const double xz = box[4];
155 const double yz = box[5];
156 const double xmin = std::min(std::min(0.0, xy), std::min(xz, xy + xz));
157 const double xmax = std::max(std::max(0.0, xy), std::max(xz, xy + xz));
158 const double ymin = std::min(0.0, yz);
159 const double ymax = std::max(0.0, yz);
160 const double lx = xspan - xmax + xmin;
161 const double ly = yspan - ymax + ymin;
162 const double lz = zspan;
163 const double ox = xlo_b - xmin;
164 const double oy = ylo_b - ymin;
165 const double oz = zlo_b;
167 auto toFrac = [&](
double x,
double y,
double z) {
168 const double sz = (z - oz) / lz;
169 const double sy = (y - oy - yz * sz) / ly;
170 const double sx = (x - ox - xy * sy - xz * sz) / lx;
171 return std::array<double, 3>{sx, sy, sz};
173 const auto si = toFrac(xi, yi, zi);
174 const auto sj = toFrac(xj, yj, zj);
175 double dsx = si[0] - sj[0];
176 double dsy = si[1] - sj[1];
177 double dsz = si[2] - sj[2];
178 dsx -= std::round(dsx);
179 dsy -= std::round(dsy);
180 dsz -= std::round(dsz);
181 return {lx * dsx + xy * dsy + xz * dsz, ly * dsy + yz * dsz, lz * dsz};
197 int iatom,
int jatom) {
198#ifdef SEAMS_HAS_MINIMAGE
199 const mi_cell cell = pointCloudCell(yCloud);
200 const double p[3] = {yCloud.pts[iatom].x, yCloud.pts[iatom].y,
201 yCloud.pts[iatom].z};
202 const double q[3] = {yCloud.pts[jatom].x, yCloud.pts[jatom].y,
203 yCloud.pts[jatom].z};
205 mi_dist2(&cell, p, q, &out);
208 if (yCloud.box.size() >= 6) {
210 yCloud, yCloud.pts[iatom].x, yCloud.pts[iatom].y, yCloud.pts[iatom].z,
211 yCloud.pts[jatom].x, yCloud.pts[jatom].y, yCloud.pts[jatom].z);
212 return dr[0] * dr[0] + dr[1] * dr[1] + dr[2] * dr[2];
215 std::array<double, 3> dr;
219 dr[0] = std::fabs(yCloud.pts[iatom].x - yCloud.pts[jatom].x);
220 dr[1] = std::fabs(yCloud.pts[iatom].y - yCloud.pts[jatom].y);
221 dr[2] = std::fabs(yCloud.pts[iatom].z - yCloud.pts[jatom].z);
224 for (
int k = 0; k < 3; k++) {
225 dr[k] -= yCloud.box[k] * std::round(dr[k] / yCloud.box[k]);
244 int iatom,
int jatom) {
252 const int *jatom, std::size_t n,
double *distSq) {
253 for (std::size_t k = 0; k < n; k++) {
260 std::ostringstream oss;
261 if (box.size() >= 3) {
262 oss << box[0] <<
' ' << box[1] <<
' ' << box[2];
264 if (box.size() >= 6) {
265 oss <<
" xy " << box[3] <<
" xz " << box[4] <<
" yz " << box[5];
274 const bool tilt = yCloud.box.size() >= 6;
276 os <<
"ITEM: BOX BOUNDS xy xz yz pp pp pp\n";
278 os <<
"ITEM: BOX BOUNDS pp pp pp\n";
280 for (
int k = 0; k < 3; k++) {
281 const double lo = (
static_cast<std::size_t
>(k) < yCloud.boxLow.size())
284 const double len = (
static_cast<std::size_t
>(k) < yCloud.box.size())
287 os << lo <<
' ' << lo + len;
289 os <<
' ' << yCloud.box[
static_cast<std::size_t
>(k + 3)];
307 double xj,
double yj,
double zj) {
308#ifdef SEAMS_HAS_MINIMAGE
309 const mi_cell cell = pointCloudCell(yCloud);
310 const double p[3] = {xj, yj, zj};
311 const double q[3] = {yCloud.pts[iatom].x, yCloud.pts[iatom].y,
312 yCloud.pts[iatom].z};
313 double dr[3] = {0.0, 0.0, 0.0};
314 mi_displacement(&cell, p, q, dr);
315 return {dr[0], dr[1], dr[2]};
317 if (yCloud.box.size() >= 6) {
319 yCloud.pts[iatom].z, xj, yj, zj);
322 std::array<double, 3> dr = {yCloud.pts[iatom].x - xj, yCloud.pts[iatom].y - yj,
323 yCloud.pts[iatom].z - zj};
324 for (
int k = 0; k < 3; k++) {
325 if (dr[k] < -yCloud.box[k] * 0.5) {
326 dr[k] += yCloud.box[k];
328 if (dr[k] >= yCloud.box[k] * 0.5) {
329 dr[k] -= yCloud.box[k];
338 const std::vector<double> &singlePoint) {
342 return std::sqrt(dr[0] * dr[0] + dr[1] * dr[1] + dr[2] * dr[2]);
358 std::array<double, 3> dr;
362 dr[0] = fabs(yCloud.pts[iatom].x - yCloud.pts[jatom].x);
363 dr[1] = fabs(yCloud.pts[iatom].y - yCloud.pts[jatom].y);
364 dr[2] = fabs(yCloud.pts[iatom].z - yCloud.pts[jatom].z);
367 for (
int k = 0; k < 3; k++) {
368 r2 += pow(dr[k], 2.0);
385inline std::array<double, 3>
389 yCloud.pts[jatom].y, yCloud.pts[jatom].z);
408 std::string outFile);
413 int jatomIndex,
double *x_i,
double *y_i,
double *z_i,
double *x_j,
414 double *y_j,
double *z_j);
419 std::vector<double> quat2);
426inline std::vector<std::string>
tokenizer(std::string line) {
427 std::istringstream iss(line);
428 std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
429 std::istream_iterator<std::string>{}};
438 std::istringstream iss(line);
439 std::vector<double> tokens;
441 while (iss >> number) {
442 tokens.push_back(number);
452 std::istringstream iss(line);
453 std::vector<int> tokens;
455 while (iss >> number) {
456 tokens.push_back(number);
466 return std::filesystem::exists(name);
477inline std::vector<std::complex<double>>
478avgVector(std::vector<std::complex<double>> v,
int l,
int neigh) {
482 for (
int m = 0; m < 2 * l + 1; m++) {
483 v[m] = (1.0 /
static_cast<double>(neigh)) * v[m];
double distance(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, int jatom)
Inline generic function for obtaining the wrapped distance between two particles WITHOUT applying PBC...
std::vector< std::complex< double > > avgVector(std::vector< std::complex< double > > v, int l, int neigh)
Calculates the complex vector, normalized by the number of nearest neighbours, of length .
void writeDumpBoxBounds(std::ostream &os, const molSys::PointCloud< molSys::Point< double >, double > &yCloud)
std::array< double, 3 > relDist(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, int jatom)
Inline generic function for getting the relative unwrapped distance between two particles for each di...
double periodicDist(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, int jatom)
Inline generic function for obtaining the unwrapped periodic distance between two particles,...
double eigenVecAngle(std::vector< double > OO, std::vector< double > OH)
Eigen function for getting the angle (in radians) between the O–O and O-H vectors.
double calcMedian(std::vector< double > *input)
Inline generic function for calculating the median given a vector of the values.
std::array< double, 3 > triclinicMinImage(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, double xi, double yi, double zi, double xj, double yj, double zj)
std::string formatDumpBox(const std::vector< double > &box)
std::vector< double > tokenizerDouble(std::string line)
Function for tokenizing line strings into a vector of doubles.
constexpr double pi
Uses Boost to get the value of pi.
bool file_exists(const std::string &name)
Function for checking if a file exists or not.
std::vector< std::string > tokenizer(std::string line)
Function for tokenizing line strings into words (strings) delimited by whitespace.
int prettyPrintYoda(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, std::string outFile)
Generic function for printing all the struct information.
double angDistDegQuaternions(std::vector< double > quat1, std::vector< double > quat2)
std::array< double, 3 > relDistFromPoint(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, double xj, double yj, double zj)
Inline generic function for obtaining the unwrapped periodic distance between one particle and anothe...
void batchPeriodicDistSq(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, const int *jatom, std::size_t n, double *distSq)
int unwrappedCoordShift(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatomIndex, int jatomIndex, double *x_i, double *y_i, double *z_i, double *x_j, double *y_j, double *z_j)
Shift particles (unwrapped coordinates).
std::vector< int > tokenizerInt(std::string line)
Function for tokenizing line strings into a vector of ints.
double radDeg(double angle)
Inline function for converting radians->degrees.
bool compareByAtomID(const molSys::Point< double > &a, const molSys::Point< double > &b)
Inline generic function for sorting or comparing two particles, according to the atom ID when the ent...
double getAverageWithoutOutliers(std::vector< double > inpVec)
Get the average, after excluding the outliers, using quartiles.
double unWrappedDistFromPoint(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, const std::vector< double > &singlePoint)
double periodicDistSq(const molSys::PointCloud< molSys::Point< double >, double > &yCloud, int iatom, int jatom)
Inline generic function for obtaining the unwrapped periodic distance between two particles,...
The main molecular system handler.
Small generic functions that are shared by all namespaces.
This contains a collection of points; contains information for a particular frame.
This contains per-particle information.