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;
 
  191        upperLimit[0]= parseOrFallback(token[3], xhi);
 
  192        upperLimit[1]= parseOrFallback(token[4], yhi);
 
  193        upperLimit[2]= parseOrFallback(token[5], zhi);
 
  196        deltax = std::stod(token[6]);
 
  197        deltay = std::stod(token[7]);
 
  198        deltaz = std::stod(token[8]);
 
  200        ngridx= (abs(deltax) > FLT_EPSILON) ? floor((upperLimit(0)-lowerLimit(0))/deltax) : 1;
 
  201        ngridy= (abs(deltay) > FLT_EPSILON) ? floor((upperLimit(1)-lowerLimit(1))/deltay) : 1;
 
  202        ngridz= (abs(deltaz) > FLT_EPSILON) ? floor((upperLimit(2)-lowerLimit(2))/deltaz) : 1;
 
  204        std::cout << 
"Grid Limits: ";
 
  205        std::cout << lowerLimit << 
" " << upperLimit << std::endl;
 
  206        std::cout << 
"Number of grid points: " << ngridx << 
" " << ngridy << 
" " << ngridz << std::endl;
 
  209        outPrefix= next_line();
 
  210        std::cout << 
"Output file: " << outPrefix << 
"\n";
 
  213        if (averagingDomain==
"ldad") {
 
  221                                std::tie(ldadTrigonometricStress),
 
  222                                std::tie(), project);
 
  224                double mlsRadius= 10.0;
 
  225                Mls mls(body,&grid,mlsRadius,outPrefix);
 
  226                std::vector<Matrix3d> cauchyPushedField;
 
  231            catch (
const std::runtime_error &e) {
 
  232                std::cout << e.what() << std::endl;
 
  233                std::cout << 
"Compute stress with projected forces failed. Moving on" << std::endl;
 
  236        else if(averagingDomain==
"sphere"){
 
  237            Grid<Current> grid(lowerLimit, upperLimit, ngridx, ngridy, ngridz);
 
  246                                std::tie(hardyStress), project);
 
  247                hardyStress.
write(outPrefix);
 
  249            catch (
const std::runtime_error &e) {
 
  250                std::cout << e.what() << std::endl;
 
  251                std::cout << 
"Compute stress with projected forces failed. Moving on" << std::endl;
 
  255            MY_ERROR(
"Unknown stress method: " + stressMethod);