45#include "applications/staticProps/TetrahedralityParamXYZ.hpp"
53#include "utils/Constants.hpp"
54#include "utils/simError.h"
58 TetrahedralityParamXYZ::TetrahedralityParamXYZ(
59 SimInfo* info,
const std::string& filename,
const std::string& sele1,
60 const std::string& sele2, RealType rCut, RealType voxelSize,
61 RealType gaussWidth) :
62 StaticAnalyser(info, filename, 1),
63 selectionScript1_(sele1), selectionScript2_(sele2), seleMan1_(info),
64 seleMan2_(info), evaluator1_(info), evaluator2_(info), rCut_(rCut),
65 voxelSize_(voxelSize), gaussWidth_(gaussWidth) {
66 evaluator1_.loadScriptString(sele1);
67 if (!evaluator1_.isDynamic()) {
68 seleMan1_.setSelectionSet(evaluator1_.evaluate());
70 evaluator2_.loadScriptString(sele2);
71 if (!evaluator2_.isDynamic()) {
72 seleMan2_.setSelectionSet(evaluator2_.evaluate());
75 Mat3x3d hmat = info->getSnapshotManager()->getCurrentSnapshot()->getHmat();
77 nBins_(0) = int(hmat(0, 0) / voxelSize);
78 nBins_(1) = int(hmat(1, 1) / voxelSize);
79 nBins_(2) = int(hmat(2, 2) / voxelSize);
81 hist_.resize(nBins_(0));
82 count_.resize(nBins_(0));
83 for (
int i = 0; i < nBins_(0); ++i) {
84 hist_[i].resize(nBins_(1));
85 count_[i].resize(nBins_(1));
86 for (
int j = 0; j < nBins_(1); ++j) {
87 hist_[i][j].resize(nBins_(2));
88 count_[i][j].resize(nBins_(2));
89 std::fill(hist_[i][j].begin(), hist_[i][j].end(), 0.0);
90 std::fill(count_[i][j].begin(), count_[i][j].end(), 0.0);
94 setOutputName(
getPrefix(filename) +
".Qxyz");
97 void TetrahedralityParamXYZ::process() {
104 Vector3d ri, rj, rk, rik, rkj;
108 std::vector<std::pair<RealType, StuntDouble*>> myNeighbors;
113 bool usePeriodicBoundaryConditions_ =
114 info_->getSimParams()->getUsePeriodicBoundaryConditions();
116 int kMax = int(5.0 * gaussWidth_ / voxelSize_);
117 int kSqLim = kMax * kMax;
118 cerr <<
"gw = " << gaussWidth_ <<
" vS = " << voxelSize_
119 <<
" kMax = " << kMax <<
" kSqLim = " << kSqLim <<
"\n";
121 DumpReader reader(info_, dumpFilename_);
122 int nFrames = reader.getNFrames();
124 for (
int istep = 0; istep < nFrames; istep += step_) {
125 reader.readFrame(istep);
127 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
128 Mat3x3d hmat = currentSnapshot_->getHmat();
129 Vector3d halfBox = Vector3d(hmat(0, 0), hmat(1, 1), hmat(2, 2)) / 2.0;
131 if (evaluator1_.isDynamic()) {
132 seleMan1_.setSelectionSet(evaluator1_.evaluate());
135 if (evaluator2_.isDynamic()) {
136 seleMan2_.setSelectionSet(evaluator2_.evaluate());
142 for (sd = seleMan1_.beginSelected(isd1); sd != NULL;
143 sd = seleMan1_.nextSelected(isd1)) {
144 myIndex = sd->getGlobalIndex();
149 for (sd2 = seleMan2_.beginSelected(isd2); sd2 != NULL;
150 sd2 = seleMan2_.nextSelected(isd2)) {
151 if (sd2->getGlobalIndex() != myIndex) {
152 vec = sd->getPos() - sd2->getPos();
154 if (usePeriodicBoundaryConditions_)
155 currentSnapshot_->wrapVector(vec);
161 if (r < rCut_) { myNeighbors.push_back(std::make_pair(r, sd2)); }
166 std::sort(myNeighbors.begin(), myNeighbors.end());
170 int nbors = myNeighbors.size() > 4 ? 4 : myNeighbors.size();
171 int nang = int(0.5 * (nbors * (nbors - 1)));
175 for (
int i = 0; i < nbors - 1; i++) {
176 sdi = myNeighbors[i].second;
179 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rik);
183 for (
int j = i + 1; j < nbors; j++) {
184 sdj = myNeighbors[j].second;
187 if (usePeriodicBoundaryConditions_)
188 currentSnapshot_->wrapVector(rkj);
191 cospsi =
dot(rik, rkj);
195 Qk -= (pow(cospsi + 1.0 / 3.0, 2) * 2.25 / nang);
200 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rk);
203 Vector3d pos = rk + halfBox;
205 Vector3i whichVoxel(
int(pos[0] / voxelSize_),
206 int(pos[1] / voxelSize_),
207 int(pos[2] / voxelSize_));
209 for (
int l = -kMax; l <= kMax; l++) {
210 for (
int m = -kMax; m <= kMax; m++) {
211 for (
int n = -kMax; n <= kMax; n++) {
212 int kk = l * l + m * m + n * n;
214 int ll = (whichVoxel[0] + l) % nBins_(0);
215 ll = ll < 0 ? nBins_(0) + ll : ll;
216 int mm = (whichVoxel[1] + m) % nBins_(1);
217 mm = mm < 0 ? nBins_(1) + mm : mm;
218 int nn = (whichVoxel[2] + n) % nBins_(2);
219 nn = nn < 0 ? nBins_(2) + nn : nn;
221 Vector3d bPos = Vector3d(ll, mm, nn) * voxelSize_ - halfBox;
222 Vector3d d = bPos - rk;
223 currentSnapshot_->wrapVector(d);
225 pow(2.0 * sqrt(Constants::PI) * gaussWidth_, 3);
226 RealType exponent = -
dot(d, d) / pow(2.0 * gaussWidth_, 2);
227 RealType weight = exp(exponent) / denom;
228 count_[ll][mm][nn] += weight;
229 hist_[ll][mm][nn] += weight * Qk;
258 void TetrahedralityParamXYZ::writeVTKGrid() {
259 Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
262 for (
unsigned int i = 0; i < hist_.size(); ++i) {
263 for (
unsigned int j = 0; j < hist_[i].size(); ++j) {
264 for (
unsigned int k = 0; k < hist_[i][j].size(); ++k) {
265 hist_[i][j][k] = hist_[i][j][k] / count_[i][j][k];
270 std::ofstream qXYZstream(outputFilename_.c_str());
271 if (qXYZstream.is_open()) {
272 qXYZstream <<
"# vtk DataFile Version 2.0\n";
273 qXYZstream <<
"Tetrahedrality Parameter volume rendering\n";
274 qXYZstream <<
"ASCII\n";
275 qXYZstream <<
"DATASET RECTILINEAR_GRID\n";
276 qXYZstream <<
"DIMENSIONS " << hist_.size() <<
" " << hist_[0].size()
277 <<
" " << hist_[0][0].size() <<
"\n";
278 qXYZstream <<
"X_COORDINATES " << hist_.size() <<
" float\n";
279 for (std::size_t i = 0; i < hist_.size(); ++i) {
280 qXYZstream << (RealType(i) / nBins_.x()) * hmat(0, 0) <<
" ";
283 qXYZstream <<
"Y_COORDINATES " << hist_[0].size() <<
" float\n";
284 for (std::size_t j = 0; j < hist_[0].size(); ++j) {
285 qXYZstream << (RealType(j) / nBins_.y()) * hmat(1, 1) <<
" ";
288 qXYZstream <<
"Z_COORDINATES " << hist_[0][0].size() <<
" float\n";
289 for (std::size_t k = 0; k < hist_[0][0].size(); ++k) {
290 qXYZstream << (RealType(k) / nBins_.z()) * hmat(2, 2) <<
" ";
293 qXYZstream <<
"POINT_DATA "
294 << hist_.size() * hist_[0].size() * hist_[0][0].size() <<
"\n";
295 qXYZstream <<
"SCALARS scalars float\n";
296 qXYZstream <<
"LOOKUP_TABLE default\n";
298 for (std::size_t k = 0; k < hist_[0][0].size(); ++k) {
299 for (std::size_t j = 0; j < hist_[0].size(); ++j) {
300 for (std::size_t i = 0; i < hist_.size(); ++i) {
301 qXYZstream << hist_[i][j][k] <<
" ";
310 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
311 "TetrahedralityParamXYZ: unable to open %s\n",
312 outputFilename_.c_str());
313 painCave.isFatal = 1;
319 void TetrahedralityParamXYZ::writeQxyz() {
320 Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
323 for (
unsigned int i = 0; i < hist_.size(); ++i) {
324 for (
unsigned int j = 0; j < hist_[i].size(); ++j) {
325 for (
unsigned int k = 0; k < hist_[i][j].size(); ++k) {
326 hist_[i][j][k] = hist_[i][j][k] / count_[i][j][k];
331 std::ofstream qXYZstream(outputFilename_.c_str());
332 if (qXYZstream.is_open()) {
333 qXYZstream <<
"# AmiraMesh ASCII 1.0\n\n";
334 qXYZstream <<
"# Dimensions in x-, y-, and z-direction\n";
335 qXYZstream <<
" define Lattice " << hist_.size() <<
" "
336 << hist_[0].size() <<
" " << hist_[0][0].size() <<
"\n";
338 qXYZstream <<
"Parameters {\n";
339 qXYZstream <<
" CoordType \"uniform\",\n";
340 qXYZstream <<
" # BoundingBox is xmin xmax ymin ymax zmin zmax\n";
341 qXYZstream <<
" BoundingBox 0.0 " << hmat(0, 0) <<
" 0.0 "
342 << hmat(1, 1) <<
" 0.0 " << hmat(2, 2) <<
"\n";
345 qXYZstream <<
"Lattice { double ScalarField } = @1\n";
347 qXYZstream <<
"@1\n";
349 for (std::size_t k = 0; k < hist_[0][0].size(); ++k) {
350 for (std::size_t j = 0; j < hist_[0].size(); ++j) {
351 for (std::size_t i = 0; i < hist_.size(); ++i) {
352 qXYZstream << hist_[i][j][k] <<
" ";
361 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
362 "TetrahedralityParamXYZ: unable to open %s\n",
363 outputFilename_.c_str());
364 painCave.isFatal = 1;
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)