Loading...
Searching...
No Matches
Matter.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/Matter.h"
13#include "eon/BaseStructures.h"
14#include "eon/BondBoost.h"
16#include "eon/HelperFunctions.h"
18
19#include "eon/EonLogger.h"
20#include <memory>
21#include <stdexcept>
22
23Matter::Matter(const Matter &matter) { operator=(matter); }
24
25const Matter &Matter::operator=(const Matter &matter) {
26 if (this == &matter) {
27 return *this;
28 }
29 nAtoms = matter.nAtoms;
31
32 positions = matter.positions;
33 forces = matter.forces;
34 masses = matter.masses;
35 atomicNrs = matter.atomicNrs;
36 isFixed = matter.isFixed;
37 atomIndex = matter.atomIndex;
38 cell = matter.cell;
39 cellInverse = matter.cellInverse;
40 velocities = matter.velocities;
41
43 structComp = matter.structComp;
44 parameters = matter.parameters;
45
48
49 potential = matter.potential;
52 forceCalls = matter.forceCalls;
54 // Both caches describe the forces this object held before the assignment.
55 // resize() above already raises them; state it here alongside the members
56 // this function owns.
57 recomputeFreeMask = true;
59
60 // A BondBoost binds to one Matter (BondBoost.h:32 takes a Matter *), so a
61 // copy cannot share the source's: boosting through it would drive the
62 // original. The copy starts without one and re-establishes it through
63 // setBiasPotential. biasForces is zeroed by the resize above, which is the
64 // state that matches having no bias potential.
65 biasPotential = nullptr;
66
67 headerCon = matter.headerCon;
68 // ConFrame is move-only; copy does not retain movie trajectory.
69 movie_frames_.clear();
70
71 return *this;
72}
73
74Matter::Matter(Matter &&other) noexcept { operator=(std::move(other)); }
75
76Matter &Matter::operator=(Matter &&other) noexcept {
77 if (this == &other) {
78 return *this;
79 }
80 potential = std::move(other.potential);
81 usePeriodicBoundaries = other.usePeriodicBoundaries;
82 pbcConvention = other.pbcConvention;
83 recomputePotential = other.recomputePotential;
84 forceCalls = other.forceCalls;
85 headerCon = std::move(other.headerCon);
86 removeNetForce = other.removeNetForce;
87 structComp = other.structComp;
88 parameters = other.parameters;
89 nAtoms = other.nAtoms;
90 positions = std::move(other.positions);
91 velocities = std::move(other.velocities);
92 forces = std::move(other.forces);
93 biasForces = std::move(other.biasForces);
94 biasPotential = other.biasPotential;
95 other.biasPotential = nullptr;
96 masses = std::move(other.masses);
97 atomicNrs = std::move(other.atomicNrs);
98 isFixed = std::move(other.isFixed);
99 atomIndex = std::move(other.atomIndex);
100 freeMask = std::move(other.freeMask);
101 maskedForces = std::move(other.maskedForces);
102 freeIndices = std::move(other.freeIndices);
103 recomputeFreeMask = other.recomputeFreeMask;
104 recomputeMaskedForces = other.recomputeMaskedForces;
105 cell = std::move(other.cell);
106 cellInverse = std::move(other.cellInverse);
107 energyVariance = other.energyVariance;
108 movie_frames_ = std::move(other.movie_frames_);
109 potentialEnergy = other.potentialEnergy;
110
111 other.nAtoms = 0;
112 other.recomputePotential = true;
113 other.recomputeFreeMask = true;
114 other.recomputeMaskedForces = true;
115 return *this;
116}
117
118// The == comparison considers identity. This is crucial for process search.
119// bool Matter::operator==(const Matter& matter) {
120// if(structComp.check_rotation) {
121// return eonc::helpers::rotationMatch(this, &matter,
122// structComp.distance_difference);
123// }else{
124// return (structComp.distance_difference)
125// > perAtomNorm(matter);
126// }
127// }
128
129bool Matter::compare(const Matter &matter, bool indistinguishable) {
130 if (nAtoms != matter.numberOfAtoms())
131 return false;
132 if (structComp.check_rotation && indistinguishable) {
133 return eonc::helpers::sortedR(*this, matter,
134 structComp.distance_difference);
135 } else if (indistinguishable) {
136 if (this->numberOfFixedAtoms() == 0 and structComp.remove_translation)
138 return eonc::helpers::identical(*this, matter,
139 structComp.distance_difference);
140 } else if (structComp.check_rotation) {
141 return eonc::helpers::rotationMatch(*this, matter,
142 structComp.distance_difference);
143 } else {
144 if (this->numberOfFixedAtoms() == 0 and structComp.remove_translation)
146 return (structComp.distance_difference) > perAtomNorm(matter);
147 }
148}
149
150// bool Matter::operator!=(const Matter& matter) {
151// return !operator==(matter);
152// }
153
154// Returns the distance to the given matter object.
155double Matter::distanceTo(const Matter &matter) {
156 return pbc(positions - matter.positions).norm();
157}
158
159// Returns the maximum distance between two atoms in the Matter objects.
160double Matter::perAtomNorm(const Matter &matter) {
161 long i = 0;
162 double max_distance = 0.0;
163
164 if (matter.numberOfAtoms() == nAtoms) {
165 AtomMatrix diff = pbc(positions - matter.positions);
166 for (i = 0; i < nAtoms; i++) {
167 max_distance = std::max(diff.row(i).norm(), max_distance);
168 }
169 }
170 return max_distance;
171}
172
173void Matter::resize(const long int length) {
174 if (length < 0) {
175 throw std::invalid_argument("Matter::resize: negative atom count");
176 }
177 // Zero is a real size: leaving nAtoms at the old value there sends
178 // setMasses and every other nAtoms loop off the end of an empty array.
179 nAtoms = length;
180 positions.resize(length, 3);
181 positions.setZero();
182
183 velocities.resize(length, 3);
184 velocities.setZero();
185
186 biasForces.resize(length, 3);
187 biasForces.setZero();
188
189 forces.resize(length, 3);
190 forces.setZero();
191
192 masses.resize(length);
193 masses.setZero();
194
195 atomicNrs.resize(length);
196 atomicNrs.setZero();
197
198 isFixed.resize(length, 3);
199 isFixed.setZero();
200
201 atomIndex.resize(length);
202 for (long i = 0; i < length; i++)
203 atomIndex(i) = static_cast<std::int64_t>(i); // default: sequential
204 recomputePotential = true;
206 recomputeFreeMask = true;
207}
208
209long int Matter::numberOfAtoms() const { return (nAtoms); }
210
211Matrix3d Matter::getCell() const { return cell; }
212
213void Matter::setCell(const Matrix3d &newCell) {
214 cell = newCell;
215 cellInverse = cell.inverse();
216}
217
218double Matter::getPosition(long int indexAtom, int axis) const {
219 return positions(indexAtom, axis);
220}
221
222void Matter::setPosition(long int indexAtom, int axis, double position) {
223 positions(indexAtom, axis) = position;
226 }
227 recomputePotential = true;
229}
230
231void Matter::setVelocity(long int indexAtom, int axis, double vel) {
232 velocities(indexAtom, axis) = vel;
233}
234
235// return coordinates of atoms by const reference (zero-copy)
236const AtomMatrix &Matter::getPositions() const { return positions; }
237// return a modifiable copy of positions
239
240VectorXd Matter::getPositionsV() const {
241 return VectorXd::Map(positions.data(), 3 * numberOfAtoms());
242}
243
245 getFree(); // ensure freeIndices is up to date
246 AtomMatrix ret(static_cast<long>(freeIndices.size()), 3);
247 for (size_t j = 0; j < freeIndices.size(); j++) {
248 ret.row(static_cast<long>(j)) = positions.row(freeIndices[j]);
249 }
250 return ret;
251}
252
253VectorXi Matter::getAtomicNrsFree() const {
254 return this->atomicNrs.array() * getFreeV().cast<int>().array();
255}
256
257bool Matter::relax(bool quiet, bool writeMovie, bool checkpoint,
258 std::string prefixMovie, std::string prefixCheckpoint,
259 bool retainMovieFrames) {
260 if (retainMovieFrames) {
261 movie_frames_.clear();
262 }
264 *this, *parameters, quiet, writeMovie, checkpoint, prefixMovie,
265 prefixCheckpoint, retainMovieFrames ? &movie_frames_ : nullptr);
266}
267
269 return VectorXd::Map(getPositionsFree().data(), 3 * numberOfFreeAtoms());
270}
271
272// update Matter with the new positions of the free atoms given in array 'pos'
274 positions = pos;
277 }
278 recomputePotential = true;
280}
281
282// Same but takes vector instead of n x 3 matrix
283void Matter::setPositionsV(const VectorXd &pos) {
284 setPositions(AtomMatrix::Map(pos.data(), numberOfAtoms(), 3));
285}
286
288 getFree(); // ensure freeIndices is up to date
289 for (size_t j = 0; j < freeIndices.size(); j++) {
290 positions.row(freeIndices[j]) = pos.row(static_cast<long>(j));
291 }
292 // Optimizers write free-atom coords only (TIP4P/SPCE and any PBC pot).
293 // Match setPositions: wrap the full configuration when PBC is on (#171).
296 }
297 recomputePotential = true;
299}
300
301void Matter::setPositionsFreeV(const VectorXd &pos) {
302 setPositionsFree(AtomMatrix::Map(pos.data(), numberOfFreeAtoms(), 3));
303}
304
306 if (biasPotential != nullptr) {
307 // Evaluate the current bias only. The MD job advances the bond-boost
308 // schedule once per step via BondBoost::advance().
309 biasPotential->boost();
310 }
311 return biasForces.array() * getFree().array();
312}
313
315 biasPotential = bondBoost;
316}
317
319 biasForces = bf.array() * getFree().array();
320}
321// Return forces with fixed atoms zeroed (cached).
322// Note: not thread-safe. Concurrent reads on the same Matter instance
323// may race on the mutable maskedForces/recomputeMaskedForces members.
327 // Use the cached freeMask (Nx3, 1.0 for free / 0.0 for fixed) to zero
328 // fixed-atom forces in a single vectorized Eigen operation.
329 maskedForces = forces.array() * getFree().array();
330 recomputeMaskedForces = false;
331 }
332 return maskedForces;
333}
334
337 return forces;
338}
339
340VectorXd Matter::getForcesV() const {
341 return VectorXd::Map(getForces().data(), 3 * numberOfAtoms());
342}
343
345 AtomMatrix allForces = getForces();
346 getFree(); // ensure freeIndices is up to date (mutable cache)
347 AtomMatrix ret(static_cast<long>(freeIndices.size()), 3);
348 for (size_t j = 0; j < freeIndices.size(); j++) {
349 ret.row(static_cast<long>(j)) = allForces.row(freeIndices[j]);
350 }
351 return ret;
352}
353
354VectorXd Matter::getForcesFreeV() const {
355 AtomMatrix freeForces = getForcesFree();
356 return VectorXd::Map(freeForces.data(), 3 * numberOfFreeAtoms());
357}
358
359// return distance between the atoms with index1 and index2
360double Matter::distance(long index1, long index2) const {
361 return pbc(positions.row(index1) - positions.row(index2)).norm();
362}
363
364// return projected distance between the atoms with index1 and index2 on asix
365// (0-x,1-y,2-z)
366double Matter::pdistance(long index1, long index2, int axis) const {
367 Matrix<double, 1, 3> ret;
368 ret.setZero();
369 ret(0, axis) = positions(index1, axis) - positions(index2, axis);
370 ret = pbc(ret);
371 return ret(0, axis);
372}
373
374// return the distance atom with index has moved between the current Matter
375// object and the Matter object passed as argument
376double Matter::distance(const Matter &matter, long index) const {
377 return pbc(positions.row(index) - matter.getPositions().row(index)).norm();
378}
379
380double Matter::getMass(long int indexAtom) const { return (masses[indexAtom]); }
381
382void Matter::setMass(long int indexAtom, double mass) {
383 masses[indexAtom] = mass;
384}
385
386void Matter::setMasses(const VectorXd &massesIn) {
387 for (int i = 0; i < nAtoms; i++) {
388 masses[i] = massesIn[i];
389 }
390}
391
392long Matter::getAtomicNr(long int indexAtom) const {
393 return (atomicNrs[indexAtom]);
394}
395
396void Matter::setAtomicNr(long int indexAtom, long atomicNr) {
397 atomicNrs[indexAtom] = atomicNr;
398 recomputePotential = true;
400}
401
402int Matter::getFixed(long int indexAtom) const {
403 return (isFixed(indexAtom, 0) > 0.5 && isFixed(indexAtom, 1) > 0.5 &&
404 isFixed(indexAtom, 2) > 0.5)
405 ? 1
406 : 0;
407}
408
409int Matter::getFixed(long int indexAtom, int axis) const {
410 return isFixed(indexAtom, axis) > 0.5 ? 1 : 0;
411}
412
413std::array<bool, 3> Matter::getFixedMask(long int indexAtom) const {
414 return {isFixed(indexAtom, 0) > 0.5, isFixed(indexAtom, 1) > 0.5,
415 isFixed(indexAtom, 2) > 0.5};
416}
417
418void Matter::setFixed(long int indexAtom, int isFixed_passed) {
419 const double v = isFixed_passed ? 1.0 : 0.0;
420 isFixed(indexAtom, 0) = v;
421 isFixed(indexAtom, 1) = v;
422 isFixed(indexAtom, 2) = v;
423 recomputeFreeMask = true;
425}
426
427void Matter::setFixed(long int indexAtom, int axis, int isFixed_passed) {
428 isFixed(indexAtom, axis) = isFixed_passed ? 1.0 : 0.0;
429 recomputeFreeMask = true;
431}
432
433void Matter::setFixedMask(long int indexAtom, std::array<bool, 3> mask) {
434 isFixed(indexAtom, 0) = mask[0] ? 1.0 : 0.0;
435 isFixed(indexAtom, 1) = mask[1] ? 1.0 : 0.0;
436 isFixed(indexAtom, 2) = mask[2] ? 1.0 : 0.0;
437 recomputeFreeMask = true;
439}
440
441// void Matter::setPotentialEnergy(double epot_input)
442//{
443// potentialEnergy=epot_input;
444// }
445
447 if (nAtoms > 0) {
449 return potentialEnergy;
450 } else
451 return 0.0;
452}
453
455 // 0.5 * sum(mass_i * |v_i,free|^2); a constrained axis does not contribute.
456 AtomMatrix vfree = velocities.array() * getFree().array();
457 Eigen::VectorXd speed2 = vfree.rowwise().squaredNorm();
458 return 0.5 * (masses.array() * speed2.array()).sum();
459}
460
464
466 long n = 0;
467 for (long i = 0; i < nAtoms; ++i) {
468 if (getFixed(i)) {
469 ++n;
470 }
471 }
472 return n;
473}
474
476 return nAtoms - numberOfFixedAtoms();
477}
478
479long Matter::getForceCalls() const { return (forceCalls); }
480
482 forceCalls = 0;
483 return;
484}
485
487 if (!potential || !potential->requiresIsolatedMoleculeLayout()) {
488 return;
489 }
491 throw std::runtime_error(
492 "Potential requires an isolated (non-periodic) molecular layout "
493 "(NWChem/ORCA-class). Disable periodic boundaries before optimizing; "
494 "PBC wraps can tear non-centered molecules (issue #188).");
495 }
496}
497
499 if (recomputePotential) {
500 if (!potential) {
501 throw std::runtime_error(
502 "Matter::computePotential called without a potential");
503 }
505 if (potential->isSurrogate()) {
506 // Surrogate potential case: uses free-atom subset interface
507 auto surrogatePotential =
508 static_cast<SurrogatePotential *>(potential.get());
509 auto [freePE, freeForces, vari] = surrogatePotential->get_ef_var(
510 this->getPositionsFree(), this->getAtomicNrsFree(), cell);
511 this->potentialEnergy = freePE;
512 this->energyVariance = vari;
513 for (long idx{0}, jdx{0}; idx < nAtoms; idx++) {
514 if (!getFixed(idx)) {
515 forces.row(idx) = freeForces.row(jdx);
516 jdx++;
517 }
518 }
519 } else {
520 // Hot path: call force() directly into member storage.
521 // No intermediate allocation, no tuple, no copy.
522 double var{0};
523 potential->force(nAtoms, positions.data(), atomicNrs.data(),
524 forces.data(), &potentialEnergy, &var, cell.data());
525 potential->forceCallCounter++;
527 }
529 recomputePotential = false;
530
531 if (isFixed.maxCoeff() < 0.5 && removeNetForce) {
532 Vector3d tempForce = forces.colwise().sum() / nAtoms;
533 for (long int i = 0; i < nAtoms; i++) {
534 forces.row(i) -= tempForce.transpose();
535 }
536 }
537 }
538}
539
540// Transform coordinates into the cell using the selected PBC convention (#176).
541// Legacy: fractional [0,1) via fmod (historical). MinimumImage: fractional
542// [-0.5,0.5) via floor (same MIC as eonc::pbc::apply for differences).
545 // Unset / singular cell (default after Matter construct is Zero) — do not
546 // wipe coordinates; callers set the cell before wrapping makes sense.
547 if (std::abs(cell.determinant()) < 1e-30) {
548 return;
549 }
550 positions =
552}
553
554double Matter::maxForce() const {
555 // Ensures that the forces are up to date
557
558 const AtomMatrix &f = getForces();
559 double maxForce = 0.0;
560 for (int i = 0; i < nAtoms; i++) {
561 if (getFixed(i)) {
562 continue;
563 }
564 maxForce = std::max(f.row(i).norm(), maxForce);
565 }
566 return maxForce;
567}
568
569VectorXi Matter::getAtomicNrs() const { return this->atomicNrs; }
570
571void Matter::setAtomicNrs(const VectorXi &atmnrs) {
572 if (atmnrs.size() != this->nAtoms) {
573 throw std::invalid_argument(
574 "Vector of atomic numbers not equal to the number of atoms");
575 } else {
576 this->atomicNrs = atmnrs;
577 }
578}
579
581 if (recomputeFreeMask) {
582 freeMask.resize(nAtoms, 3);
583 freeMask = 1.0 - isFixed.array();
584 freeIndices.clear();
585 freeIndices.reserve(static_cast<size_t>(nAtoms));
586 for (long i = 0; i < nAtoms; i++) {
587 if (freeMask.row(i).sum() > 0.5) {
588 freeIndices.push_back(static_cast<int>(i));
589 }
590 }
591 recomputeFreeMask = false;
592 }
593 return freeMask;
594}
595
596VectorXd Matter::getFreeV() const {
597 return VectorXd::Map(getFree().data(), 3 * numberOfAtoms());
598}
599
601 return velocities.array() * getFree().array();
602}
603
605 velocities = v.array() * getFree().array();
606}
607
609 forces = f.array() * getFree().array();
610}
611
614 AtomMatrix ret = totF.array() * getFree().array();
615 // Single reciprocal mass computation, replicated across 3 columns
616 auto invMass = masses.array().inverse();
617 ret.col(0).array() *= invMass;
618 ret.col(1).array() *= invMass;
619 ret.col(2).array() *= invMass;
620 return ret;
621}
622
623Matrix<double, Eigen::Dynamic, 1> Matter::getMasses() const { return masses; }
624
625void Matter::setPotential(std::shared_ptr<Potential> pot) {
626 this->potential = pot;
627 // Molecular QM backends (NWChem/ORCA) must not use PBC wraps (#188). Auto-off
628 // with a hard fail if code later forces PBC while this pot is attached.
629 if (potential && potential->requiresIsolatedMoleculeLayout() &&
631 usePeriodicBoundaries = false;
632 // Use EONC_LOG_* (not bare QUILL_LOG_* with eonc::log::get() as arg): the
633 // quill macros expand logger->… and choke on a call expression as the first
634 // macro argument on some GCC versions (CI: expected primary-expression).
636 "Disabled PBC for isolated-molecule potential (NWChem/ORCA-class); "
637 "re-enabling PBC will throw (issue #188)");
638 }
639 recomputePotential = true;
641}
642
643void Matter::setComputedPotential(double energy, double variance) {
644 potentialEnergy = energy;
645 energyVariance = variance;
646 recomputePotential = false;
648 forceCalls++;
649
650 // Apply the same net force removal as computePotential()
651 if (isFixed.maxCoeff() < 0.5 && removeNetForce) {
652 Vector3d tempForce = forces.colwise().sum() / nAtoms;
653 for (long int i = 0; i < nAtoms; i++) {
654 forces.row(i) -= tempForce.transpose();
655 }
656 }
657}
658
660 return this->potential->forceCallCounter;
661}
662
663double Matter::getEnergyVariance() const { return this->energyVariance; }
664
665// Eigen::VectorXd Matter::getForceVariance() {
666// return this->variance.segment(1, numberOfFreeAtoms() * 3);
667// }
668
669// double Matter::getMaxVariance() { return this->variance.maxCoeff(); }
670
671std::shared_ptr<Potential> Matter::getPotential() { return this->potential; }
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Definition Eigen.h:35
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
#define EONC_LOG_WARNING(...)
Definition EonLogger.h:256
Matter(std::shared_ptr< Potential > pot, const Parameters &params)
Definition Matter.h:95
Functionality relying on the conjugate gradients algorithm.
Definition BondBoost.h:25
double potentialEnergy
Definition Matter.h:386
Parameters::structure_comparison_options_t structComp
Definition Matter.h:363
double getPotentialEnergy() const
Definition Matter.cpp:446
VectorXd getFreeV() const
Definition Matter.cpp:596
long int numberOfFixedAtoms() const
Definition Matter.cpp:465
void setComputedPotential(double energy, double variance)
Set energy/variance from external batched evaluation and mark forces as up-to-date (recomputePotentia...
Definition Matter.cpp:643
void setForces(const AtomMatrix &f)
Definition Matter.cpp:608
Eigen::Matrix< std::int64_t, Eigen::Dynamic, 1 > atomIndex
Definition Matter.h:376
void setPositionsFreeV(const VectorXd &pos)
Definition Matter.cpp:301
bool recomputeFreeMask
Definition Matter.h:380
PbcConvention pbcConvention
Definition Matter.h:347
void setAtomicNrs(const VectorXi &atmnrs)
Definition Matter.cpp:571
VectorXd getPositionsV() const
Definition Matter.cpp:240
VectorXd masses
Definition Matter.h:372
std::vector< readcon::ConFrame > movie_frames_
Definition Matter.h:385
long getForceCalls() const
Definition Matter.cpp:479
void setMasses(const VectorXd &massesIn)
Definition Matter.cpp:386
void setPosition(long int atom, int axis, double position)
Definition Matter.cpp:222
void computePotential() const
Definition Matter.cpp:498
std::vector< int > freeIndices
Definition Matter.h:379
double distance(long index1, long index2) const
Definition Matter.cpp:360
VectorXi atomicNrs
Definition Matter.h:373
AtomMatrix getFree() const
Definition Matter.cpp:580
void setBiasPotential(BondBoost *bondBoost)
Definition Matter.cpp:314
const AtomMatrix & getForces() const
Definition Matter.cpp:324
double maxForce(void) const
Definition Matter.cpp:554
AtomMatrix velocities
Definition Matter.h:368
bool recomputeMaskedForces
Definition Matter.h:381
void setVelocities(const AtomMatrix &v)
Definition Matter.cpp:604
VectorXi getAtomicNrs() const
Definition Matter.cpp:569
const Parameters * parameters
Definition Matter.h:365
bool removeNetForce
Definition Matter.h:362
long nAtoms
Definition Matter.h:366
void setBiasForces(const AtomMatrix &bf)
Definition Matter.cpp:318
AtomMatrix pbc(const AtomMatrix &diff) const
Definition Matter.h:163
VectorXd getForcesV() const
Definition Matter.cpp:340
std::shared_ptr< Potential > potential
Definition Matter.h:342
double getEnergyVariance() const
Definition Matter.cpp:663
AtomMatrix getPositionsCopy() const
Definition Matter.cpp:238
BondBoost * biasPotential
Definition Matter.h:371
long int numberOfAtoms() const
Definition Matter.cpp:209
Eigen::Matrix< double, Eigen::Dynamic, 1 > getMasses() const
Definition Matter.cpp:623
AtomMatrix getPositionsFree() const
Definition Matter.cpp:244
long forceCalls
Definition Matter.h:351
std::shared_ptr< Potential > getPotential()
Definition Matter.cpp:671
void setPositionsFree(const AtomMatrix &pos)
Definition Matter.cpp:287
double getPosition(long int atom, int axis) const
Definition Matter.cpp:218
AtomMatrix freeMask
Definition Matter.h:377
void resize(long int nAtoms)
Definition Matter.cpp:173
AtomMatrix forces
Definition Matter.h:369
void applyPeriodicBoundary()
Definition Matter.cpp:543
void resetForceCalls()
Definition Matter.cpp:481
const AtomMatrix & getForcesRaw() const
Definition Matter.cpp:335
void setMass(long int atom, double mass)
Definition Matter.cpp:382
bool recomputePotential
Definition Matter.h:348
void setPositionsV(const VectorXd &pos)
Definition Matter.cpp:283
void setCell(const Matrix3d &newCell)
Definition Matter.cpp:213
bool relax(bool quiet=false, bool writeMovie=false, bool checkpoint=false, std::string prefixMovie=std::string(), std::string prefixCheckpoint=std::string(), bool retainMovieFrames=false)
Definition Matter.cpp:257
std::array< std::string, 5 > headerCon
Definition Matter.h:354
void assertIsolatedMoleculeLayoutSafe() const
Throw if pot forbids PBC (isolated molecular QM backends, issue #188).
Definition Matter.cpp:486
bool usePeriodicBoundaries
Definition Matter.h:343
AtomMatrix isFixed
Definition Matter.h:374
std::array< bool, 3 > getFixedMask(long int atom) const
Per-axis CON column-4 mask (bit0=x, bit1=y, bit2=z).
Definition Matter.cpp:413
VectorXd getForcesFreeV() const
Definition Matter.cpp:354
Matrix3d cell
Definition Matter.h:382
Matter(std::shared_ptr< Potential > pot, const Parameters &params)
Definition Matter.h:95
VectorXd getPositionsFreeV() const
Definition Matter.cpp:268
Matrix3d cellInverse
Definition Matter.h:383
VectorXi getAtomicNrsFree() const
Definition Matter.cpp:253
double getMechanicalEnergy() const
Definition Matter.cpp:461
const Matter & operator=(const Matter &matter)
Definition Matter.cpp:25
long int numberOfFreeAtoms() const
Definition Matter.cpp:475
bool compare(const Matter &matter, bool indistinguishable=false)
Definition Matter.cpp:129
void setFixed(long int atom, int isFixed)
Broadcast a whole-atom flag onto all three axes.
Definition Matter.cpp:418
long getAtomicNr(long int atom) const
Definition Matter.cpp:392
void setFixedMask(long int atom, std::array< bool, 3 > mask)
Definition Matter.cpp:433
Matrix3d getCell() const
Definition Matter.cpp:211
AtomMatrix getVelocities() const
Definition Matter.cpp:600
double energyVariance
Definition Matter.h:384
double perAtomNorm(const Matter &matter)
Definition Matter.cpp:160
AtomMatrix getForcesFree() const
Definition Matter.cpp:344
void setPositions(const AtomMatrix &pos)
Definition Matter.cpp:273
double getKineticEnergy() const
Definition Matter.cpp:454
AtomMatrix maskedForces
Definition Matter.h:378
double getMass(long int atom) const
Definition Matter.cpp:380
double distanceTo(const Matter &matter)
Definition Matter.cpp:155
size_t getPotentialCalls() const
Definition Matter.cpp:659
void setVelocity(long int atom, int axis, double velocity)
Definition Matter.cpp:231
AtomMatrix biasForces
Definition Matter.h:370
const AtomMatrix & getPositions() const
Definition Matter.cpp:236
AtomMatrix getAccelerations()
Definition Matter.cpp:612
AtomMatrix getBiasForces()
Definition Matter.cpp:305
double pdistance(long index1, long index2, int axis) const
Definition Matter.cpp:366
AtomMatrix positions
Definition Matter.h:367
void setAtomicNr(long int atom, long atomicNr)
Definition Matter.cpp:396
void setPotential(std::shared_ptr< Potential > pot)
Definition Matter.cpp:625
int getFixed(long int atom) const
1 if every Cartesian axis of the atom is fixed, else 0.
Definition Matter.cpp:402
static PotRegistry & get() noexcept
Process-lifetime singleton.
void on_force_call(PotType t) noexcept
std::tuple< double, AtomMatrix, double > get_ef_var(const AtomMatrix pos, const VectorXi atmnrs, const Matrix3d box)
bool relaxMatter(Matter &matter, const Parameters &params, bool quiet=false, bool writeMovie=false, bool checkpoint=false, std::string prefixMovie=std::string(), std::string prefixCheckpoint=std::string(), std::vector< readcon::ConFrame > *outFrames=nullptr)
bool rotationMatch(const Matter &m1, const Matter &m2, const double max_diff)
bool identical(const Matter &m1, const Matter &m2, const double distanceDifference)
bool sortedR(const Matter &m1, const Matter &m2, const double distanceDifference)
void translationRemove(Matter &m1, const AtomMatrix r1)
AtomMatrix applyPositions(const AtomMatrix &coords, const Matrix3d &cell, const Matrix3d &cellInverse, PbcConvention convention)
Definition Matter.h:66