diff --git a/doc/src/create_atoms.rst b/doc/src/create_atoms.rst index 492253bffc..ccf987e726 100644 --- a/doc/src/create_atoms.rst +++ b/doc/src/create_atoms.rst @@ -21,7 +21,7 @@ Syntax *single* args = x y z x,y,z = coordinates of a single particle (distance units) *mesh* args = STL-file - STL-file = file with triangle mesh in ASCII STL format + STL-file = file with triangle mesh in STL format *random* args = N seed region-ID N = number of particles to create seed = random # seed (positive integer) @@ -136,18 +136,20 @@ positions. :align: right :target: _images/marble_race.jpg -For the *mesh* style, a file with a triangle mesh in `ASCII STL format -`_ is read -and one or more particles are placed into the area of each triangle. -Binary STL files (e.g. as frequently offered for 3d-printing) can be -converted to ASCII with the :ref:`stl_bin2txt tool `. The -use of the *units box* option is required. There are two algorithms for -placing atoms available: *bisect* and *qrand*. They can be selected via -the *meshmode* option; *bisect* is the default. If the atom style allows -to set a per-atom radius this radius is set to the average -distance of the triangle vertices from its center times the value of the -*radscale* keyword (default: 1.0). If the atom style supports it, the -atoms created from the mesh are assigned a new molecule ID. +For the *mesh* style, a file with a triangle mesh in `STL format +`_ is read and one or +more particles are placed into the area of each triangle. The reader +supports both ASCII and binary files conforming to the format on the +Wikipedia page. Binary STL files (e.g. as frequently offered for +3d-printing) also be first converted to ASCII for editing with the +:ref:`stl_bin2txt tool `. The use of the *units box* option +is required. There are two algorithms for placing atoms available: +*bisect* and *qrand*. They can be selected via the *meshmode* option; +*bisect* is the default. If the atom style allows to set a per-atom +radius this radius is set to the average distance of the triangle +vertices from its center times the value of the *radscale* keyword +(default: 1.0). If the atom style supports it, the atoms created from +the mesh are assigned a new molecule ID. In *bisect* mode a particle is created at the center of each triangle unless the average distance of the triangle vertices from its center is diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 0b3a14403c..e24b20e02f 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -1036,9 +1036,11 @@ void CreateAtoms::add_mesh(const char *filename) molid = maxmol + 1; } - FILE *fp = fopen(filename, "r"); + FILE *fp = fopen(filename, "rb"); if (fp == nullptr) error->one(FLERR, "Cannot open file {}: {}", filename, utils::getsyserror()); + // first try reading the file in ASCII format + TextFileReader reader(fp, "STL mesh"); try { char *line = reader.next_line(); @@ -1047,7 +1049,7 @@ void CreateAtoms::add_mesh(const char *filename) line += 6; if (comm->me == 0) - utils::logmesg(lmp, "Reading STL object {} from file {}\n", utils::trim(line), filename); + utils::logmesg(lmp, "Reading STL object {} from text file {}\n", utils::trim(line), filename); while ((line = reader.next_line())) { @@ -1092,7 +1094,49 @@ void CreateAtoms::add_mesh(const char *filename) } } } catch (std::exception &e) { - error->all(FLERR, "Error reading triangles from file {}: {}", filename, e.what()); + + // if ASCII failed for the first line, try reading as binary + if (utils::strmatch(e.what(), "^Invalid STL mesh file format")) { + char title[80]; + float triangle[12]; + uint32_t ntri; + uint16_t attr; + size_t count; + + rewind(fp); + count = fread(title, sizeof(char), 80, fp); + title[79] = '\0'; + count = fread(&ntri, sizeof(ntri), 1, fp); + if (count <= 0) { + error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror()); + } else { + if (comm->me == 0) + utils::logmesg(lmp, "Reading STL object {} from binary file {}\n", utils::trim(title), + filename); + } + + for (uint32_t i = 0U; i < ntri; ++i) { + count = fread(triangle, sizeof(float), 12, fp); + if (count != 12) + error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror()); + count = fread(&attr, sizeof(attr), 1, fp); + + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 3; ++k) vert[j][k] = triangle[3 * j + 3 + k]; + + ++ntriangle; + if (mesh_style == BISECTION) { + // add in center of triangle or bisecting recursively along longest edge + // as needed to get the desired atom density/radii + atomlocal += add_bisection(vert, molid); + } else if (mesh_style == QUASIRANDOM) { + // add quasi-random distribution of atoms + atomlocal += add_quasirandom(vert, molid); + } + } + } else { + error->all(FLERR, "Error reading triangles from file {}: {}", filename, e.what()); + } } if (ntriangle > 0) {