eOn 3.2.0
Long-timescale dynamics: aKMC, NEB, parallel replica
☾
Toggle main menu visibility
Loading...
Searching...
No Matches
EpiCenters.cpp
Go to the documentation of this file.
1
/*
2
** This file is part of eOn.
3
**
4
** SPDX-License-Identifier: BSD-3-Clause
5
**
6
** Copyright (c) 2010--present, eOn Development Team
7
** All rights reserved.
8
**
9
** Repo:
10
** https://github.com/TheochemUI/eOn
11
*/
12
#include "
eon/EpiCenters.h
"
13
#include "
eon/HelperFunctions.h
"
14
15
#include <climits>
16
#include <memory>
17
#include <stdexcept>
18
#include <vector>
19
20
namespace
eonc
{
21
22
namespace
{
23
long
pickFromHits(
const
std::vector<long> &hits,
const
char
*what) {
24
if
(hits.empty()) {
25
throw
std::runtime_error(what);
26
}
27
const
long
pick =
static_cast<
long
>
(
28
eonc::rng::randomDouble
(
static_cast<
long
>
(hits.size())));
29
return
hits[
static_cast<
size_t
>
(pick)];
30
}
31
}
// namespace
32
33
long
eonc::EpiCenters::cnaEpiCenter
(
const
Matter
*matter,
34
double
neighborCutoff) {
35
if
(!matter) {
36
throw
std::invalid_argument(
"EpiCenters: null Matter"
);
37
}
38
const
long
nAtoms = matter->
numberOfAtoms
();
39
std::vector<long> cnaList(
static_cast<
size_t
>
(nAtoms));
40
cna
(cnaList.data(), matter, neighborCutoff);
41
42
std::vector<long> hits;
43
hits.reserve(
static_cast<
size_t
>
(nAtoms));
44
for
(
long
i = 0; i < nAtoms; ++i) {
45
if
(cnaList[
static_cast<
size_t
>
(i)] == 2 && !matter->
getFixed
(i)) {
46
hits.push_back(i);
47
}
48
}
49
return
pickFromHits(hits,
"EpiCenters: no free non-FCC/HCP atom"
);
50
}
51
52
long
eonc::EpiCenters::minCoordinatedEpiCenter
(
const
Matter
*matter,
53
double
neighborCutoff) {
54
if
(!matter) {
55
throw
std::invalid_argument(
"EpiCenters: null Matter"
);
56
}
57
const
long
nAtoms = matter->
numberOfAtoms
();
58
auto
minCoordinatedList =
59
std::make_unique<bool[]>(
static_cast<
size_t
>
(nAtoms));
60
const
long
minCoordinationVal =
minCoordination
(matter, neighborCutoff);
61
coordinationLessOrEqual
(minCoordinatedList.get(), minCoordinationVal, matter,
62
neighborCutoff);
63
64
std::vector<long> hits;
65
hits.reserve(
static_cast<
size_t
>
(nAtoms));
66
for
(
long
i = 0; i < nAtoms; ++i) {
67
if
(minCoordinatedList[
static_cast<
size_t
>
(i)] && !matter->
getFixed
(i)) {
68
hits.push_back(i);
69
}
70
}
71
return
pickFromHits(hits,
"EpiCenters: no free minimally coordinated atom"
);
72
}
73
74
long
eonc::EpiCenters::lastAtom
(
const
Matter
*matter) {
75
if
(!matter) {
76
throw
std::invalid_argument(
"EpiCenters: null Matter"
);
77
}
78
const
long
nAtoms = matter->
numberOfAtoms
();
79
if
(nAtoms <= 0) {
80
throw
std::runtime_error(
"EpiCenters: lastAtom on empty Matter"
);
81
}
82
return
nAtoms - 1;
83
}
84
85
long
eonc::EpiCenters::randomFreeAtomEpiCenter
(
const
Matter
*matter) {
86
if
(!matter) {
87
throw
std::invalid_argument(
"EpiCenters: null Matter"
);
88
}
89
const
long
nAtoms = matter->
numberOfAtoms
();
90
std::vector<long> hits;
91
hits.reserve(
static_cast<
size_t
>
(nAtoms));
92
for
(
long
i = 0; i < nAtoms; ++i) {
93
if
(!matter->
getFixed
(i)) {
94
hits.push_back(i);
95
}
96
}
97
return
pickFromHits(hits,
"EpiCenters: no free atom"
);
98
}
99
100
void
eonc::EpiCenters::cna
(
long
*
cna
,
const
Matter
*matter,
101
double
neighborCutoff) {
102
long
nAtoms = matter->
numberOfAtoms
();
103
std::vector<int> nFCC(nAtoms, 0);
104
std::vector<int> nHCP(nAtoms, 0);
105
std::vector<std::vector<int>> neighborLists(nAtoms);
106
107
for
(
long
i = 0; i < nAtoms - 1; i++) {
108
for
(
long
j = i + 1; j < nAtoms; j++) {
109
double
diffR = matter->
distance
(i, j);
110
if
(diffR < neighborCutoff) {
111
neighborLists[i].push_back(
static_cast<
int
>
(j));
112
neighborLists[j].push_back(
static_cast<
int
>
(i));
113
}
114
}
115
}
116
117
for
(
long
a2 = 0; a2 < nAtoms; a2++) {
118
const
auto
&nbs2 = neighborLists[a2];
119
for
(
size_t
n2 = 0; n2 < nbs2.size(); n2++) {
120
int
a1 = nbs2[n2];
121
if
(a1 < a2) {
122
std::vector<int> common;
123
const
auto
&nbs1 = neighborLists[a1];
124
for
(
size_t
n1 = 0; n1 < nbs1.size(); n1++) {
125
int
a3 = nbs1[n1];
126
for
(
size_t
m2 = 0; m2 < nbs2.size(); m2++) {
127
if
(a3 == nbs2[m2])
128
common.push_back(a3);
129
}
130
}
131
if
(common.size() == 4) {
132
int
nBonds = 0;
133
int
bondsSum = 0;
134
for
(
int
j2 = 1; j2 < 4; j2++) {
135
const
auto
&nbs = neighborLists[common[j2]];
136
for
(
int
j1 = 0; j1 < j2; j1++) {
137
for
(
size_t
n = 0; n < nbs.size(); n++) {
138
if
(common[j1] == nbs[n]) {
139
nBonds++;
140
bondsSum += j1 + j2;
141
break
;
142
}
143
}
144
}
145
}
146
if
(nBonds == 2) {
147
if
(bondsSum == 6) {
148
nFCC[a1]++;
149
nFCC[a2]++;
150
}
else
{
151
nHCP[a1]++;
152
nHCP[a2]++;
153
}
154
}
155
}
156
}
157
}
158
}
159
// 0: fcc (421), 1: hcp (422), 2: other
160
for
(
long
i = 0; i < nAtoms; i++) {
161
if
(neighborLists[i].size() == 12) {
162
if
(nFCC[i] == 12)
163
cna
[i] = 0;
164
else
if
(nFCC[i] == 6 && nHCP[i] == 6)
165
cna
[i] = 1;
166
else
167
cna
[i] = 2;
168
}
else
{
169
cna
[i] = 2;
170
}
171
}
172
}
173
174
void
eonc::EpiCenters::coordination
(
long
*coordinationVal,
const
Matter
*matter,
175
double
neighborCutoff) {
176
long
nAtoms = matter->
numberOfAtoms
();
177
for
(
long
i = 0; i < nAtoms; i++)
178
coordinationVal[i] = 0;
179
180
for
(
long
i = 0; i < nAtoms - 1; i++) {
181
for
(
long
j = i + 1; j < nAtoms; j++) {
182
double
diffR = matter->
distance
(i, j);
183
if
(diffR < neighborCutoff) {
184
coordinationVal[i]++;
185
coordinationVal[j]++;
186
}
187
}
188
}
189
}
190
191
void
eonc::EpiCenters::coordinationLessOrEqual
(
bool
*result,
192
long
coordinationMaxVal,
193
const
Matter
*matter,
194
double
neighborCutoff) {
195
long
nAtoms = matter->
numberOfAtoms
();
196
std::vector<long> coordinationVal(nAtoms);
197
198
coordination
(coordinationVal.data(), matter, neighborCutoff);
199
200
for
(
long
i = 0; i < nAtoms; i++) {
201
result[i] =
202
(coordinationVal[i] <= coordinationMaxVal) && !matter->
getFixed
(i);
203
}
204
}
205
206
long
eonc::EpiCenters::listedAtomEpiCenter
(
const
Matter
*matter,
207
const
std::vector<long> &atomList) {
208
if
(!matter) {
209
throw
std::invalid_argument(
"EpiCenters: null Matter"
);
210
}
211
long
nAtoms = matter->
numberOfAtoms
();
212
std::vector<long> freeAtoms;
213
// Lone -1 is every free atom (akmc-al / ListedAtoms). A mixed list
214
// still treats negatives as out of range.
215
if
(atomList.size() == 1 && atomList[0] == -1) {
216
for
(
long
i = 0; i < nAtoms; ++i) {
217
if
(!matter->
getFixed
(i)) {
218
freeAtoms.push_back(i);
219
}
220
}
221
}
else
{
222
for
(
long
idx : atomList) {
223
if
(idx < 0 || idx >= nAtoms) {
224
continue
;
225
}
226
const
long
row = matter->
mapFileRow
(idx);
227
if
(row >= 0 && row < nAtoms && !matter->getFixed(row)) {
228
freeAtoms.push_back(row);
229
}
230
}
231
}
232
if
(freeAtoms.empty()) {
233
throw
std::runtime_error(
"Listed atoms are all frozen"
);
234
}
235
// eonc::rng::randomDouble(N) is [0, N); size-1 dropped the last listed / last
236
// free atom.
237
long
pick =
static_cast<
long
>
(
238
eonc::rng::randomDouble
(
static_cast<
long
>
(freeAtoms.size())));
239
return
freeAtoms[pick];
240
}
241
242
long
eonc::EpiCenters::minCoordination
(
const
Matter
*matter,
243
double
neighborCutoff) {
244
if
(!matter) {
245
throw
std::invalid_argument(
"EpiCenters: null Matter"
);
246
}
247
long
nAtoms = matter->
numberOfAtoms
();
248
std::vector<long> coordinationVal(nAtoms);
249
250
coordination
(coordinationVal.data(), matter, neighborCutoff);
251
252
long
minVal = LONG_MAX;
253
for
(
long
i = 0; i < nAtoms; i++) {
254
if
(coordinationVal[i] < minVal && !matter->
getFixed
(i)) {
255
minVal = coordinationVal[i];
256
}
257
}
258
return
minVal;
259
}
260
261
}
// namespace eonc
EpiCenters.h
HelperFunctions.h
eonc::Matter
Definition
Matter.h:90
eonc::Matter::numberOfAtoms
long int numberOfAtoms() const
Definition
Matter.cpp:273
eonc::Matter::distance
double distance(long index1, long index2) const
Definition
Matter.cpp:448
eonc::Matter::mapFileRow
long mapFileRow(long file_row) const
Map a CON file-order row onto the Matter row after matter_order.
Definition
Matter.h:293
eonc::Matter::getFixed
int getFixed(long int atom) const
1 if every Cartesian axis of the atom is fixed, else 0.
Definition
Matter.cpp:505
eonc::EpiCenters::lastAtom
long lastAtom(const Matter *matter)
Definition
EpiCenters.cpp:74
eonc::EpiCenters::minCoordination
long minCoordination(const Matter *matter, double neighborCutoff)
Definition
EpiCenters.cpp:242
eonc::EpiCenters::cna
void cna(long *cna, const Matter *matter, double neighborCutoff)
Definition
EpiCenters.cpp:100
eonc::EpiCenters::cnaEpiCenter
long cnaEpiCenter(const Matter *matter, double neighborCutoff)
Definition
EpiCenters.cpp:33
eonc::EpiCenters::randomFreeAtomEpiCenter
long randomFreeAtomEpiCenter(const Matter *matter)
Definition
EpiCenters.cpp:85
eonc::EpiCenters::coordinationLessOrEqual
void coordinationLessOrEqual(bool *result, long coordinationMaxVal, const Matter *matter, double neighborCutoff)
Definition
EpiCenters.cpp:191
eonc::EpiCenters::listedAtomEpiCenter
long listedAtomEpiCenter(const Matter *matter, const std::vector< long > &atomList)
Definition
EpiCenters.cpp:206
eonc::EpiCenters::minCoordinatedEpiCenter
long minCoordinatedEpiCenter(const Matter *matter, double neighborCutoff)
Definition
EpiCenters.cpp:52
eonc::EpiCenters::coordination
void coordination(long *coordinationVal, const Matter *matter, double neighborCutoff)
Definition
EpiCenters.cpp:174
eonc::rng::randomDouble
double randomDouble()
Definition
RandomNumbers.cpp:72
eonc
RAII resource manager for the ARTn C library with global synchronization.
Definition
ARTnSaddleSearch.cpp:23
client
EpiCenters.cpp
Generated by
1.17.0
Generated by
Doxygen 1.17.0
Analytics by
Antics
provided by
TurtleTech ehf