oILAB
Loading...
Searching...
No Matches
LandauWangTPImplementation.h
Go to the documentation of this file.
1//
2// Created by Nikhil Chandra Admal on 8/14/24.
3//
4
5#ifndef OILAB_LANDAUWANGTPIMPLEMENTATION_H
6#define OILAB_LANDAUWANGTPIMPLEMENTATION_H
7
8#include <iostream>
9#include <numeric>
10#include <GbMesoState.h>
11#include <iomanip>
12
13namespace gbLAB {
14/* ---------------------------------------------------*/
15 template<typename StateType, typename SystemType>
16 LandauWangTP<StateType,SystemType>::LandauWangTP(const std::tuple<double,double,int>& energyLimits,
17 const std::string& lmpLocation,
18 const std::string& potentialName):
19 LandauWangTP(energyLimits,{0.0,1.0,1},lmpLocation,potentialName)
20 {}
21
22 template<typename StateType, typename SystemType>
23 LandauWangTP<StateType,SystemType>::LandauWangTP(const std::tuple<double,double,int>& energyLimits,
24 const std::tuple<double,double,int>& densityLimits,
25 const std::string& lmpLocation,
26 const std::string& potentialName) try:
27 exponentialRegime(true),
28 f(exp(1.0)),
29 countLW(-1),
30 currentEnergy(0.0),
31 currentDensity(0.0),
32 energyLimits(energyLimits),
33 densityLimits(densityLimits),
34 numberOfEnergyStates(std::get<2>(energyLimits)),
35 numberOfDensityStates(std::get<2>(densityLimits)),
36 histogram(Eigen::MatrixXi::Zero(numberOfEnergyStates,numberOfDensityStates)),
37 stateDensityEnergyMap(getStateDensityEnergyMap()),
38 lmpLocation(lmpLocation),
39 potentialName(potentialName),
40 mask(getMask(numberOfEnergyStates,numberOfDensityStates)),
41 theta(getTheta(mask,f))
42 {
43 std::cout << "Number of the mask-free histogram bins= " << histogram.size()-mask.template cast<int>().sum() << std::endl;
44 spectrumFile.open("energyDensityLW.txt",std::ios_base::app);
45 }
46 catch(std::runtime_error& e)
47 {
48 std::cout << e.what() << std::endl;
49 exit(0);
50 }
51 template<typename StateType, typename SystemType>
52 double LandauWangTP<StateType,SystemType>::probability(const std::pair<StateType,SystemType>& proposedStateSystem,
53 const std::pair<StateType,SystemType>& currentStateSystem)
54 {
55 countLW++;
56 std::cout << countLW << ") ";
57 const auto& currentState= currentStateSystem.first;
58 const auto& currentSystem= currentStateSystem.second;
59 const auto& proposedState= proposedStateSystem.first;
60 const auto& proposedSystem= proposedStateSystem.second;
61
62 // Compute current state properties
63 // if this is the first call, compute the current energy and density
64 if(countLW==0) {
65 const auto& temp= currentSystem.densityEnergy(lmpLocation, potentialName, false);
66 //currentDensity= temp.first;
67 currentDensity= currentState.density();
68 currentEnergy= std::get<1>(temp);
69 std::cout << currentState;
70 stateDensityEnergyMap[currentState]= std::make_pair(std::get<0>(temp),std::get<1>(temp));
71 spectrumFile << currentDensity << " " << currentEnergy << " " << currentState << std::endl;
72 }
73 else {
74 assert(stateDensityEnergyMap.find(currentState) != stateDensityEnergyMap.end());
75 currentDensity= stateDensityEnergyMap.at(currentState).first;
76 currentEnergy= stateDensityEnergyMap.at(currentState).second;
77 }
78
79 // Compute proposed state properties
80 double proposedEnergy, proposedDensity;
81 if (stateDensityEnergyMap.find(proposedState) != stateDensityEnergyMap.end()) {
82 std::cout << "found. Proposed state = " << proposedState << std::endl;
83 proposedDensity= stateDensityEnergyMap.at(proposedState).first;
84 proposedEnergy = stateDensityEnergyMap.at(proposedState).second;
85 std::cout << "proposedDensity = " << proposedDensity << "; proposedEnergy = " << proposedEnergy << std::endl;
86 }
87 else {
88 std::cout << "new" << std::endl;
89 const auto& temp= proposedSystem.densityEnergy(lmpLocation, potentialName, false);
90 //proposedDensity= temp.first;
91 proposedDensity= proposedState.density();
92 proposedEnergy= std::get<1>(temp);
93 stateDensityEnergyMap[proposedState]= std::make_pair(std::get<0>(temp),std::get<1>(temp));
94 spectrumFile << proposedDensity << " " << proposedEnergy << " " << proposedState << std::endl;
95 }
96
97 auto [currentEnergyIndex,currentDensityIndex,currentInSpectrum]= spectrumIndex(currentEnergy,currentDensity,energyLimits,densityLimits);
98 auto [proposedEnergyIndex,proposedDensityIndex,proposedInSpectrum]= spectrumIndex(proposedEnergy,proposedDensity,energyLimits,densityLimits);
99
100 //if (currentEnergyIndex < 0) currentEnergyIndex = 0;
101
102 // if current state is outside the energy-density spectrum (or masked) accept the move
103 if (!currentInSpectrum || mask(currentEnergyIndex,currentDensityIndex))
104 return 1.0;
105 // now we are guaranteed that the current state is within the energy spectrum and is unmasked
106
107 // if the proposed state is not in the density-energy spectrum or is masked reject it
108 if (!proposedInSpectrum || mask(proposedEnergyIndex, proposedDensityIndex))
109 return 0.0;
110
111 // update histogram and theta only when the proposed state is unmasked and is in the spectrum
112 histogram(currentEnergyIndex,currentDensityIndex) += 1;
113 theta(currentEnergyIndex,currentDensityIndex) *= f;
114 double thetaNorm = theta.lpNorm<1>();
115 theta = theta / thetaNorm;
116
117 // output histogram
118 //std::cout << "current density = " << currentDensity
119 // << ", energy = " << currentEnergy << std::endl;
120 for(int i=0; i<histogram.rows(); ++i)
121 {
122 for(int j=0; j<histogram.cols(); ++j)
123 {
124 if(!mask(i,j))
125 std::cout << histogram(i,j) << " ";
126 }
127 }
128 std::cout << std::endl;
129
130 // update f
131 if (exponentialRegime) {
132 if (histogramIsFlat(0.8)) {
133 std::cout << "Histogram is flat: f = " << f << std::endl;
134 // reset the histogram
135 histogram.setZero();
136 // exponential regime
137 f = sqrt(f);
138 }
139 if (f < exp(1.0 / (countLW + 1))) {
140 std::cout << "Beginning non-exponential regime." << std::endl;
141 exponentialRegime = false;
142 // non-exponential regime
143 f = exp(1.0 / (countLW + 1));
144 }
145 } else
146 f = exp(1.0 / (countLW + 1));
147
148 return theta(currentEnergyIndex,currentDensityIndex) / theta(proposedEnergyIndex,proposedDensityIndex);
149 }
150
151
152 template<typename StateType,typename SystemType>
154 {
155 //int sum = std::accumulate(histogram.begin(), histogram.end(), 0);
156 int sum = histogram.sum();
157 int size= histogram.size()-mask.template cast<int>().sum();
158
159 std::vector<double> flatnessMeasure;
160
161 /*
162 for (const auto& element : histogram.reshaped())
163 flatnessMeasure.push_back(abs((double) element / sum - 1. / size));
164 // max(|e-mean|)/sum * size/0.8 < 1 => max(|e-mean|) < 0.8 * mean => max(mean-e) < 0.8 *mean => mean-min(e) < 0.8*mean => min(e) > 0.2*mean
165 */
166
167 for(int i=0; i<histogram.rows(); ++i)
168 {
169 for(int j=0; j<histogram.cols(); ++j)
170 {
171 if(!mask(i,j))
172 flatnessMeasure.push_back(abs((double) histogram(i,j)/ sum - 1. / size));
173 }
174
175 }
176
177 double nonFlatness= *std::max_element(flatnessMeasure.begin(), flatnessMeasure.end())*size/c;
178 //if (*std::max_element(flatnessMeasure.begin(), flatnessMeasure.end()) < c / histogram.size())
179 std::cout << "Flatness measure = " << nonFlatness << std::endl;
180
181 if (nonFlatness<1)
182 return true;
183 else
184 return false;
185 }
186
187 template<typename StateType,typename SystemType>
188 std::tuple<int,int,bool> LandauWangTP<StateType,SystemType>::spectrumIndex(const double& energy,
189 const double& density,
190 const std::tuple<double,double,int>& energyLimits,
191 const std::tuple<double,double,int>& densityLimits)
192 {
193 const auto& [minEnergy,maxEnergy,numberOfEnergyStates]= energyLimits;
194 const auto& [minDensity,maxDensity,numberOfDensityStates]= densityLimits;
195 double deltaE= (maxEnergy - minEnergy) / numberOfEnergyStates;
196 double deltarho= (maxDensity - minDensity) / numberOfDensityStates;
197
198 int energyIndex = floor((energy - minEnergy) / deltaE);
199 int densityIndex = floor((density- minDensity) / deltarho);
200 if (energyIndex >= 0 && energyIndex < numberOfEnergyStates &&
201 densityIndex >= 0 && densityIndex < numberOfDensityStates)
202 return std::make_tuple(energyIndex,densityIndex,true);
203 else
204 return std::make_tuple(energyIndex,densityIndex,false);
205 }
206
207 template<typename StateType,typename SystemType>
208 Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic> LandauWangTP<StateType,SystemType>::getMask(const int& numberOfEnergyStates,
209 const int& numberOfDensityStates)
210 {
211 Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic> output(numberOfEnergyStates,numberOfDensityStates);
212 output.setZero();
213 std::ifstream file;
214 file.open("mask.txt");
215 std::string line;
216 if (!file)
217 std::cout << "File mask.txt not found.";
218 else{
219 int i= 0;
220 while(std::getline(file,line)) {
221 std::stringstream s(line);
222 for (int j = 0; j < numberOfDensityStates; ++j)
223 s >> output(i, j);
224 ++i;
225 }
226 }
227 std::cout << "mask = " << std::endl;
228 std::cout << output << std::endl;
229 return output;
230 }
231
232 template<typename StateType,typename SystemType>
233 std::map<StateType, std::pair<double,double>> LandauWangTP<StateType,SystemType>::getStateDensityEnergyMap()
234 {
235 std::map<StateType, std::pair<double,double>> output;
236 std::ifstream file;
237 file.open("energyDensityLW.txt");
238 if (!file)
239 return output;
240
241 double energy, density;
242
243 std::string line;
244 while(std::getline(file,line)) {
245 std::stringstream s(line);
246 s >> density; s >> energy;
247 int temp;
248 std::vector<int> tempVector;
249 while (s >> temp)
250 tempVector.push_back(temp);
251
252 StateType state(tempVector.size());
253 for (int i=0; i<tempVector.size(); ++i)
254 state(i)= tempVector[i];
255
256 output[state]= std::make_pair(density,energy);
257 }
258
259 /*
260 for (const auto& [key,value]: output)
261 std::cout << value.first << " " << value.second << " " << key << std::endl;
262 */
263 std::cout << "Number of pre-computed states = " << output.size() << std::endl;
264 file.close();
265 return output;
266 }
267
268 template<typename StateType,typename SystemType>
269 Eigen::MatrixXd LandauWangTP<StateType,SystemType>::getTheta(const Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>& mask,
270 double& f)
271 {
272 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> outputTheta(mask.rows(),mask.cols());
273 std::ifstream file;
274 file.open("theta.txt");
275 std::string line;
276 if (!file) {
277 std::cout << "File theta.txt not found. Setting a uniform distribution for theta";
278 outputTheta.setOnes();
279 }
280 else {
281 outputTheta.setZero();
282 int lno= -1;
283 while(std::getline(file,line)) {
284 std::stringstream s(line);
285 int j= 0;
286 double temp;
287 while(s >> temp)
288 {
289 if (lno==-1) {
290 f = temp;
291 break;
292 }
293 outputTheta(lno,j)= temp;
294 j++;
295 }
296 if (lno != -1 && j != mask.cols())
297 throw(std::runtime_error("Error reading row in theta.txt") );
298 lno++;
299 }
300 if (lno != mask.rows())
301 throw(std::runtime_error("Error reading column in theta.txt") );
302
303 }
304
305 // normalize theta
306 double outputThetaNorm= 0.0;
307 for(int i=0; i<outputTheta.rows(); ++i)
308 {
309 for(int j=0; j<outputTheta.cols(); ++j)
310 {
311 if(!mask(i,j))
312 outputThetaNorm+= abs(outputTheta(i,j));
313 else
314 outputTheta(i,j)= 0.0;
315 }
316 }
317 outputTheta= outputTheta/outputThetaNorm;
318 std::cout << "f = " << f << std::endl;
319 std::cout << "theta = " << std::endl;
320 std::cout << outputTheta << std::endl;
321 return outputTheta;
322 }
323
324
325 template<typename StateType,typename SystemType>
326 void LandauWangTP<StateType,SystemType>::writeTheta(const std::string& filename) const
327 {
328 std::ofstream outputFileHandle;
329 outputFileHandle.open(filename);
330 outputFileHandle << f << std::endl;
331 outputFileHandle << theta;
332 outputFileHandle.close();
333 }
334
335}
336#endif
std::pair< double, double > energy(const std::string &lammpsLocation, const std::string &oilabConfigFile, const std::string &potentialFile)
Definition Lammps.h:239
static Eigen::MatrixXd getTheta(const Eigen::Matrix< bool, Eigen::Dynamic, Eigen::Dynamic > &mask, double &f)
LandauWangTP(const std::tuple< double, double, int > &energyLimits, const std::string &lmpLocation, const std::string &potentialName)
Eigen::MatrixXi histogram
bool histogramIsFlat(const double &c) const
static std::tuple< int, int, bool > spectrumIndex(const double &energy, const double &density, const std::tuple< double, double, int > &energyLimits, const std::tuple< double, double, int > &densityLimits)
void writeTheta(const std::string &filename) const
double probability(const std::pair< StateType, SystemType > &proposedState, const std::pair< StateType, SystemType > &currentState)
static std::map< StateType, std::pair< double, double > > getStateDensityEnergyMap()
std::ofstream spectrumFile
Eigen::Matrix< bool, Eigen::Dynamic, Eigen::Dynamic > mask
static Eigen::Matrix< bool, Eigen::Dynamic, Eigen::Dynamic > getMask(const int &numberOfEnergyStates, const int &numberOfDensityStates)