25 auto next_line = [&]() -> std::string {
26 while (std::getline(std::cin, line)) {
27 if (line.empty() || line[0] ==
'#' || line.find_first_not_of(
" \t\r\n") == std::string::npos)
continue;
34 std::istringstream configFileStream(next_line());
36 std::string currentConfigFileName, referenceConfigFileName;
37 std::ifstream referenceConfigFile, currentConfigFile;
38 if (configFileStream >> currentConfigFileName) {
39 std::cout <<
"LAMMPS data file for current configuration: " << currentConfigFileName << std::endl;
40 currentConfigFile.open(currentConfigFileName);
41 if(!currentConfigFile)
MY_ERROR(
"ERROR: current configuration file could not be opened for reading!");
43 if (configFileStream >> referenceConfigFileName) {
44 std::cout <<
"LAMMPS data file for reference configuration: " << referenceConfigFileName << std::endl;
45 referenceConfigFile.open(referenceConfigFileName);
46 if(!referenceConfigFile)
MY_ERROR(
"ERROR: reference configuration file could not be opened for reading!");
48 if(referenceConfigFileName.empty())
49 referenceConfigFileName= currentConfigFileName;
53 int numberOfParticles;
54 double xlo, xhi, ylo, yhi, zlo, zhi;
55 while (std::getline(currentConfigFile, line)) {
56 std::string loweredLine = line;
57 std::transform(loweredLine.begin(), loweredLine.end(), loweredLine.begin(), ::tolower);
59 if (loweredLine.find(
"atoms") != std::string::npos && (std::stringstream(line) >> numberOfParticles) ) {
61 else if (loweredLine.find(
"xlo xhi") != std::string::npos) {
62 std::istringstream ss(line);
64 }
else if (loweredLine.find(
"ylo yhi") != std::string::npos) {
65 std::istringstream ss(line);
67 }
else if (loweredLine.find(
"zlo zhi") != std::string::npos) {
68 std::istringstream ss(line);
74 if (numberOfParticles < 0)
MY_ERROR(
"Error: Negative number of particles.\n");
77 body.
readLMP(currentConfigFileName,referenceConfigFileName);
81 std::istringstream pbStream(next_line());
82 pbStream >> pbc(0) >> pbc(1) >> pbc(2);
83 std::cout <<
"PBCs: " << pbc << std::endl;
86 std::ofstream writeConfigReference(
"reference.txt");
87 std::ofstream writeConfigCurrent(
"current.txt");
88 for (
int i=0; i<body.numberOfParticles; ++i)
90 writeConfigReference << body.species[i] <<
" " << body.coordinates[
Reference].row(i) << std::endl;
91 writeConfigCurrent << body.species[i] <<
" " << body.coordinates[
Current].row(i) << std::endl;
95 std::string kimID = next_line();
96 std::cout <<
"KIM ID: " << kimID << std::endl;
100 std::istringstream atomStream(next_line());
101 std::vector<std::string> atomTypes;
103 while (atomStream >> atom) atomTypes.push_back(atom);
104 std::cout <<
"Atom types: ";
105 for (
const auto& a : atomTypes) std::cout << a <<
" ";
106 std::cout << std::endl;
109 int numGrids = std::stoi(next_line());
110 std::cout <<
"Number of grids: " << numGrids <<
"\n";
112 int ngridx, ngridy, ngridz;
113 double deltax, deltay, deltaz;
114 std::string outPrefix;
116 for (
int i = 0; i < numGrids; ++i) {
118 MY_HEADING(
"Reading stress and grid parameters from input file");
120 std::istringstream stressStream(next_line());
121 std::string stressMethod, averagingDomain, averagingDomainParameter;
122 double averagingDomainSize;
124 stressStream >> stressMethod >> averagingDomain ;
125 std::cout <<
"stress method: " << stressMethod <<
"\n";
126 std::cout <<
"averaging domain: " << averagingDomain <<
"\n";
127 if (stressMethod ==
"project")
133 if (averagingDomain==
"ldad")
135 stressStream >> averagingDomainParameter;
136 std::cout <<
"averaging domain parameter: " << averagingDomainParameter <<
"\n";
139 if (averagingDomainParameter==
"bcc" || averagingDomainParameter==
"fcc")
141 stressStream >> averagingDomainSize >> xdir(0) >> xdir(1) >> xdir(2) >>
142 ydir(0) >> ydir(1) >> ydir(2) >>
143 zdir(0) >> zdir(1) >> zdir(2);
144 std::cout <<
"averaging domain size : " << averagingDomainSize <<
"\n";
147 if (averagingDomainParameter==
"bcc"){
148 basis1 << -0.5,0.5,0.5; basis2 << 0.5,-0.5,0.5; basis3 << 0.5,0.5,-0.5;
150 else if (averagingDomainParameter==
"fcc"){
151 basis1 << 0,0.5,0.5; basis2 << 0.5,0,0.5; basis3 << 0.5,0.5,0;
156 rotation.row(0)= xdir.normalized();
157 rotation.row(1)= ydir.normalized();
158 rotation.row(2)= zdir.normalized();
159 assert((rotation.transpose()*rotation).isIdentity());
160 ldadVectors.col(0)= rotation*basis1.transpose();
161 ldadVectors.col(1)= rotation*basis2.transpose();
162 ldadVectors.col(2)= rotation*basis3.transpose();
163 ldadVectors= ldadVectors* averagingDomainSize;
166 else if (averagingDomainParameter==
"lat")
167 stressStream >> ldadVectors(0,0) >> ldadVectors(1,0) >> ldadVectors(2,0) >>
168 ldadVectors(0,1) >> ldadVectors(1,1) >> ldadVectors(2,1) >>
169 ldadVectors(0,2) >> ldadVectors(1,2) >> ldadVectors(2,2);
171 else if (averagingDomain==
"sphere"){
172 stressStream >> averagingDomainSize;
173 std::cout <<
"averaging domain size : " << averagingDomainSize <<
"\n";
177 std::istringstream gridStream(next_line());
178 std::string token[9];
179 for (
auto & j : token) {
183 auto parseOrFallback = [](
const std::string& s,
double fallback) ->
double {
184 return (s ==
"*") ? fallback : std::stod(s);
187 lowerLimit[0]= parseOrFallback(token[0], xlo)-FLT_EPSILON;
188 lowerLimit[1]= parseOrFallback(token[1], ylo)-FLT_EPSILON;
189 lowerLimit[2]= parseOrFallback(token[2], zlo)-FLT_EPSILON;
194 upperLimit[0]= parseOrFallback(token[3], xhi);
195 upperLimit[1]= parseOrFallback(token[4], yhi);
196 upperLimit[2]= parseOrFallback(token[5], zhi);
199 deltax = std::stod(token[6]);
200 deltay = std::stod(token[7]);
201 deltaz = std::stod(token[8]);
203 ngridx= (abs(deltax) > FLT_EPSILON) ? floor((upperLimit(0)-lowerLimit(0))/deltax) : 1;
204 ngridy= (abs(deltay) > FLT_EPSILON) ? floor((upperLimit(1)-lowerLimit(1))/deltay) : 1;
205 ngridz= (abs(deltaz) > FLT_EPSILON) ? floor((upperLimit(2)-lowerLimit(2))/deltaz) : 1;
210 std::cout <<
"Grid Limits: ";
211 std::cout << lowerLimit <<
" " << upperLimit << std::endl;
212 std::cout <<
"Number of grid points: " << ngridx <<
" " << ngridy <<
" " << ngridz << std::endl;
215 outPrefix= next_line();
216 std::cout <<
"Output file: " << outPrefix <<
"\n";
219 if (averagingDomain==
"ldad") {
227 std::tie(ldadTrigonometricStress),
228 std::tie(), project);
230 double mlsRadius= 10.0;
231 Mls mls(body,&grid,mlsRadius,outPrefix);
232 std::vector<Matrix3d> cauchyPushedField;
237 catch (
const std::runtime_error &e) {
238 std::cout << e.what() << std::endl;
239 std::cout <<
"Compute stress with projected forces failed. Moving on" << std::endl;
242 else if(averagingDomain==
"sphere"){
243 Grid<Current> grid(lowerLimit, upperLimit, ngridx, ngridy, ngridz);
252 std::tie(hardyStress), project);
253 hardyStress.
write(outPrefix);
255 catch (
const std::runtime_error &e) {
256 std::cout << e.what() << std::endl;
257 std::cout <<
"Compute stress with projected forces failed. Moving on" << std::endl;
261 MY_ERROR(
"Unknown stress method: " + stressMethod);