/* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories LAMMPS development team: developers@lammps.org Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "write_coeff.h" #include "angle.h" #include "bond.h" #include "comm.h" #include "dihedral.h" #include "domain.h" #include "error.h" #include "force.h" #include "improper.h" #include "pair.h" #include #include using namespace LAMMPS_NS; enum { REGULAR_MODE, CLASS2_MODE }; static constexpr int BUF_SIZE = 256; /* ---------------------------------------------------------------------- called as write_coeff command in input script ------------------------------------------------------------------------- */ void WriteCoeff::command(int narg, char **arg) { if (domain->box_exist == 0) error->all(FLERR, "Write_coeff command before simulation box is defined" + utils::errorurl(33)); if (narg != 1) utils::missing_cmd_args(FLERR, "write_coeff", error); char *file = utils::strdup(fmt::format("{}.tmp", arg[0])); // initialize relevant styles lmp->init(); if (comm->me == 0) { char str[BUF_SIZE], coeff[BUF_SIZE]; FILE *one = fopen(file, "wb+"); if (one == nullptr) error->one(FLERR, "Cannot open coeff file {}: {}", file, utils::getsyserror()); if (force->pair && force->pair->writedata) { fprintf(one, "# pair_style %s\npair_coeff\n", force->pair_style); force->pair->write_data_all(one); fprintf(one, "end\n"); } if (force->bond && force->bond->writedata) { fprintf(one, "# bond_style %s\nbond_coeff\n", force->bond_style); force->bond->write_data(one); fprintf(one, "end\n"); } if (force->angle && force->angle->writedata) { fprintf(one, "# angle_style %s\nangle_coeff\n", force->angle_style); force->angle->write_data(one); fprintf(one, "end\n"); } if (force->dihedral && force->dihedral->writedata) { fprintf(one, "# dihedral_style %s\ndihedral_coeff\n", force->dihedral_style); force->dihedral->write_data(one); fprintf(one, "end\n"); } if (force->improper && force->improper->writedata) { fprintf(one, "# improper_style %s\nimproper_coeff\n", force->improper_style); force->improper->write_data(one); fprintf(one, "end\n"); } rewind(one); FILE *two = fopen(arg[0], "w"); if (two == nullptr) error->one(FLERR, "Cannot open coeff file {}: {}", arg[0], utils::getsyserror()); fprintf(two, "# LAMMPS coeff file via write_coeff, version %s\n", lmp->version); while (true) { int coeff_mode = REGULAR_MODE; if (fgets(str, BUF_SIZE, one) == nullptr) break; // some coeffs need special treatment if (strstr(str, "class2") != nullptr) { if (strstr(str, "angle_style") != nullptr) coeff_mode = CLASS2_MODE; else if (strstr(str, "dihedral_style") != nullptr) coeff_mode = CLASS2_MODE; else if (strstr(str, "improper_style") != nullptr) coeff_mode = CLASS2_MODE; } const char *section = (const char *) ""; // NOLINT fputs(str, two); // style utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); // coeff int n = strlen(str); strncpy(coeff, str, BUF_SIZE); coeff[n - 1] = '\0'; utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); while (strcmp(str, "end\n") != 0) { if (coeff_mode == REGULAR_MODE) { fprintf(two, "%s %s", coeff, str); utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); } else if (coeff_mode == CLASS2_MODE) { // class2 angles, dihedrals, and impropers can have // multiple sections and thus need special treatment if (strcmp(str, "\n") == 0) { // all but the the last section end with an empty line. // skip it and read and parse the next section title utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); if (strcmp(str, "BondBond Coeffs\n") == 0) section = (const char *) "bb"; else if (strcmp(str, "BondAngle Coeffs\n") == 0) section = (const char *) "ba"; else if (strcmp(str, "MiddleBondTorsion Coeffs\n") == 0) section = (const char *) "mbt"; else if (strcmp(str, "EndBondTorsion Coeffs\n") == 0) section = (const char *) "ebt"; else if (strcmp(str, "AngleTorsion Coeffs\n") == 0) section = (const char *) "at"; else if (strcmp(str, "AngleAngleTorsion Coeffs\n") == 0) section = (const char *) "aat"; else if (strcmp(str, "BondBond13 Coeffs\n") == 0) section = (const char *) "bb13"; else if (strcmp(str, "AngleAngle Coeffs\n") == 0) section = (const char *) "aa"; // gobble up one more empty line utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); } // parse type number and skip over it int type = std::stoi(str); char *p = str; while ((*p != '\0') && (*p == ' ')) ++p; while ((*p != '\0') && isdigit(*p)) ++p; fprintf(two, "%s %d %s %s", coeff, type, section, p); utils::sfgets(FLERR, str, BUF_SIZE, one, file, error); } } fputc('\n', two); } fclose(one); fclose(two); platform::unlink(file); } delete[] file; }