Adding quasirandom mesh option

This commit is contained in:
Joel Thomas Clemmer
2022-05-10 18:35:36 -06:00
parent bdbab77286
commit c9d350edc2
3 changed files with 120 additions and 4 deletions

View File

@ -48,12 +48,15 @@ using MathConst::THIRD;
static constexpr double BIG = 1.0e30;
static constexpr double EPSILON = 1.0e-6;
static constexpr double LB_FACTOR = 1.1;
static constexpr double INV_P_CONST = 0.7548777;
static constexpr double INV_SQ_P_CONST = 0.5698403;
static constexpr int DEFAULT_MAXTRY = 1000;
enum { BOX, REGION, SINGLE, RANDOM, MESH };
enum { ATOM, MOLECULE };
enum { COUNT, INSERT, INSERT_SELECTED };
enum { NONE, RATIO, SUBSET };
enum { TRICENTER, QUASIRANDOM };
/* ---------------------------------------------------------------------- */
@ -135,6 +138,7 @@ void CreateAtoms::command(int narg, char **arg)
int scaleflag = 1;
remapflag = 0;
mesh_style = TRICENTER;
mode = ATOM;
int molseed;
ranmol = nullptr;
@ -261,6 +265,8 @@ void CreateAtoms::command(int narg, char **arg)
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms radscale", error);
if (style != MESH)
error->all(FLERR, "Create_atoms radscale can only be used with mesh style");
if (mesh_style != TRICENTER)
error->all(FLERR, "Create_atoms radscale can only be used with tricenter mesh style");
if (!atom->radius_flag)
error->all(FLERR, "Must have atom attribute radius to set radscale factor");
radscale = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
@ -269,8 +275,17 @@ void CreateAtoms::command(int narg, char **arg)
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms radthresh", error);
if (style != MESH)
error->all(FLERR, "Create_atoms radthresh can only be used with mesh style");
if (mesh_style != TRICENTER)
error->all(FLERR, "Create_atoms radthresh can only be used with tricenter mesh style");
radthresh = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
iarg += 2;
} else if (strcmp(arg[iarg], "quasirandom") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms quasirandom", error);
if (style != MESH)
error->all(FLERR, "Create_atoms quasirandom can only be used with mesh style");
mesh_style = QUASIRANDOM;
mesh_density = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
iarg += 2;
} else
error->all(FLERR, "Illegal create_atoms command option {}", arg[iarg]);
}
@ -925,6 +940,86 @@ int CreateAtoms::add_tricenter(const double vert[3][3], tagint molid)
return ilocal;
}
/* ----------------------------------------------------------------------
add monodisperse atoms by mapping quasirandom sequence onto a triangle
method by Martin Roberts 2019 http://extremelearning.com.au/evenly-distributing-points-in-a-triangle/
------------------------------------------------------------------------- */
int CreateAtoms::add_quasirandom(const double vert[3][3], tagint molid)
{
double ab[3], ac[3], bc[3], temp[3], point[3], ref[3];
double lab, lac, lbc, area, xi, yi;
double seed = 0.5;
// Order vertices such that a has the largest angle
MathExtra::sub3(vert[1], vert[0], ab);
MathExtra::sub3(vert[2], vert[0], ac);
MathExtra::sub3(vert[2], vert[1], bc);
lab = MathExtra::len3(ab);
lac = MathExtra::len3(ac);
lbc = MathExtra::len3(bc);
if (lac > lab && lac > lbc) {
// B has the largest angle, relabel as A
MathExtra::scale3(-1.0, ab);
MathExtra::copy3(bc, ac);
MathExtra::copy3(vert[1], ref);
} else if (lab > lac && lab > lbc) {
// C has the largest angle, relabel as A
MathExtra::scale3(-1.0, ac);
MathExtra::copy3(bc, ab);
MathExtra::scale3(-1.0, ab);
MathExtra::copy3(vert[2], ref);
} else {
MathExtra::copy3(vert[0], ref);
}
// Estimate number of particles from area, could scale by RCP
MathExtra::cross3(ab, ac, temp);
area = 0.5 * MathExtra::len3(temp);
int nparticles = ceil(mesh_density * area);
for (int i = 0; i < nparticles; i++) {
// Define point in unit square
xi = (i + 1) * INV_P_CONST;
yi = (i + 1) * INV_SQ_P_CONST; // Add seed function of vertices
xi += seed;
yi += seed;
xi = std::fmod(xi, 1.0);
yi = std::fmod(yi, 1.0);
// Map to tirangle using parallelogram method
if ((xi + yi) < 1) {
MathExtra::scale3(xi, ac, point);
MathExtra::scale3(yi, ab, temp);
MathExtra::add3(point, temp, point);
} else {
xi = 1.0 - xi;
yi = 1.0 - yi;
MathExtra::scale3(xi, ac, point);
MathExtra::scale3(yi, ab, temp);
MathExtra::add3(point, temp, point);
}
MathExtra::add3(point, ref, point);
// if atom/molecule is in my subbox, create it
if ((point[0] >= sublo[0]) && (point[0] < subhi[0]) && (point[1] >= sublo[1]) &&
(point[1] < subhi[1]) && (point[2] >= sublo[2]) && (point[2] < subhi[2])) {
atom->avec->create_atom(ntype, point);
int idx = atom->nlocal - 1;
if (atom->molecule_flag) atom->molecule[idx] = molid;
}
}
return nparticles;
}
/* ----------------------------------------------------------------------
add atoms at center of triangulated mesh
------------------------------------------------------------------------- */
@ -990,10 +1085,14 @@ void CreateAtoms::add_mesh(const char *filename)
if (!line || !utils::strmatch(line, "^ *endfacet"))
throw TokenizerException("Error reading endfacet", "");
// now we have three vertices ... proceed with adding atom in center of triangle
// or splitting recursively into halves as needed to get the desired density
++ntriangle;
atomlocal += add_tricenter(vert, molid);
if (mesh_style == TRICENTER) {
// now we have three vertices ... proceed with adding atom in center of triangle
// or splitting recursively into halves as needed to get the desired density
atomlocal += add_tricenter(vert, molid);
} else if (mesh_style == QUASIRANDOM) {
atomlocal += add_quasirandom(vert, molid);
}
}
} catch (std::exception &e) {
error->all(FLERR, "Error reading triangles from file {}: {}", filename, e.what());