- swithced to prefix "++"
[alexxy/gromacs-domains.git] / src / domaintype.cpp
1 #include "domaintype.h"
2
3 // деструктор класса
4 domainType::~domainType() {}
5
6 // конструктор класса для полноценной инициализации данных
7 domainType::domainType(const std::vector< size_t > &index, const std::vector< RVec > &reference,
8                     const int windowSize, const int domainMinimumSize,
9                     const int domainSearchAlgorythm, const int timeStepBetweenWindowStarts,
10                     const unsigned int sliceNum, const double epsilon, const double delta,
11                     const std::string &outPutFileName) {
12     setDefaults(index, reference, windowSize, domainMinimumSize, domainSearchAlgorythm, timeStepBetweenWindowStarts, sliceNum, epsilon, delta, outPutFileName);
13 }
14
15 // функция заполнения необходимых данных для вычисления структурных доменов
16 void domainType::setDefaults(const std::vector< size_t > &index, const std::vector< RVec > &reference,
17                         const int windowSize, const int domainMinimumSize,
18                         const int domainSearchAlgorythm, const int timeStepBetweenWindows,
19                         const unsigned int sliceNum, const double epsilon, const double delta,
20                         const std::string &outPutFileName) {
21     graph.resize(0);
22     structIndex = index;
23     refTable.resize(reference.size());
24     for (size_t i {0}; i < reference.size(); ++i) {
25         refTable[i].resize(0);
26         for (size_t j {0}; j < reference.size(); ++j) {
27             refTable[i].push_back(reference[i] - reference[j]);
28         }
29     }
30     epsilon > 0 ? eps = epsilon : eps = 0.2;
31     delta > 0 && delta <= 1 ? dlt = delta : dlt = 0.95;
32     windowSize > 0 ? window = windowSize : window = 1000;
33     domainMinimumSize > 3 ? dms = domainMinimumSize : dms = 4;
34     domainSearchAlgorythm > -1 && domainSearchAlgorythm < 3 ? dsa = domainSearchAlgorythm : dsa = 0;
35     timeStepBetweenWindows > 0 ? ts = timeStepBetweenWindows : ts = window / 10;
36     outPutFileName.size() > 0 ? outPut = outPutFileName : outPut = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
37     domsizes.resize(0);
38     domsizes.resize(sliceNum);
39     updateCount = 0;
40 }
41
42 // фукнция обновления данных для выделения структурных доменов
43 void domainType::update(const std::vector< std::vector< RVec > > &frame, const int frameNumber) {
44     // инициализируем новое "окно", громакс считает кадры с нуля
45     if (frameNumber % ts == 0) {
46         graph.resize(graph.size() + 1);
47         graph.back().resize(structIndex.size() - static_cast< size_t >(dms) + 1);
48         for (auto &i : graph.back()) {
49             setGraph(i);
50         }
51     }
52     // заполняем матрицы данных для структурных доменов для всех текущих "окон"
53     for (auto &i : graph) {
54         #pragma omp parallel for
55         for (size_t j = 0; j < i.size(); ++j) {
56             for (size_t k1 {0}; k1 < i[j].size(); ++k1) {
57                 for (size_t k2 {k1}; k2 < i[j].size(); ++k2) {
58                     if ((frame[j][k1] - frame[j][k2] - refTable[k1][k2]).norm() <= static_cast< float >(eps)) {
59                         if (k1 != k2) {
60                             ++i[j][k1][k2].num;
61                             ++i[j][k2][k1].num;
62                         } else {
63                             ++i[j][k1][k2].num;
64                         }
65                     }
66                 }
67             }
68         }
69         #pragma omp barrier
70     }
71     // обновляем число эффективных обновлений
72     if (graph.size() > 0) {
73         ++updateCount;
74     }
75     // в случае, если число обновлений равно размеру окна, выделяем на нём домены
76     if (updateCount == window) {
77         getDomains();
78         print(frameNumber);
79     }
80 }
81
82 // инициализация матриц соотношений в структуре
83 void domainType::setGraph(std::vector< std::vector< node > > &smallGraph) {
84     smallGraph.resize(0);
85     smallGraph.resize(refTable.size());
86     for (size_t i {0}; i < refTable.size(); ++i) {
87         smallGraph[i].resize(0);
88         smallGraph[i].resize(refTable.size());
89         for (size_t j {0}; j < refTable.size(); ++j) {
90             smallGraph[i][j].num = 0;
91             smallGraph[i][j].check = false;
92         }
93     }
94 }
95
96 // "зануление" элементов матриц вошедших в домен
97 void domainType::deleteDomainFromGraph(const std::vector< size_t > &domain) {
98     for (auto &i : graph.front()) {
99         for (const auto &j : domain) {
100             for (size_t k {0}; k < i.size(); ++k) {
101                 i[j][k].check = false;
102                 i[k][j].check = false;
103             }
104         }
105     }
106 }
107
108 // подсчёт размеров всех потенциально возможных доменов и проверка на наличие домена для выделения
109  bool domainType::searchDomainSizes() {
110     bool flag {false};
111     for (size_t i {0}; i < graph.front().size(); ++i) {
112         domsizes[i].resize(0); // необходимо переопределять память
113         domsizes[i].resize(graph.front()[i].size(), 0);
114         for (size_t j {0}; j < graph.front()[i].size(); ++j) {
115             for (const auto &k : graph.front()[i][j]) {
116                 if (k.check) {
117                     ++domsizes[i][j];
118                 }   
119             }
120             if ((!flag) && (domsizes[i][j] >= dms)) {
121                 flag = true;
122             }
123         }
124     }
125     return flag;
126 }
127
128 // функция выделения доменов
129 void domainType::getDomains() {
130     // проверка элементов матриц на создание на их основе доменов
131     for (auto &i : graph.front()) {
132         for (auto &j : i) {         //  -> матрица соотношений в структуре всё на всё
133             for (auto &k : j) {     //  -> матрица соотношений в структуре всё на всё
134                 if (k.num >= window * dlt) {
135                     k.check = true;
136                 }
137             }
138         }
139     }
140     domains.resize(0);
141     // итеративное выделение доменов одним из трёх способов
142     while (searchDomainSizes()) {
143         size_t t1 {0}, t2 {0};
144         for (size_t i {0}; i < domsizes.size(); ++i) {
145             for (size_t j {0}; j < domsizes[i].size(); ++j) {
146                 // вынуждены выделять первый домен из равных по кол-ву элементов
147                 if ((dsa == 0) && (domsizes[i][j] > domsizes[t1][t2])) {
148                     t1 = i;
149                     t2 = j;
150                 }
151                 if ((dsa == 2) && (domsizes[i][j] >= dms) && ((domsizes[i][j] < domsizes[t1][t2]) || (domsizes[t1][t2] < dms))) {
152                     t1 = i;
153                     t2 = j;
154                 }
155             }
156         }
157         // выделяем найдённый домен
158         domains.resize(domains.size() + 1);
159         for (size_t i {0}; i < graph.front()[t1][t2].size(); ++i) {
160             if (graph.front()[t1][t2][i].check) {
161                 domains.back().push_back(i);
162             }
163         }
164         //выход из поиска доменов при данном режиме обработки
165         if (dsa == 1) {
166             break;
167         }
168         // удаляем выделенный домен из матриц
169         deleteDomainFromGraph(domains.back());
170     }
171     // удаляем рассматриваемое окно
172     graph.erase(graph.begin());
173     // смещаем счётчик обновлений для следующего окна
174     updateCount = std::max(0, window - ts);
175 }
176
177 // функция печати ndx и selectionList файлов
178 void domainType::print(int currentFrame) {
179     if (domains.size() == 0) {
180         return;
181     }
182     FILE *ndxFile {std::fopen(outPut.c_str(), "a+")}, *slFile {std::fopen(("selectionList-" + outPut.substr(0, outPut.size() - 4)).c_str(), "a+")};
183     short int writeCount {0};
184     for (size_t i {0}; i < domains.size(); ++i) {
185         // domain - стартовая позиция в фреймах - номер домена - минимальный размер домена -
186         // константа тепловых колебаний (отклонения) - константа входимости (отклонения)
187         std::fprintf(ndxFile, "[domain-stPos-%06d-num-%03lu-dms-%03d-epsi-%04.3f-delta-%04.3f]\n", currentFrame - window + 1, i + 1, dms, eps, dlt);
188         std::fprintf(slFile, "group %cdomain-stPos-%06d-num-%03lu-dms-%03d-epsi-%04.3f-delta-%04.3f%c;\n", '"', currentFrame - window + 1, i + 1, dms, eps, dlt, '"');
189         writeCount = 0;
190         std::printf("\n");
191         for (size_t j {0}; j < domains[i].size(); ++j) {
192             ++writeCount;
193             if (writeCount > 20) {
194                 writeCount -= 20;
195                 std::fprintf(ndxFile, "\n");
196             }
197             std::fprintf(ndxFile, "%5lu ", structIndex[domains[i][j]] + 1);
198             std::printf("%5lu ", structIndex[domains[i][j]] + 1);
199         }
200         std::fprintf(ndxFile,"\n\n");
201         std::printf("\n\n");
202     }
203     std::fprintf(ndxFile,"\n");
204     std::fclose(ndxFile);
205     std::fclose(slFile);
206 }