From 9a154e6adbd698b7c7995d3752e7fa69f437e5bd Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Tue, 21 Jul 2026 17:45:32 -0600 Subject: [PATCH 01/12] Delete unittest/granular directory --- unittest/granular/CMakeLists.txt | 132 ----- unittest/granular/test_analytic_models.cpp | 395 --------------- unittest/granular/test_analytic_models.h | 31 -- unittest/granular/test_config.h | 136 ----- unittest/granular/test_config_reader.cpp | 468 ------------------ unittest/granular/test_config_reader.h | 76 --- unittest/granular/test_dem_01.cpp | 39 -- unittest/granular/test_dem_02.cpp | 40 -- unittest/granular/test_dem_03.cpp | 40 -- unittest/granular/test_dem_04.cpp | 40 -- unittest/granular/test_dem_05.cpp | 40 -- unittest/granular/test_dem_06.cpp | 41 -- unittest/granular/test_dem_07.cpp | 41 -- unittest/granular/test_dem_08.cpp | 41 -- unittest/granular/test_dem_09.cpp | 41 -- unittest/granular/test_dem_10.cpp | 42 -- unittest/granular/test_dem_11.cpp | 42 -- unittest/granular/test_dem_common.cpp | 301 ----------- unittest/granular/test_dem_common.h | 27 - unittest/granular/test_main.cpp | 319 ------------ unittest/granular/test_main.h | 58 --- unittest/granular/tests/clump_tetra.mol | 33 -- .../tests/dem01-granular-hooke-3d-si.yaml | 62 --- .../granular/tests/dem01-hooke-2d-lj.yaml | 57 --- .../granular/tests/dem01-hooke-3d-si.yaml | 60 --- .../tests/dem01-hookehistory-3d-si.yaml | 61 --- .../granular/tests/dem02-hooke-2d-lj.yaml | 65 --- .../granular/tests/dem02-hooke-3d-si.yaml | 64 --- .../tests/dem02-hookehistory-3d-si.yaml | 65 --- .../tests/dem02-restitution-3d-si.yaml | 65 --- .../granular/tests/dem03-elastic-3d-si.yaml | 96 ---- .../tests/dem03-granular-hooke-3d-si.yaml | 92 ---- .../granular/tests/dem03-hooke-3d-si.yaml | 88 ---- .../granular/tests/dem03-unequal-3d-si.yaml | 90 ---- .../granular/tests/dem04-granular-3d-si.yaml | 66 --- .../tests/dem04-hookehistory-3d-si.yaml | 64 --- .../tests/dem04-hookehistory-mu02-3d-si.yaml | 64 --- .../tests/dem04-hookehistory-mu10-3d-si.yaml | 64 --- .../granular/tests/dem04-opencyl-rim-3d.yaml | 63 --- .../tests/dem05-granular-oblique-3d.yaml | 60 --- .../dem05-granular-oblique-steep-3d.yaml | 60 --- .../tests/dem05-hertz-oblique-3d.yaml | 54 -- .../tests/dem05-hookehistory-grazing-3d.yaml | 58 --- .../tests/dem05-hookehistory-oblique-3d.yaml | 54 -- .../tests/dem05-mindlin-grazing-3d.yaml | 60 --- .../dem05-mindlin-rescale-grazing-3d.yaml | 60 --- .../tests/dem05-mindlin-steep-3d.yaml | 60 --- .../tests/dem05-superellipsoid-3d.yaml | 69 --- .../granular/tests/dem06-nonlinear-3d.yaml | 54 -- .../tests/dem06-viscous-linear-3d.yaml | 53 -- .../granular/tests/dem07-rolling-3d-si.yaml | 66 --- .../tests/dem07-rolling-mu005-3d-si.yaml | 66 --- .../tests/dem07-rolling-mu02-3d-si.yaml | 66 --- .../tests/dem08-dmt-twosphere-3d.yaml | 57 --- .../granular/tests/dem08-dmt-wall-3d.yaml | 53 -- .../tests/dem08-jkr-twosphere-3d.yaml | 72 --- unittest/granular/tests/dem09-normal-3d.yaml | 68 --- unittest/granular/tests/dem09-shear-3d.yaml | 74 --- .../tests/dem09-spin-identical-3d.yaml | 72 --- .../granular/tests/dem09-spin-unequal-3d.yaml | 68 --- .../granular/tests/dem09-spin-wall-3d.yaml | 56 --- .../granular/tests/dem10-aor-spheres-3d.yaml | 59 --- unittest/granular/tests/dem10-clump-3d.yaml | 99 ---- .../tests/dem10-settle-spheres-3d.yaml | 195 -------- .../tests/dem11-hertz-twosphere-3d.yaml | 68 --- .../granular/tests/dem11-hertz-wall-3d.yaml | 58 --- unittest/granular/tests/test_dem01_hooke.yaml | 23 - 67 files changed, 5471 deletions(-) delete mode 100644 unittest/granular/CMakeLists.txt delete mode 100644 unittest/granular/test_analytic_models.cpp delete mode 100644 unittest/granular/test_analytic_models.h delete mode 100644 unittest/granular/test_config.h delete mode 100644 unittest/granular/test_config_reader.cpp delete mode 100644 unittest/granular/test_config_reader.h delete mode 100644 unittest/granular/test_dem_01.cpp delete mode 100644 unittest/granular/test_dem_02.cpp delete mode 100644 unittest/granular/test_dem_03.cpp delete mode 100644 unittest/granular/test_dem_04.cpp delete mode 100644 unittest/granular/test_dem_05.cpp delete mode 100644 unittest/granular/test_dem_06.cpp delete mode 100644 unittest/granular/test_dem_07.cpp delete mode 100644 unittest/granular/test_dem_08.cpp delete mode 100644 unittest/granular/test_dem_09.cpp delete mode 100644 unittest/granular/test_dem_10.cpp delete mode 100644 unittest/granular/test_dem_11.cpp delete mode 100644 unittest/granular/test_dem_common.cpp delete mode 100644 unittest/granular/test_dem_common.h delete mode 100644 unittest/granular/test_main.cpp delete mode 100644 unittest/granular/test_main.h delete mode 100644 unittest/granular/tests/clump_tetra.mol delete mode 100644 unittest/granular/tests/dem01-granular-hooke-3d-si.yaml delete mode 100644 unittest/granular/tests/dem01-hooke-2d-lj.yaml delete mode 100644 unittest/granular/tests/dem01-hooke-3d-si.yaml delete mode 100644 unittest/granular/tests/dem01-hookehistory-3d-si.yaml delete mode 100644 unittest/granular/tests/dem02-hooke-2d-lj.yaml delete mode 100644 unittest/granular/tests/dem02-hooke-3d-si.yaml delete mode 100644 unittest/granular/tests/dem02-hookehistory-3d-si.yaml delete mode 100644 unittest/granular/tests/dem02-restitution-3d-si.yaml delete mode 100644 unittest/granular/tests/dem03-elastic-3d-si.yaml delete mode 100644 unittest/granular/tests/dem03-granular-hooke-3d-si.yaml delete mode 100644 unittest/granular/tests/dem03-hooke-3d-si.yaml delete mode 100644 unittest/granular/tests/dem03-unequal-3d-si.yaml delete mode 100644 unittest/granular/tests/dem04-granular-3d-si.yaml delete mode 100644 unittest/granular/tests/dem04-hookehistory-3d-si.yaml delete mode 100644 unittest/granular/tests/dem04-hookehistory-mu02-3d-si.yaml delete mode 100644 unittest/granular/tests/dem04-hookehistory-mu10-3d-si.yaml delete mode 100644 unittest/granular/tests/dem04-opencyl-rim-3d.yaml delete mode 100644 unittest/granular/tests/dem05-granular-oblique-3d.yaml delete mode 100644 unittest/granular/tests/dem05-granular-oblique-steep-3d.yaml delete mode 100644 unittest/granular/tests/dem05-hertz-oblique-3d.yaml delete mode 100644 unittest/granular/tests/dem05-hookehistory-grazing-3d.yaml delete mode 100644 unittest/granular/tests/dem05-hookehistory-oblique-3d.yaml delete mode 100644 unittest/granular/tests/dem05-mindlin-grazing-3d.yaml delete mode 100644 unittest/granular/tests/dem05-mindlin-rescale-grazing-3d.yaml delete mode 100644 unittest/granular/tests/dem05-mindlin-steep-3d.yaml delete mode 100644 unittest/granular/tests/dem05-superellipsoid-3d.yaml delete mode 100644 unittest/granular/tests/dem06-nonlinear-3d.yaml delete mode 100644 unittest/granular/tests/dem06-viscous-linear-3d.yaml delete mode 100644 unittest/granular/tests/dem07-rolling-3d-si.yaml delete mode 100644 unittest/granular/tests/dem07-rolling-mu005-3d-si.yaml delete mode 100644 unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml delete mode 100644 unittest/granular/tests/dem08-dmt-twosphere-3d.yaml delete mode 100644 unittest/granular/tests/dem08-dmt-wall-3d.yaml delete mode 100644 unittest/granular/tests/dem08-jkr-twosphere-3d.yaml delete mode 100644 unittest/granular/tests/dem09-normal-3d.yaml delete mode 100644 unittest/granular/tests/dem09-shear-3d.yaml delete mode 100644 unittest/granular/tests/dem09-spin-identical-3d.yaml delete mode 100644 unittest/granular/tests/dem09-spin-unequal-3d.yaml delete mode 100644 unittest/granular/tests/dem09-spin-wall-3d.yaml delete mode 100644 unittest/granular/tests/dem10-aor-spheres-3d.yaml delete mode 100644 unittest/granular/tests/dem10-clump-3d.yaml delete mode 100644 unittest/granular/tests/dem10-settle-spheres-3d.yaml delete mode 100644 unittest/granular/tests/dem11-hertz-twosphere-3d.yaml delete mode 100644 unittest/granular/tests/dem11-hertz-wall-3d.yaml delete mode 100644 unittest/granular/tests/test_dem01_hooke.yaml diff --git a/unittest/granular/CMakeLists.txt b/unittest/granular/CMakeLists.txt deleted file mode 100644 index 22617584060..00000000000 --- a/unittest/granular/CMakeLists.txt +++ /dev/null @@ -1,132 +0,0 @@ -# -*- CMake -*- file for tests using DEM / granular models - -function(extract_tags out yaml_file) - file(STRINGS ${yaml_file} TAGS_LINE REGEX "^tags:") - string(REPLACE "tags:" "" TAGS_LINE "${TAGS_LINE}") - string(REGEX MATCHALL "[^, \t\r\n]+" TAGS "${TAGS_LINE}") - set(${out} "${TAGS}" PARENT_SCOPE) -endfunction() - -# build support library -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - string(REPLACE "/" "\\\\" TEST_INPUT_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/tests") -else() - set(TEST_INPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/tests) -endif() -add_library(granular_tests STATIC - ../error_stats.cpp - ../yaml_writer.cpp - test_config_reader.cpp - test_analytic_models.cpp - test_dem_common.cpp - test_main.cpp) -if(YAML_FOUND) - target_compile_definitions(granular_tests PRIVATE TEST_INPUT_FOLDER=${TEST_INPUT_FOLDER}) -else() - # we always use static linkage with local compiled libyaml - target_compile_definitions(granular_tests PRIVATE TEST_INPUT_FOLDER=${TEST_INPUT_FOLDER} YAML_DECLARE_STATIC) -endif() -target_include_directories(granular_tests PRIVATE "${LAMMPS_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/..") -target_link_libraries(granular_tests PUBLIC GTest::GMock Yaml::Yaml lammps) - -# propagate sanitizer options to test tools -if(ENABLE_SANITIZER AND (NOT (ENABLE_SANITIZER STREQUAL "none"))) - target_compile_options(granular_tests PUBLIC -fsanitize=${ENABLE_SANITIZER}) - target_link_options(granular_tests PUBLIC -fsanitize=${ENABLE_SANITIZER}) -endif() - -# prepare environment for testers -if(WIN32) - set(GRANULAR_TEST_ENVIRONMENT PYTHONPATH=${TEST_INPUT_FOLDER}) -else() - set(GRANULAR_TEST_ENVIRONMENT PYTHONPATH=${TEST_INPUT_FOLDER}:${LAMMPS_PYTHON_DIR}:$ENV{PYTHONPATH}) -endif() -list(APPEND GRANULAR_TEST_ENVIRONMENT "PYTHONUNBUFFERED=1") -list(APPEND GRANULAR_TEST_ENVIRONMENT "PYTHONDONTWRITEBYTECODE=1") -list(APPEND GRANULAR_TEST_ENVIRONMENT "OMP_PROC_BIND=false") -list(APPEND GRANULAR_TEST_ENVIRONMENT "OMP_NUM_THREADS=4") -list(APPEND GRANULAR_TEST_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") -get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(BUILD_IS_MULTI_CONFIG) - set(LAMMPS_LIB_PATH ${CMAKE_BINARY_DIR}/$) -else() - set(LAMMPS_LIB_PATH ${CMAKE_BINARY_DIR}) -endif() -if(APPLE) - list(APPEND GRANULAR_TEST_ENVIRONMENT "DYLD_LIBRARY_PATH=${LAMMPS_LIB_PATH}:$ENV{DYLD_LIBRARY_PATH}") -elseif(WIN32) - list(APPEND GRANULAR_TEST_ENVIRONMENT "LAMMPSDLLPATH=${LAMMPS_LIB_PATH}") -else() - list(APPEND GRANULAR_TEST_ENVIRONMENT "LD_LIBRARY_PATH=${LAMMPS_LIB_PATH}:$ENV{LD_LIBRARY_PATH}") -endif() - -# helper to register all YAML files matching a prefix with a given test driver -function(register_dem_tests driver prefix label) - file(GLOB DEM_TESTS LIST_DIRECTORIES false CONFIGURE_DEPENDS ${TEST_INPUT_FOLDER}/${prefix}-*.yaml) - foreach(TEST ${DEM_TESTS}) - string(REGEX REPLACE "^.*${prefix}-(.*)\.yaml" "${label}:\\1" TNAME ${TEST}) - extract_tags(TEST_TAGS ${TEST}) - list(FIND TEST_TAGS "no${CMAKE_SYSTEM_NAME}" _SKIPME) - if(_SKIPME GREATER_EQUAL 0) - continue() - endif() - add_test(NAME ${TNAME} COMMAND ${driver} ${TEST}) - set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "${GRANULAR_TEST_ENVIRONMENT}") - set_tests_properties(${TNAME} PROPERTIES LABELS "${TEST_TAGS}") - endforeach() -endfunction() - -# DEM-01: freely falling particle bouncing off a wall -add_executable(test_dem_01 test_dem_01.cpp) -target_link_libraries(test_dem_01 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_01 dem01 DEM01) - -# DEM-02: repeated bouncing particle (convergence to the hard-sphere limit) -add_executable(test_dem_02 test_dem_02.cpp) -target_link_libraries(test_dem_02 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_02 dem02 DEM02) - -# DEM-03: two stacked particles in continuous compression between two walls -add_executable(test_dem_03 test_dem_03.cpp) -target_link_libraries(test_dem_03 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_03 dem03 DEM03) - -# DEM-04: sphere sliding then rolling without slipping on a rough surface -add_executable(test_dem_04 test_dem_04.cpp) -target_link_libraries(test_dem_04 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_04 dem04 DEM04) - -# DEM-05: oblique collision of a sphere with a flat wall -add_executable(test_dem_05 test_dem_05.cpp) -target_link_libraries(test_dem_05 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_05 dem05 DEM05) - -# DEM-06: single particle settling to terminal velocity under fluid drag -add_executable(test_dem_06 test_dem_06.cpp) -target_link_libraries(test_dem_06 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_06 dem06 DEM06) - -# DEM-07: spinning sphere damped by rolling resistance (rolling sds) -add_executable(test_dem_07 test_dem_07.cpp) -target_link_libraries(test_dem_07 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_07 dem07 DEM07) - -# DEM-08: cohesive/adhesive contact (DMT/JKR pull-off force) -add_executable(test_dem_08 test_dem_08.cpp) -target_link_libraries(test_dem_08 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_08 dem08 DEM08) - -# DEM-09: particle-particle head-on and oblique (shear) collisions -add_executable(test_dem_09 test_dem_09.cpp) -target_link_libraries(test_dem_09 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_09 dem09 DEM09) - -# DEM-10: bulk angle of repose and multi-sphere rigid clumps -add_executable(test_dem_10 test_dem_10.cpp) -target_link_libraries(test_dem_10 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_10 dem10 DEM10) - -# DEM-11: elastic Hertzian normal impact (peak contact mechanics) -add_executable(test_dem_11 test_dem_11.cpp) -target_link_libraries(test_dem_11 PRIVATE lammps granular_tests) -register_dem_tests(test_dem_11 dem11 DEM11) diff --git a/unittest/granular/test_analytic_models.cpp b/unittest/granular/test_analytic_models.cpp deleted file mode 100644 index 7f4fba5bb3e..00000000000 --- a/unittest/granular/test_analytic_models.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// Closed-form ("analytic") reference solutions for the DEM verification -// tests. Each model is selected by name from the YAML 'analytic_model' key -// and reads its parameters from the 'variables' block, so new functional -// forms can be exercised purely from YAML once implemented here. - -#include "test_analytic_models.h" - -#include "atom.h" -#include "lammps.h" -#include "math_const.h" -#include "update.h" - -#include "gtest/gtest.h" - -#include -#include -#include - -using namespace LAMMPS_NS; - -// parse the variables block into name->double (non-numeric values are skipped) -static std::map as_doubles(const TestConfig &cfg) -{ - std::map vars; - for (const auto &v : cfg.variables) { - try { - vars[v.first] = std::stod(v.second); - } catch (std::exception &) { - // ignore non-numeric variables (e.g. NULL placeholders) - } - } - return vars; -} - -// local index of the atom with the given tag, or -1 if not present on this rank -static int find_local(LAMMPS *lmp, tagint id) -{ - for (int i = 0; i < lmp->atom->nlocal; ++i) - if (lmp->atom->tag[i] == id) return i; - return -1; -} - -// relative-error comparison consistent with the regression epsilon checks -static void expect_rel(double expected, double actual, double tol, const std::string &what) -{ - const double denom = std::max(std::fabs(expected), 1.0e-300); - const double relerr = std::fabs(actual - expected) / denom; - EXPECT_LE(relerr, tol) << what << ": expected " << expected << " got " << actual; -} - -static double var_or(const std::map &vars, const std::string &name, - double fallback) -{ - auto it = vars.find(name); - return (it != vars.end()) ? it->second : fallback; -} - -void check_analytic_model(const TestConfig &cfg, LAMMPS *lmp, int segment) -{ - if (!cfg.analytic_enable) return; - - int target = cfg.analytic_segment; - if (target < 0) target = (int) cfg.run_segments.size() - 1; - if (segment != target) return; - - const auto vars = as_doubles(cfg); - const double t = (double) lmp->update->ntimestep * lmp->update->dt; - - if (cfg.analytic_model == "freefall") { - // ballistic motion of atom 1 before any contact: z = z0 - g t^2/2, vz = -g t. - // velocity-Verlet integrates constant acceleration exactly, so this is tight. - const double g = var_or(vars, "grav", 0.0); - const double z0 = var_or(vars, "z0", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "freefall: atom with tag 1 not found"; - expect_rel(z0 - 0.5 * g * t * t, lmp->atom->x[i][2], cfg.analytic_tol, "freefall z"); - expect_rel(-g * t, lmp->atom->v[i][2], cfg.analytic_tol, "freefall vz"); - } else if (cfg.analytic_model == "bounce_height") { - // hard-sphere limit: the apex (center) height after the k-th bounce is - // h_k = r + e^(2k) (h0 - r). - // Evaluated at a free-flight segment via energy conservation, - // apex = z + vz^2/(2g), so the segment need not end exactly at the apex. - // The match is approximate (soft-sphere, finite stiffness) -> loose tol. - const double g = var_or(vars, "grav", 0.0); - const double e = var_or(vars, "restitution", var_or(vars, "en", 1.0)); - const double r = var_or(vars, "radius", 0.0); - const double h0 = var_or(vars, "h0", 0.0); - const double k = var_or(vars, "bounce_k", 1.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "bounce_height: atom with tag 1 not found"; - const double z = lmp->atom->x[i][2]; - const double vz = lmp->atom->v[i][2]; - const double apex = z + vz * vz / (2.0 * g); - expect_rel(r + std::pow(e, 2.0 * k) * (h0 - r), apex, cfg.analytic_tol, "bounce_height apex"); - } else if (cfg.analytic_model == "stack_energy") { - // Two particles (tags 1 lower, 2 upper) stacked between a floor (ylo) - // and ceiling (yhi). For the elastic (e=1) linear-spring case the total - // mechanical energy KE + gravitational PE + contact spring PE is - // conserved; compare it to the initial value (particles start at rest). - // Masses and radii are read from the live simulation so the comparison - // does not depend on reproducing LAMMPS' mass formula. - const double g = var_or(vars, "grav", 0.0); - const double kn = var_or(vars, "knorm", 0.0); - const double ylo = var_or(vars, "ylo", 0.0); - const double yhi = var_or(vars, "yhi", 0.0); - const double y1_0 = var_or(vars, "y1", 0.0); - const double y2_0 = var_or(vars, "y2", 0.0); - const int i1 = find_local(lmp, 1); - const int i2 = find_local(lmp, 2); - ASSERT_GE(i1, 0) << "stack_energy: atom with tag 1 not found"; - ASSERT_GE(i2, 0) << "stack_energy: atom with tag 2 not found"; - const double m1 = lmp->atom->rmass[i1]; - const double m2 = lmp->atom->rmass[i2]; - const double r1 = lmp->atom->radius[i1]; - const double r2 = lmp->atom->radius[i2]; - - // linear-spring contact PE from the three possible overlaps: - // lower particle vs floor, the pair, upper particle vs ceiling - auto spring_pe = [&](double ya, double yb) { - const double df = std::max(0.0, r1 - (ya - ylo)); - const double dc = std::max(0.0, (yb + r2) - yhi); - const double dpp = std::max(0.0, (r1 + r2) - (yb - ya)); - return 0.5 * kn * (df * df + dc * dc + dpp * dpp); - }; - - const double e0 = (m1 * g * y1_0 + m2 * g * y2_0) + spring_pe(y1_0, y2_0); - const double ya = lmp->atom->x[i1][1]; - const double yb = lmp->atom->x[i2][1]; - const double va = lmp->atom->v[i1][1]; - const double vb = lmp->atom->v[i2][1]; - const double ec = 0.5 * m1 * va * va + 0.5 * m2 * vb * vb + (m1 * g * ya + m2 * g * yb) + - spring_pe(ya, yb); - expect_rel(e0, ec, cfg.analytic_tol, "stack_energy total energy"); - } else if (cfg.analytic_model == "slip_cessation") { - // sphere (tag 1) launched along +x with no spin on a rough floor (normal +z): - // kinetic friction decelerates u and spins it up about +y until the no-slip - // condition u = omega_y r is reached. Thereafter u = 5 u0/7 and omega_y = u/r. - // Evaluate at a segment past the slip-cessation time t_s = 2 u0 / (7 mu g). - const double u0 = var_or(vars, "u0", 0.0); - const double r = var_or(vars, "radius", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "slip_cessation: atom with tag 1 not found"; - const double u_final = 5.0 * u0 / 7.0; - expect_rel(u_final, lmp->atom->v[i][0], cfg.analytic_tol, "slip_cessation vx"); - expect_rel(u_final / r, lmp->atom->omega[i][1], cfg.analytic_tol, "slip_cessation omega_y"); - } else if (cfg.analytic_model == "oblique_impact") { - // grazing impact of sphere (tag 1) on a wall with normal +z, in the - // gross-sliding regime (tangential velocity never reverses during - // contact). With approach velocity (vx_in, 0, -vz_in) and no spin: - // vz_out = en vz_in, vx_out = vx_in - mu(1+en) vz_in, - // omega_y_out = (5/2) mu (1+en) vz_in / r. - // Evaluate at a free-flight segment after the rebound. - const double vx_in = var_or(vars, "vx_in", 0.0); - const double vz_in = var_or(vars, "vz_in", 0.0); - const double en = var_or(vars, "en", 1.0); - const double mu = var_or(vars, "xmu", 0.0); - const double r = var_or(vars, "radius", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "oblique_impact: atom with tag 1 not found"; - const double dvt = mu * (1.0 + en) * vz_in; // tangential velocity decrement - expect_rel(en * vz_in, lmp->atom->v[i][2], cfg.analytic_tol, "oblique_impact vz_out"); - expect_rel(vx_in - dvt, lmp->atom->v[i][0], cfg.analytic_tol, "oblique_impact vx_out"); - expect_rel(2.5 * dvt / r, lmp->atom->omega[i][1], cfg.analytic_tol, "oblique_impact omega_y"); - } else if (cfg.analytic_model == "terminal_velocity_linear") { - // particle (tag 1) falling under gravity g with linear (Stokes) drag - // F = -gamma v reaches terminal speed v_term = m g / gamma. - const double g = var_or(vars, "grav", 0.0); - const double gamma = var_or(vars, "gamma", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "terminal_velocity_linear: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - expect_rel(m * g / gamma, -lmp->atom->v[i][2], cfg.analytic_tol, - "terminal_velocity_linear"); - } else if (cfg.analytic_model == "terminal_velocity_schiller_naumann") { - // particle (tag 1) falling under gravity g with Schiller-Naumann drag - // (quiescent gas): terminal speed solves m g = 1/2 Cd rho_g pi r^2 v^2. - const double g = var_or(vars, "grav", 0.0); - const double rho = var_or(vars, "rho_gas", 0.0); - const double mu = var_or(vars, "mu_gas", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "terminal_velocity_schiller_naumann: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - const double r = lmp->atom->radius[i]; - const double area = MathConst::MY_PI * r * r; - const double mg = m * g; - auto drag = [&](double v) { - if (v <= 0.0) return 0.0; - const double re = rho * v * (2.0 * r) / mu; - const double cd = (24.0 / re) * (1.0 + 0.15 * std::pow(re, 0.687)); - return 0.5 * cd * rho * area * v * v; - }; - // bracket then bisect for the terminal speed (drag is monotone in v) - double vlo = 0.0, vhi = 1.0; - int guard = 0; - while ((drag(vhi) < mg) && (guard++ < 200)) vhi *= 2.0; - for (int it = 0; it < 100; ++it) { - const double vm = 0.5 * (vlo + vhi); - if (drag(vm) < mg) - vlo = vm; - else - vhi = vm; - } - expect_rel(0.5 * (vlo + vhi), -lmp->atom->v[i][2], cfg.analytic_tol, - "terminal_velocity_schiller_naumann"); - } else if (cfg.analytic_model == "energy_dissipation") { - // For a frictional collision with no external forces (no gravity) the - // total mechanical (translational + rotational) kinetic energy of the - // sphere (tag 1) must not increase. This guards against the - // grazing-impact energy-injection bug of the classic tangential model. - // Initial state: velocity (vx_in, 0, -vz_in) with no spin; sphere moment - // of inertia I = (2/5) m r^2. analytic_tol is the (small) fractional - // excess over the initial energy that is tolerated. - const double vx_in = var_or(vars, "vx_in", 0.0); - const double vz_in = var_or(vars, "vz_in", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "energy_dissipation: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - const double r = lmp->atom->radius[i]; - const double *v = lmp->atom->v[i]; - const double *w = lmp->atom->omega[i]; - const double e_init = 0.5 * m * (vx_in * vx_in + vz_in * vz_in); - const double ke_tr = 0.5 * m * (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); - const double ke_rot = 0.5 * (0.4 * m * r * r) * (w[0] * w[0] + w[1] * w[1] + w[2] * w[2]); - const double e_final = ke_tr + ke_rot; - EXPECT_LE(e_final, e_init * (1.0 + cfg.analytic_tol)) - << "energy_dissipation: final energy " << e_final << " exceeds initial " << e_init; - } else if (cfg.analytic_model == "rolling_decay") { - // sphere (tag 1) spinning about +y on a flat wall, damped only by the - // rolling-resistance torque M = mu_r R N (N = m g). In the gross-rolling - // (Coulomb-capped) regime the spin decays linearly: - // omega_y(t) = omega0 - (5 mu_r g)/(2 R) t. - const double g = var_or(vars, "grav", 0.0); - const double mur = var_or(vars, "mur", 0.0); - const double omega0 = var_or(vars, "omega0", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "rolling_decay: atom with tag 1 not found"; - const double r = lmp->atom->radius[i]; - expect_rel(omega0 - (5.0 * mur * g) / (2.0 * r) * t, lmp->atom->omega[i][1], cfg.analytic_tol, - "rolling_decay omega_y"); - } else if (cfg.analytic_model == "pulloff_dmt") { - // DMT cohesive contact held at (near-)zero overlap: the normal force on - // particle (tag 1) has magnitude equal to the pull-off force - // F_pull = 4 pi gamma R_eff - // since the Hertzian part ~0 at delta~0. gamma = variable 'coh', - // R_eff = variable 'reff' (= R for a wall, R/2 for two equal spheres). - const double coh = var_or(vars, "coh", 0.0); - const double reff = var_or(vars, "reff", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "pulloff_dmt: atom with tag 1 not found"; - const double *f = lmp->atom->f[i]; - const double fmag = std::sqrt(f[0] * f[0] + f[1] * f[1] + f[2] * f[2]); - expect_rel(4.0 * MathConst::MY_PI * coh * reff, fmag, cfg.analytic_tol, "pulloff_dmt force"); - } else if (cfg.analytic_model == "collision_restitution") { - // head-on collision of two equal spheres (tags 1,2) moving along x at - // +/- vin: the total x-momentum stays ~0 and the relative normal speed - // reverses with the coefficient of restitution e: - // -(v1x - v2x)/(2 vin) = e. - const double en = var_or(vars, "en", 1.0); - const double vin = var_or(vars, "vin", 0.0); - const int i1 = find_local(lmp, 1); - const int i2 = find_local(lmp, 2); - ASSERT_GE(i1, 0) << "collision_restitution: atom with tag 1 not found"; - ASSERT_GE(i2, 0) << "collision_restitution: atom with tag 2 not found"; - const double m1 = lmp->atom->rmass[i1]; - const double m2 = lmp->atom->rmass[i2]; - const double v1 = lmp->atom->v[i1][0]; - const double v2 = lmp->atom->v[i2][0]; - EXPECT_LE(std::fabs(m1 * v1 + m2 * v2), cfg.analytic_tol * (m1 + m2) * vin) - << "collision_restitution: total x-momentum not conserved"; - expect_rel(en, -(v1 - v2) / (2.0 * vin), cfg.analytic_tol, "collision_restitution e"); - } else if (cfg.analytic_model == "angle_of_repose") { - // coarse, statistical estimate of a settled heap's angle of repose: - // atan(H / R), where H is the peak height above the floor and R is the - // largest horizontal distance from the (horizontal) centroid. Asserted - // to lie within a band [aor_lo, aor_hi] degrees (variables). - const double floor = var_or(vars, "floor", 0.0); - const double lo = var_or(vars, "aor_lo", 0.0); - const double hi = var_or(vars, "aor_hi", 90.0); - double **x = lmp->atom->x; - const int nlocal = lmp->atom->nlocal; - ASSERT_GT(nlocal, 0) << "angle_of_repose: no atoms"; - double xc = 0.0, yc = 0.0, zmax = -1.0e300; - for (int k = 0; k < nlocal; ++k) { - xc += x[k][0]; - yc += x[k][1]; - if (x[k][2] > zmax) zmax = x[k][2]; - } - xc /= nlocal; - yc /= nlocal; - double rmax = 0.0; - for (int k = 0; k < nlocal; ++k) { - const double dx = x[k][0] - xc, dy = x[k][1] - yc; - const double rr = std::sqrt(dx * dx + dy * dy); - if (rr > rmax) rmax = rr; - } - const double angle = - (rmax > 0.0) ? std::atan((zmax - floor) / rmax) * 180.0 / MathConst::MY_PI : 90.0; - EXPECT_GE(angle, lo) << "angle_of_repose " << angle << " deg is below the band"; - EXPECT_LE(angle, hi) << "angle_of_repose " << angle << " deg is above the band"; - } else if (cfg.analytic_model == "hertz_normal_impact") { - // Elastic Hertzian normal impact at peak compression (Chung & Ooi 2011, - // Tests 1 & 2). This segment must be timed to land at peak compression, - // where the relative normal velocity is ~0 and all relative kinetic - // energy is stored as Hertzian elastic potential energy. For a contact - // force F = K delta^{3/2}, that PE is (2/5) K delta^{5/2} = (2/5) F delta, - // so (1/2) mu_red V_rela^2 = (2/5) P_max alpha_max. The 2/5 factor is - // the signature of the 3/2 power law (a linear spring would give 1/2); - // the relation is independent of the stiffness convention. mu_red is - // mred_factor * m (1/2 for two equal spheres, 1 for a sphere on a rigid - // wall) and V_rela is the relative approach speed (2*vin for two spheres, - // vin for a wall) -- both supplied via the variables block. - const double vrela = var_or(vars, "vrela", 0.0); - const double mredf = var_or(vars, "mred_factor", 1.0); - const double floor = var_or(vars, "floor", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "hertz_normal_impact: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - const double mred = mredf * m; - // peak overlap: two-sphere (tags 1,2) or sphere-on-wall (single atom) - double alpha; - if (lmp->atom->nlocal >= 2) { - const int j = find_local(lmp, 2); - ASSERT_GE(j, 0) << "hertz_normal_impact: atom with tag 2 not found"; - const double dx = lmp->atom->x[i][0] - lmp->atom->x[j][0]; - const double dy = lmp->atom->x[i][1] - lmp->atom->x[j][1]; - const double dz = lmp->atom->x[i][2] - lmp->atom->x[j][2]; - alpha = lmp->atom->radius[i] + lmp->atom->radius[j] - - std::sqrt(dx * dx + dy * dy + dz * dz); - } else { - alpha = lmp->atom->radius[i] - (lmp->atom->x[i][2] - floor); - } - ASSERT_GT(alpha, 0.0) << "hertz_normal_impact: atoms not in contact (segment " - "not timed at peak compression?)"; - const double fx = lmp->atom->f[i][0]; - const double fy = lmp->atom->f[i][1]; - const double fz = lmp->atom->f[i][2]; - const double pmax = std::sqrt(fx * fx + fy * fy + fz * fz); - const double ke = 0.5 * mred * vrela * vrela; - const double pe = 0.4 * pmax * alpha; // (2/5) P_max alpha_max - expect_rel(ke, pe, cfg.analytic_tol, "hertz_normal_impact peak energy balance"); - } else if (cfg.analytic_model == "spin_impact") { - // A sphere (tag 1) impacts a much heavier/rigid partner -- a wall or a - // large dense sphere -- approaching normally in -z at speed vin while - // spinning about +y with omega0 (Chung & Ooi 2011, Tests 6 and 8). The - // spin gives a contact-point tangential velocity ~r*omega0 along x; in - // the gross-sliding regime the Coulomb friction impulse mu(1+en) vin - // (per unit mass) acts throughout contact, so for the spinning sphere - // vz_out = en vin (rebound), - // vx_out = mu (1+en) vin, - // omega_y_out = omega0 - (5/2) mu (1+en) vin / r. - // Evaluate at a free-flight segment after rebound (needs omega0 large - // enough that the contact never sticks). - const double vin = var_or(vars, "vin", 0.0); - const double w0 = var_or(vars, "omega0", 0.0); - const double en = var_or(vars, "en", 1.0); - const double mu = var_or(vars, "xmu", 0.0); - const double r = var_or(vars, "radius", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "spin_impact: atom with tag 1 not found"; - const double dvt = mu * (1.0 + en) * vin; - expect_rel(en * vin, lmp->atom->v[i][2], cfg.analytic_tol, "spin_impact vz_out"); - expect_rel(dvt, lmp->atom->v[i][0], cfg.analytic_tol, "spin_impact vx_out"); - expect_rel(w0 - 2.5 * dvt / r, lmp->atom->omega[i][1], cfg.analytic_tol, - "spin_impact omega_y"); - } else if (cfg.analytic_model == "spin_no_friction") { - // Two identical spheres (tags 1,2) collide head-on along z while spinning - // about y with equal and opposite omega0, arranged so the relative - // tangential velocity at the contact point is zero (Chung & Ooi 2011, - // Test 7). No tangential force should be generated: each sphere's spin - // is preserved and it gains no tangential (x,y) velocity. This guards - // against a model spuriously creating friction from spin alone. - const double w0 = var_or(vars, "omega0", 0.0); - const double tol = cfg.analytic_tol; - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "spin_no_friction: atom with tag 1 not found"; - expect_rel(w0, lmp->atom->omega[i][1], tol, "spin_no_friction omega_y preserved"); - EXPECT_LE(std::fabs(lmp->atom->v[i][0]), tol) << "spin_no_friction: spurious vx"; - EXPECT_LE(std::fabs(lmp->atom->v[i][1]), tol) << "spin_no_friction: spurious vy"; - } else { - ADD_FAILURE() << "unknown analytic_model: '" << cfg.analytic_model << "'"; - } -} diff --git a/unittest/granular/test_analytic_models.h b/unittest/granular/test_analytic_models.h deleted file mode 100644 index 1bf6267b22b..00000000000 --- a/unittest/granular/test_analytic_models.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -#ifndef TEST_ANALYTIC_MODELS_H -#define TEST_ANALYTIC_MODELS_H - -#include "test_config.h" - -namespace LAMMPS_NS { -class LAMMPS; -} - -// Evaluate the closed-form ("analytic") model selected in the YAML config -// after run segment `segment` has completed. Does nothing unless -// cfg.analytic_enable is set and `segment` matches cfg.analytic_segment -// (a negative analytic_segment means "the last segment"). Parameters are -// taken from the cfg.variables block; the relevant per-atom state is read -// from the live LAMMPS instance and compared with cfg.analytic_tol. -void check_analytic_model(const TestConfig &cfg, LAMMPS_NS::LAMMPS *lmp, int segment); - -#endif diff --git a/unittest/granular/test_config.h b/unittest/granular/test_config.h deleted file mode 100644 index 48068d5e1e2..00000000000 --- a/unittest/granular/test_config.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -#ifndef TEST_CONFIG_H -#define TEST_CONFIG_H - -#include -#include -#include -#include -#include - -struct coord_t { - double x, y, z; -}; - -struct stress_t { - double xx, yy, zz, xy, xz, yz; -}; - -class TestConfig { -public: - std::string lammps_version; - std::string date_generated; - std::string basename; - double epsilon; - std::set skip_tests; - std::vector> prerequisites; - std::vector pre_commands; - std::vector post_commands; - std::vector tags; - std::string input_file; - std::string pair_style; - std::string bond_style; - std::string angle_style; - std::string dihedral_style; - std::string improper_style; - std::string kspace_style; - std::vector pair_coeff; - std::vector bond_coeff; - std::vector angle_coeff; - std::vector dihedral_coeff; - std::vector improper_coeff; - std::vector equilibrium; - std::vector> extract; - // granular/DEM specific: ${var} substitution and multi-segment runs - std::vector> variables; - std::vector run_segments; - // optional analytic (closed-form) verification - bool analytic_enable; - std::string analytic_model; - double analytic_tol; - int analytic_segment; - // when true, record/compare only the analytic check (no per-atom regression). - // used for chaotic bulk tests (e.g. angle of repose) whose trajectories are not - // bit-reproducible across newton on/off or platforms -- only the bulk analytic - // observable is robust. The generator then omits the run_pos/run_vel/... blocks. - bool analytic_only; - int natoms; - double init_energy; - double run_energy; - double init_vdwl; - double run_vdwl; - double init_coul; - double run_coul; - stress_t init_stress; - stress_t run_stress; - double global_scalar; - std::vector global_vector; - std::vector init_forces; - std::vector run_forces; - // per-segment captured state, indexed [segment][tag] - std::vector> seg_pos; - std::vector> seg_vel; - std::vector> seg_torque; - std::vector> seg_omega; - std::vector> seg_angmom; - - TestConfig() : - lammps_version(""), date_generated(""), basename(""), epsilon(1.0e-14), input_file(""), - pair_style("zero"), bond_style("zero"), angle_style("zero"), dihedral_style("zero"), - improper_style("zero"), kspace_style("none"), analytic_enable(false), analytic_model(""), - analytic_tol(1.0e-2), analytic_segment(-1), analytic_only(false), natoms(0), init_energy(0), - run_energy(0), - init_vdwl(0), run_vdwl(0), init_coul(0), run_coul(0), init_stress({0, 0, 0, 0, 0, 0}), - run_stress({0, 0, 0, 0, 0, 0}), global_scalar(0) - { - skip_tests.clear(); - prerequisites.clear(); - pre_commands.clear(); - post_commands.clear(); - pair_coeff.clear(); - bond_coeff.clear(); - angle_coeff.clear(); - dihedral_coeff.clear(); - improper_coeff.clear(); - extract.clear(); - variables.clear(); - run_segments.clear(); - init_forces.clear(); - run_forces.clear(); - seg_pos.clear(); - seg_vel.clear(); - seg_torque.clear(); - seg_omega.clear(); - seg_angmom.clear(); - global_vector.clear(); - } - TestConfig(const TestConfig &) = delete; - TestConfig &operator=(const TestConfig &) = delete; - - [[nodiscard]] std::string tags_line() const - { - if (tags.size() > 0) { - std::stringstream line; - line << tags[0]; - for (size_t i = 1; i < tags.size(); i++) { - line << ", " << tags[i]; - } - return line.str(); - } - return "generated"; - } -}; - -#endif diff --git a/unittest/granular/test_config_reader.cpp b/unittest/granular/test_config_reader.cpp deleted file mode 100644 index 9a730f9c7d9..00000000000 --- a/unittest/granular/test_config_reader.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/* ---------------------------------------------------------------------- - 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 "test_config_reader.h" -#include "test_config.h" -#include "utils.h" -#include "yaml.h" - -#include - -#include -#include -#include -#include -#include -#include - -using LAMMPS_NS::utils::split_words; -using LAMMPS_NS::utils::trim; - -TestConfigReader::TestConfigReader(TestConfig &config) : config(config) -{ - consumers["lammps_version"] = &TestConfigReader::lammps_version; - consumers["tags"] = &TestConfigReader::tags; - consumers["date_generated"] = &TestConfigReader::date_generated; - consumers["epsilon"] = &TestConfigReader::epsilon; - consumers["skip_tests"] = &TestConfigReader::skip_tests; - consumers["prerequisites"] = &TestConfigReader::prerequisites; - consumers["pre_commands"] = &TestConfigReader::pre_commands; - consumers["post_commands"] = &TestConfigReader::post_commands; - consumers["input_file"] = &TestConfigReader::input_file; - consumers["extract"] = &TestConfigReader::extract; - consumers["natoms"] = &TestConfigReader::natoms; - consumers["init_stress"] = &TestConfigReader::init_stress; - consumers["run_stress"] = &TestConfigReader::run_stress; - consumers["init_forces"] = &TestConfigReader::init_forces; - consumers["run_forces"] = &TestConfigReader::run_forces; - consumers["run_pos"] = &TestConfigReader::run_pos; - consumers["run_vel"] = &TestConfigReader::run_vel; - consumers["run_torque"] = &TestConfigReader::run_torque; - consumers["run_omega"] = &TestConfigReader::run_omega; - consumers["run_angmom"] = &TestConfigReader::run_angmom; - - consumers["variables"] = &TestConfigReader::variables; - consumers["run_segments"] = &TestConfigReader::run_segments; - consumers["analytic_enable"] = &TestConfigReader::analytic_enable; - consumers["analytic_model"] = &TestConfigReader::analytic_model; - consumers["analytic_tol"] = &TestConfigReader::analytic_tol; - consumers["analytic_segment"] = &TestConfigReader::analytic_segment; - consumers["analytic_only"] = &TestConfigReader::analytic_only; - - consumers["pair_style"] = &TestConfigReader::pair_style; - consumers["pair_coeff"] = &TestConfigReader::pair_coeff; - consumers["init_vdwl"] = &TestConfigReader::init_vdwl; - consumers["init_coul"] = &TestConfigReader::init_coul; - consumers["run_vdwl"] = &TestConfigReader::run_vdwl; - consumers["run_coul"] = &TestConfigReader::run_coul; - - consumers["global_scalar"] = &TestConfigReader::global_scalar; - consumers["global_vector"] = &TestConfigReader::global_vector; - - consumers["bond_style"] = &TestConfigReader::bond_style; - consumers["bond_coeff"] = &TestConfigReader::bond_coeff; - consumers["angle_style"] = &TestConfigReader::angle_style; - consumers["angle_coeff"] = &TestConfigReader::angle_coeff; - consumers["dihedral_style"] = &TestConfigReader::dihedral_style; - consumers["dihedral_coeff"] = &TestConfigReader::dihedral_coeff; - consumers["improper_style"] = &TestConfigReader::improper_style; - consumers["improper_coeff"] = &TestConfigReader::improper_coeff; - consumers["init_energy"] = &TestConfigReader::init_energy; - consumers["run_energy"] = &TestConfigReader::run_energy; - consumers["equilibrium"] = &TestConfigReader::equilibrium; -} - -void TestConfigReader::skip_tests(const yaml_event_t &event) -{ - config.skip_tests.clear(); - for (auto &word : split_words((char *)event.data.scalar.value)) - config.skip_tests.insert(word); -} - -void TestConfigReader::prerequisites(const yaml_event_t &event) -{ - config.prerequisites.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string key, value; - - while (true) { - data >> key >> value; - if (data.eof()) break; - config.prerequisites.emplace_back(key, value); - } -} - -void TestConfigReader::pre_commands(const yaml_event_t &event) -{ - config.pre_commands.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.pre_commands.push_back(line); - } -} - -void TestConfigReader::post_commands(const yaml_event_t &event) -{ - config.post_commands.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.post_commands.push_back(line); - } -} - -void TestConfigReader::lammps_version(const yaml_event_t &event) -{ - config.lammps_version = (char *)event.data.scalar.value; -} - -void TestConfigReader::date_generated(const yaml_event_t &event) -{ - config.date_generated = (char *)event.data.scalar.value; -} - -void TestConfigReader::epsilon(const yaml_event_t &event) -{ - config.epsilon = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::input_file(const yaml_event_t &event) -{ - config.input_file = (char *)event.data.scalar.value; -} - -void TestConfigReader::extract(const yaml_event_t &event) -{ - config.extract.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string name; - int value; - while (true) { - data >> name >> value; - if (data.eof()) break; - config.extract.emplace_back(name, value); - } -} - -void TestConfigReader::natoms(const yaml_event_t &event) -{ - config.natoms = atoi((char *)event.data.scalar.value); -} - -void TestConfigReader::init_stress(const yaml_event_t &event) -{ - stress_t stress; - sscanf((char *)event.data.scalar.value, "%lg %lg %lg %lg %lg %lg", &stress.xx, &stress.yy, - &stress.zz, &stress.xy, &stress.xz, &stress.yz); - config.init_stress = stress; -} - -void TestConfigReader::run_stress(const yaml_event_t &event) -{ - stress_t stress; - sscanf((char *)event.data.scalar.value, "%lg %lg %lg %lg %lg %lg", &stress.xx, &stress.yy, - &stress.zz, &stress.xy, &stress.xz, &stress.yz); - config.run_stress = stress; -} - -void TestConfigReader::init_forces(const yaml_event_t &event) -{ - config.init_forces.clear(); - config.init_forces.resize(config.natoms + 1); - std::stringstream data((const char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - int tag = 0; - coord_t xyz; - sscanf(line.c_str(), "%d %lg %lg %lg", &tag, &xyz.x, &xyz.y, &xyz.z); - config.init_forces[tag] = xyz; - } -} - -void TestConfigReader::run_forces(const yaml_event_t &event) -{ - config.run_forces.clear(); - config.run_forces.resize(config.natoms + 1); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - int tag; - coord_t xyz; - sscanf(line.c_str(), "%d %lg %lg %lg", &tag, &xyz.x, &xyz.y, &xyz.z); - config.run_forces[tag] = xyz; - } -} - -// parse a multi-segment per-atom block. Each line is "segment tag x y z"; -// rows are routed into target[segment][tag], growing the storage as needed. -static void parse_segment_block(std::vector> &target, const char *value) -{ - target.clear(); - std::stringstream data(value); - std::string line; - - while (std::getline(data, line, '\n')) { - int seg = 0, tag = 0; - coord_t xyz{0.0, 0.0, 0.0}; - if (sscanf(line.c_str(), "%d %d %lg %lg %lg", &seg, &tag, &xyz.x, &xyz.y, &xyz.z) != 5) - continue; - if ((seg < 0) || (tag < 0)) continue; - if ((int)target.size() <= seg) target.resize(seg + 1); - if ((int)target[seg].size() <= tag) target[seg].resize(tag + 1); - target[seg][tag] = xyz; - } -} - -void TestConfigReader::run_pos(const yaml_event_t &event) -{ - parse_segment_block(config.seg_pos, (const char *)event.data.scalar.value); -} - -void TestConfigReader::run_vel(const yaml_event_t &event) -{ - parse_segment_block(config.seg_vel, (const char *)event.data.scalar.value); -} - -void TestConfigReader::run_torque(const yaml_event_t &event) -{ - parse_segment_block(config.seg_torque, (const char *)event.data.scalar.value); -} - -void TestConfigReader::run_omega(const yaml_event_t &event) -{ - parse_segment_block(config.seg_omega, (const char *)event.data.scalar.value); -} - -void TestConfigReader::run_angmom(const yaml_event_t &event) -{ - parse_segment_block(config.seg_angmom, (const char *)event.data.scalar.value); -} - -void TestConfigReader::variables(const yaml_event_t &event) -{ - config.variables.clear(); - std::stringstream data((const char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - std::stringstream parts(line); - std::string name, value; - parts >> name; - if (name.empty()) continue; - // the value is the remainder of the line (may contain spaces) - std::getline(parts, value); - value = trim(value); - config.variables.emplace_back(name, value); - } -} - -void TestConfigReader::run_segments(const yaml_event_t &event) -{ - config.run_segments.clear(); - std::stringstream data((const char *)event.data.scalar.value); - std::string word; - - while (data >> word) { - try { - config.run_segments.push_back(std::stoi(word)); - } catch (std::exception &) { - // ignore non-integer tokens - } - } -} - -void TestConfigReader::analytic_enable(const yaml_event_t &event) -{ - const std::string value = trim((const char *)event.data.scalar.value); - config.analytic_enable = - (value == "yes") || (value == "true") || (value == "on") || (value == "1"); -} - -void TestConfigReader::analytic_model(const yaml_event_t &event) -{ - config.analytic_model = trim((const char *)event.data.scalar.value); -} - -void TestConfigReader::analytic_tol(const yaml_event_t &event) -{ - config.analytic_tol = atof((const char *)event.data.scalar.value); -} - -void TestConfigReader::analytic_segment(const yaml_event_t &event) -{ - config.analytic_segment = atoi((const char *)event.data.scalar.value); -} - -void TestConfigReader::analytic_only(const yaml_event_t &event) -{ - const std::string value = trim((const char *)event.data.scalar.value); - config.analytic_only = - (value == "yes") || (value == "true") || (value == "on") || (value == "1"); -} - -void TestConfigReader::pair_style(const yaml_event_t &event) -{ - config.pair_style = (char *)event.data.scalar.value; -} - -void TestConfigReader::pair_coeff(const yaml_event_t &event) -{ - config.pair_coeff.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.pair_coeff.push_back(line); - } -} - -void TestConfigReader::bond_style(const yaml_event_t &event) -{ - config.bond_style = (char *)event.data.scalar.value; -} - -void TestConfigReader::bond_coeff(const yaml_event_t &event) -{ - config.bond_coeff.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.bond_coeff.push_back(line); - } -} - -void TestConfigReader::angle_style(const yaml_event_t &event) -{ - config.angle_style = (char *)event.data.scalar.value; -} - -void TestConfigReader::angle_coeff(const yaml_event_t &event) -{ - config.angle_coeff.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.angle_coeff.push_back(line); - } -} - -void TestConfigReader::dihedral_style(const yaml_event_t &event) -{ - config.dihedral_style = (char *)event.data.scalar.value; -} - -void TestConfigReader::dihedral_coeff(const yaml_event_t &event) -{ - config.dihedral_coeff.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.dihedral_coeff.push_back(line); - } -} - -void TestConfigReader::improper_style(const yaml_event_t &event) -{ - config.improper_style = (char *)event.data.scalar.value; -} - -void TestConfigReader::improper_coeff(const yaml_event_t &event) -{ - config.improper_coeff.clear(); - std::stringstream data((char *)event.data.scalar.value); - std::string line; - - while (std::getline(data, line, '\n')) { - config.improper_coeff.push_back(line); - } -} - -void TestConfigReader::equilibrium(const yaml_event_t &event) -{ - std::stringstream data((char *)event.data.scalar.value); - config.equilibrium.clear(); - double value; - std::size_t num; - data >> num; - for (std::size_t i = 0; i < num; ++i) { - data >> value; - if (data.eof()) break; - config.equilibrium.push_back(value); - } -} - -void TestConfigReader::init_vdwl(const yaml_event_t &event) -{ - config.init_vdwl = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::init_coul(const yaml_event_t &event) -{ - config.init_coul = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::run_vdwl(const yaml_event_t &event) -{ - config.run_vdwl = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::run_coul(const yaml_event_t &event) -{ - config.run_coul = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::init_energy(const yaml_event_t &event) -{ - config.init_energy = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::run_energy(const yaml_event_t &event) -{ - config.run_energy = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::global_scalar(const yaml_event_t &event) -{ - config.global_scalar = atof((char *)event.data.scalar.value); -} - -void TestConfigReader::global_vector(const yaml_event_t &event) -{ - std::stringstream data((char *)event.data.scalar.value); - config.global_vector.clear(); - double value; - std::size_t num; - data >> num; - for (std::size_t i = 0; i < num; ++i) { - data >> value; - config.global_vector.push_back(value); - } -} - -void TestConfigReader::tags(const yaml_event_t &event) -{ - std::stringstream data((char *)event.data.scalar.value); - config.tags.clear(); - for (std::string tag; std::getline(data, tag, ' ');) { - const auto addme = trim(tag); - if (addme.size() > 0) config.tags.push_back(addme); - } -} diff --git a/unittest/granular/test_config_reader.h b/unittest/granular/test_config_reader.h deleted file mode 100644 index c5f04e743c7..00000000000 --- a/unittest/granular/test_config_reader.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -#ifndef TEST_CONFIG_READER_H -#define TEST_CONFIG_READER_H - -#include "test_config.h" -#include "../yaml_reader.h" - -class TestConfigReader : public YamlReader { - TestConfig &config; - -public: - TestConfigReader(TestConfig &config); - TestConfigReader() = delete; - const TestConfigReader &operator=(TestConfig &) = delete; - - void skip_tests(const yaml_event_t &event); - void prerequisites(const yaml_event_t &event); - void pre_commands(const yaml_event_t &event); - void post_commands(const yaml_event_t &event); - void lammps_version(const yaml_event_t &event); - void date_generated(const yaml_event_t &event); - void epsilon(const yaml_event_t &event); - void input_file(const yaml_event_t &event); - void extract(const yaml_event_t &event); - void natoms(const yaml_event_t &event); - void init_stress(const yaml_event_t &event); - void run_stress(const yaml_event_t &event); - void init_forces(const yaml_event_t &event); - void run_forces(const yaml_event_t &event); - void run_pos(const yaml_event_t &event); - void run_vel(const yaml_event_t &event); - void run_torque(const yaml_event_t &event); - void run_omega(const yaml_event_t &event); - void run_angmom(const yaml_event_t &event); - void variables(const yaml_event_t &event); - void run_segments(const yaml_event_t &event); - void analytic_enable(const yaml_event_t &event); - void analytic_model(const yaml_event_t &event); - void analytic_tol(const yaml_event_t &event); - void analytic_segment(const yaml_event_t &event); - void analytic_only(const yaml_event_t &event); - void pair_style(const yaml_event_t &event); - void pair_coeff(const yaml_event_t &event); - void bond_style(const yaml_event_t &event); - void bond_coeff(const yaml_event_t &event); - void angle_style(const yaml_event_t &event); - void angle_coeff(const yaml_event_t &event); - void dihedral_style(const yaml_event_t &event); - void dihedral_coeff(const yaml_event_t &event); - void improper_style(const yaml_event_t &event); - void improper_coeff(const yaml_event_t &event); - void equilibrium(const yaml_event_t &event); - void init_vdwl(const yaml_event_t &event); - void init_coul(const yaml_event_t &event); - void run_vdwl(const yaml_event_t &event); - void run_coul(const yaml_event_t &event); - void init_energy(const yaml_event_t &event); - void run_energy(const yaml_event_t &event); - void global_scalar(const yaml_event_t &event); - void global_vector(const yaml_event_t &event); - void tags(const yaml_event_t &event); -}; - -#endif diff --git a/unittest/granular/test_dem_01.cpp b/unittest/granular/test_dem_01.cpp deleted file mode 100644 index 8a7dc9f7fa7..00000000000 --- a/unittest/granular/test_dem_01.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 01: freely falling particle bouncing off a wall. -// Mirrors MFiX-DEM VVUQ case DEM-01. All test logic is shared via -// test_dem_common; the reference systems live in tests/dem01-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem01, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem01, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_02.cpp b/unittest/granular/test_dem_02.cpp deleted file mode 100644 index 4cdc1757abb..00000000000 --- a/unittest/granular/test_dem_02.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 02: a particle bouncing repeatedly off a wall, whose -// successive rebound heights converge to the hard-sphere limit as the spring -// stiffness increases. Mirrors MFiX-DEM VVUQ case DEM-02. All test logic is -// shared via test_dem_common; the reference systems live in tests/dem02-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem02, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem02, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_03.cpp b/unittest/granular/test_dem_03.cpp deleted file mode 100644 index 1646ecdbb16..00000000000 --- a/unittest/granular/test_dem_03.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 03: two particles stacked in a narrow channel between -// two walls, held in continuous (enduring) compression under gravity. Mirrors -// MFiX-DEM VVUQ case DEM-03. All test logic is shared via test_dem_common; -// the reference systems live in tests/dem03-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem03, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem03, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_04.cpp b/unittest/granular/test_dem_04.cpp deleted file mode 100644 index 22a3c63a46e..00000000000 --- a/unittest/granular/test_dem_04.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 04: a sphere launched tangentially on a rough surface, -// where sliding friction spins it up until it rolls without slipping. Mirrors -// MFiX-DEM VVUQ case DEM-04. All test logic is shared via test_dem_common; -// the reference systems live in tests/dem04-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem04, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem04, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_05.cpp b/unittest/granular/test_dem_05.cpp deleted file mode 100644 index 3504b7a6c54..00000000000 --- a/unittest/granular/test_dem_05.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 05: oblique collision of a sphere with a flat wall, -// measuring the rebound velocity and the spin generated by friction. Mirrors -// MFiX-DEM VVUQ case DEM-05. All test logic is shared via test_dem_common; -// the reference systems live in tests/dem05-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem05, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem05, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_06.cpp b/unittest/granular/test_dem_06.cpp deleted file mode 100644 index f09c0a7e0ac..00000000000 --- a/unittest/granular/test_dem_06.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 06: a single particle settling to its terminal -// velocity under gravity and fluid drag. Mirrors MFiX-DEM VVUQ case DEM-06. -// Exercises both fix viscous (linear/Stokes drag) and the new -// fix viscous/nonlinear (Schiller-Naumann drag). All test logic is shared -// via test_dem_common; the reference systems live in tests/dem06-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem06, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem06, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_07.cpp b/unittest/granular/test_dem_07.cpp deleted file mode 100644 index dec7faafb71..00000000000 --- a/unittest/granular/test_dem_07.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 07: a spinning sphere on a frictional surface whose -// rotation is damped by rolling resistance (rolling sds), so its angular -// velocity decays linearly to zero. Inspired by Sim C of Mohajeri, Coetzee & -// Schott, Powder Technology 447 (2024) 120136. All test logic is shared via -// test_dem_common; the reference systems live in tests/dem07-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem07, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem07, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_08.cpp b/unittest/granular/test_dem_08.cpp deleted file mode 100644 index 04dc44429de..00000000000 --- a/unittest/granular/test_dem_08.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 08: cohesive/adhesive contact. LAMMPS has no EEPA -// model (used by Mohajeri, Coetzee & Schott, Powder Technology 447 (2024)), so -// the DMT and JKR cohesive normal models are exercised instead, verifying the -// analytic pull-off force. All test logic is shared via test_dem_common; the -// reference systems live in tests/dem08-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem08, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem08, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_09.cpp b/unittest/granular/test_dem_09.cpp deleted file mode 100644 index cc32dbac602..00000000000 --- a/unittest/granular/test_dem_09.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 09: particle-particle (not wall) collisions -- a -// head-on (normal) and an oblique (shear) collision of two equal spheres. -// Mirrors Sim A and Sim B of Mohajeri, Coetzee & Schott, Powder Technology -// 447 (2024). All test logic is shared via test_dem_common; the reference -// systems live in tests/dem09-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem09, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem09, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_10.cpp b/unittest/granular/test_dem_10.cpp deleted file mode 100644 index 5ba6bd247c4..00000000000 --- a/unittest/granular/test_dem_10.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 10: bulk behaviour -- a small deterministic heap of -// particles settling under gravity (angle of repose) and multi-sphere rigid -// clumps. Inspired by the draw-down test of Mohajeri, Coetzee & Schott, -// Powder Technology 447 (2024) and the angle-of-repose round robin of Saomoto -// et al., Soils and Foundations 63 (2023). All test logic is shared via -// test_dem_common; the reference systems live in tests/dem10-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem10, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem10, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_11.cpp b/unittest/granular/test_dem_11.cpp deleted file mode 100644 index e935fb7d06f..00000000000 --- a/unittest/granular/test_dem_11.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// DEM verification test 11: elastic Hertzian normal impact at the particle -// impact level -- two identical spheres (and a sphere on a rigid wall) colliding -// head-on with restitution 1, verifying the Hertzian peak contact mechanics -// against the closed-form solution (Chung & Ooi, Granular Matter 13:643-656, -// 2011, Tests 1 and 2). All test logic is shared via test_dem_common; the -// reference systems live in tests/dem11-*.yaml. - -#include "test_dem_common.h" -#include "test_main.h" - -#include "info.h" - -#include "gtest/gtest.h" - -using namespace LAMMPS_NS; - -TEST(Dem11, newton_on) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(true, "newton on"); -} - -TEST(Dem11, newton_off) -{ - if (!Info::has_package("GRANULAR")) GTEST_SKIP(); - if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); - run_dem_trajectory_test(false, "newton off"); -} diff --git a/unittest/granular/test_dem_common.cpp b/unittest/granular/test_dem_common.cpp deleted file mode 100644 index 000d8a3ca14..00000000000 --- a/unittest/granular/test_dem_common.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* ---------------------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -// Shared implementation for the DEM verification test drivers -// (test_dem_01 ... test_dem_11). Every driver builds its system entirely -// from the YAML file: a 'variables' block provides ${var} substitution, -// 'pre_commands' create the geometry, 'pair_style'/'pair_coeff' set the -// contact model, and 'post_commands' add the integrator, gravity and walls. -// The trajectory is run in segments ('run_segments') and per-atom positions, -// velocities, torques and angular velocities are compared against the -// recorded reference after each segment, together with any analytic model -// selected in the YAML. Driver-specific behaviour lives in the YAML files -// and in test_analytic_models.cpp, so the drivers themselves only differ in -// the GoogleTest suite name. - -#include "test_dem_common.h" - -#include "test_analytic_models.h" -#include "test_config.h" -#include "test_main.h" -#include "yaml_writer.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -#include "atom.h" -#include "force.h" -#include "info.h" -#include "input.h" - -#include "fmt/format.h" - -#include -#include -#include -#include - -using ::testing::HasSubstr; -using ::testing::StartsWith; - -using namespace LAMMPS_NS; - -static void cleanup_lammps(LAMMPS *&lmp, const TestConfig &cfg) -{ - (void) cfg; - delete lmp; - lmp = nullptr; -} - -static LAMMPS *init_lammps(LAMMPS::argv &args, const TestConfig &cfg, const bool newton) -{ - LAMMPS *lmp = new LAMMPS(args, MPI_COMM_WORLD); - - // check if prerequisite styles are available - Info *info = new Info(lmp); - int nfail = 0; - for (const auto &prerequisite : cfg.prerequisites) { - if (!info->has_style(prerequisite.first, prerequisite.second)) ++nfail; - } - delete info; - if (nfail > 0) { - cleanup_lammps(lmp, cfg); - return nullptr; - } - - // utility lambda to improve readability - auto command = [&](const std::string &line) { - lmp->input->one(line); - }; - - // newton must be set before the simulation box is created in pre_commands - command(newton ? "newton on" : "newton off"); - command("variable input_dir index " + INPUT_FOLDER); - - // user-defined variables enable ${var} substitution in all command strings - for (const auto &var : cfg.variables) - command("variable " + var.first + " index " + var.second); - - // build the system geometry (units, atom_style, region, create_atoms, set, ...) - for (const auto &pre_command : cfg.pre_commands) - command(pre_command); - - // contact model - command("pair_style " + cfg.pair_style); - for (const auto &pair_coeff : cfg.pair_coeff) - command("pair_coeff " + pair_coeff); - - // integrator, gravity, walls, ... - for (const auto &post_command : cfg.post_commands) - command(post_command); - - command("run 0 post no"); - return lmp; -} - -// run all segments and compare per-atom state against the reference after each -static void run_and_check(LAMMPS *lmp, const TestConfig &cfg, double epsilon, - const std::string &label) -{ - auto command = [&](const std::string &line) { - lmp->input->one(line); - }; - - const bool has_torque = lmp->atom->torque_flag; - const bool has_omega = lmp->atom->omega_flag; - const bool has_angmom = lmp->atom->angmom_flag; - - for (std::size_t i = 0; i < cfg.run_segments.size(); ++i) { - command("run " + std::to_string(cfg.run_segments[i]) + " post no"); - const std::string tag = label + ", seg " + std::to_string(i); - - if (i < cfg.seg_pos.size()) - EXPECT_POSITIONS("run_pos (" + tag + ")", lmp->atom, cfg.seg_pos[i], epsilon); - if (i < cfg.seg_vel.size()) - EXPECT_VELOCITIES("run_vel (" + tag + ")", lmp->atom, cfg.seg_vel[i], epsilon); - if (has_torque && (i < cfg.seg_torque.size())) - EXPECT_TORQUES("run_torque (" + tag + ")", lmp->atom, cfg.seg_torque[i], epsilon); - if (has_omega && (i < cfg.seg_omega.size())) - EXPECT_OMEGA("run_omega (" + tag + ")", lmp->atom, cfg.seg_omega[i], epsilon); - if (has_angmom && (i < cfg.seg_angmom.size())) - EXPECT_ANGMOM("run_angmom (" + tag + ")", lmp->atom, cfg.seg_angmom[i], epsilon); - - check_analytic_model(cfg, lmp, (int) i); - } -} - -// re-generate yaml file with current settings. - -void generate_yaml_file(const char *outfile, const TestConfig &config) -{ - LAMMPS::argv args = {"DEM", "-log", "none", "-echo", "screen", "-nocite"}; - LAMMPS *lmp = nullptr; - try { - lmp = init_lammps(args, config, true); - } catch (std::exception &e) { - FAIL() << e.what(); - } - if (!lmp) { - std::cerr << "One or more prerequisite styles are not available " - "in this LAMMPS configuration:\n"; - for (auto prerequisite : config.prerequisites) - std::cerr << prerequisite.first << "_style " << prerequisite.second << "\n"; - return; - } - - const int natoms = lmp->atom->natoms; - YamlWriter writer(outfile); - - // write yaml header - write_yaml_header(&writer, &test_config, lmp->version); - - // natoms - writer.emit("natoms", natoms); - - // variables block (echo back verbatim) - std::string block; - for (const auto &var : config.variables) - block += var.first + " " + var.second + "\n"; - writer.emit_block("variables", block); - - // pair style and coefficients - writer.emit("pair_style", config.pair_style); - block.clear(); - for (const auto &pair_coeff : config.pair_coeff) - block += pair_coeff + "\n"; - writer.emit_block("pair_coeff", block); - - // run segments - block.clear(); - for (std::size_t i = 0; i < config.run_segments.size(); ++i) { - if (i) block += " "; - block += std::to_string(config.run_segments[i]); - } - writer.emit_block("run_segments", block); - - // optional analytic check flags (echo back if enabled) - if (config.analytic_enable) { - writer.emit("analytic_enable", std::string("yes")); - writer.emit("analytic_model", config.analytic_model); - writer.emit("analytic_tol", config.analytic_tol); - writer.emit("analytic_segment", (long) config.analytic_segment); - if (config.analytic_only) writer.emit("analytic_only", std::string("yes")); - } - - auto command = [&](const std::string &line) { - lmp->input->one(line); - }; - - // For analytic-only (chaotic bulk) tests -- e.g. angle of repose -- the - // trajectory is not bit-reproducible across newton on/off or platforms, so - // we record no per-atom reference. Only the bulk analytic observable is - // robust; it is checked live during the test (check_analytic_model). We - // still execute the run segments so the reference reflects a completed run. - if (config.analytic_only) { - for (std::size_t i = 0; i < config.run_segments.size(); ++i) - command("run " + std::to_string(config.run_segments[i]) + " post no"); - cleanup_lammps(lmp, config); - return; - } - - const bool has_torque = lmp->atom->torque_flag; - const bool has_omega = lmp->atom->omega_flag; - const bool has_angmom = lmp->atom->angmom_flag; - std::string pos_block, vel_block, torque_block, omega_block, angmom_block; - - // iterate over local atoms by tag; granular/atomic systems have no atom map. - // rows are keyed by (segment, tag), so the emission order is irrelevant. - for (std::size_t i = 0; i < config.run_segments.size(); ++i) { - command("run " + std::to_string(config.run_segments[i]) + " post no"); - auto *x = lmp->atom->x; - auto *v = lmp->atom->v; - auto *t = lmp->atom->torque; - auto *w = lmp->atom->omega; - auto *angmom = lmp->atom->angmom; - tagint *tag = lmp->atom->tag; - const int local = lmp->atom->nlocal; - for (int j = 0; j < local; ++j) { - const tagint id = tag[j]; - pos_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, x[j][0], - x[j][1], x[j][2]); - vel_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, v[j][0], - v[j][1], v[j][2]); - if (has_torque) - torque_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, - t[j][0], t[j][1], t[j][2]); - if (has_omega) - omega_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, - w[j][0], w[j][1], w[j][2]); - if (has_angmom) - angmom_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, - angmom[j][0], angmom[j][1], angmom[j][2]); - } - } - writer.emit_block("run_pos", pos_block); - writer.emit_block("run_vel", vel_block); - if (has_torque) writer.emit_block("run_torque", torque_block); - if (has_omega) writer.emit_block("run_omega", omega_block); - if (has_angmom) writer.emit_block("run_angmom", angmom_block); - - cleanup_lammps(lmp, config); -} - -void run_dem_trajectory_test(bool newton, const std::string &label) -{ - LAMMPS::argv args = {"DEM", "-log", "none", "-echo", "screen", "-nocite"}; - - ::testing::internal::CaptureStdout(); - LAMMPS *lmp = nullptr; - try { - lmp = init_lammps(args, test_config, newton); - } catch (std::exception &e) { - std::string output = ::testing::internal::GetCapturedStdout(); - if (verbose) std::cout << output; - FAIL() << e.what(); - } - std::string output = ::testing::internal::GetCapturedStdout(); - if (verbose) std::cout << output; - - if (!lmp) { - std::cerr << "One or more prerequisite styles are not available " - "in this LAMMPS configuration:\n"; - for (auto &prerequisite : test_config.prerequisites) - std::cerr << prerequisite.first << "_style " << prerequisite.second << "\n"; - GTEST_SKIP(); - } - - EXPECT_THAT(output, StartsWith("LAMMPS (")); - EXPECT_THAT(output, HasSubstr("Loop time")); - - // abort if running in parallel and not all atoms are local - const int nlocal = lmp->atom->nlocal; - ASSERT_EQ(lmp->atom->natoms, nlocal); - - // when requesting newton off, only compare if the pair style honored it - if (!newton && (lmp->force->newton_pair != 0)) { - if (!verbose) ::testing::internal::CaptureStdout(); - cleanup_lammps(lmp, test_config); - if (!verbose) ::testing::internal::GetCapturedStdout(); - GTEST_SKIP() << "pair style forces newton pair on"; - } - - double epsilon = test_config.epsilon; - - if (!verbose) ::testing::internal::CaptureStdout(); - run_and_check(lmp, test_config, epsilon, label); - if (!verbose) ::testing::internal::GetCapturedStdout(); - - if (!verbose) ::testing::internal::CaptureStdout(); - cleanup_lammps(lmp, test_config); - if (!verbose) ::testing::internal::GetCapturedStdout(); -} diff --git a/unittest/granular/test_dem_common.h b/unittest/granular/test_dem_common.h deleted file mode 100644 index e1f0ae34c55..00000000000 --- a/unittest/granular/test_dem_common.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -#ifndef TEST_DEM_COMMON_H -#define TEST_DEM_COMMON_H - -#include - -// Shared trajectory-comparison body for all DEM test drivers. Builds a -// LAMMPS instance from the global test_config (newton on or off), runs the -// configured 'run_segments' and compares per-atom positions, velocities, -// torques and angular velocities -- plus any enabled analytic model -- -// against the recorded reference. The per-driver TEST() fixtures only set -// up the package/skip guards and then call this with the newton flag. -void run_dem_trajectory_test(bool newton, const std::string &label); - -#endif diff --git a/unittest/granular/test_main.cpp b/unittest/granular/test_main.cpp deleted file mode 100644 index e41f0fc847d..00000000000 --- a/unittest/granular/test_main.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* ---------------------------------------------------------------------- - 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 "test_main.h" - -#include "atom.h" -#include "error_stats.h" -#include "pointers.h" -#include "test_config.h" -#include "test_config_reader.h" -#include "yaml_writer.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -#include -#include -#include -#include -#include -#include - -using LAMMPS_NS::Atom; -using LAMMPS_NS::LAMMPS; -using LAMMPS_NS::tagint; -using LAMMPS_NS::utils::split_words; -using LAMMPS_NS::utils::trim; - -void EXPECT_STRESS(const std::string &name, double *stress, const stress_t &expected_stress, - double epsilon) -{ - SCOPED_TRACE("EXPECT_STRESS: " + name); - ErrorStats stats; - EXPECT_FP_LE_WITH_EPS(stress[0], expected_stress.xx, epsilon); - EXPECT_FP_LE_WITH_EPS(stress[1], expected_stress.yy, epsilon); - EXPECT_FP_LE_WITH_EPS(stress[2], expected_stress.zz, epsilon); - EXPECT_FP_LE_WITH_EPS(stress[3], expected_stress.xy, epsilon); - EXPECT_FP_LE_WITH_EPS(stress[4], expected_stress.xz, epsilon); - EXPECT_FP_LE_WITH_EPS(stress[5], expected_stress.yz, epsilon); - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -void EXPECT_FORCES(const std::string &name, Atom *atom, const std::vector &f_ref, - double epsilon) -{ - SCOPED_TRACE("EXPECT_FORCES: " + name); - double **f = atom->f; - tagint *tag = atom->tag; - const int nlocal = atom->nlocal; - ASSERT_EQ(nlocal + 1, f_ref.size()); - ErrorStats stats; - for (int i = 0; i < nlocal; ++i) { - EXPECT_FP_LE_WITH_EPS(f[i][0], f_ref[tag[i]].x, epsilon); - EXPECT_FP_LE_WITH_EPS(f[i][1], f_ref[tag[i]].y, epsilon); - EXPECT_FP_LE_WITH_EPS(f[i][2], f_ref[tag[i]].z, epsilon); - } - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -void EXPECT_POSITIONS(const std::string &name, Atom *atom, const std::vector &x_ref, - double epsilon) -{ - SCOPED_TRACE("EXPECT_POSITIONS: " + name); - double **x = atom->x; - tagint *tag = atom->tag; - const int nlocal = atom->nlocal; - ASSERT_EQ(nlocal + 1, x_ref.size()); - ErrorStats stats; - for (int i = 0; i < nlocal; ++i) { - EXPECT_FP_LE_WITH_EPS(x[i][0], x_ref[tag[i]].x, epsilon); - EXPECT_FP_LE_WITH_EPS(x[i][1], x_ref[tag[i]].y, epsilon); - EXPECT_FP_LE_WITH_EPS(x[i][2], x_ref[tag[i]].z, epsilon); - } - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -void EXPECT_VELOCITIES(const std::string &name, Atom *atom, const std::vector &v_ref, - double epsilon) -{ - SCOPED_TRACE("EXPECT_VELOCITIES: " + name); - double **v = atom->v; - tagint *tag = atom->tag; - const int nlocal = atom->nlocal; - ASSERT_EQ(nlocal + 1, v_ref.size()); - ErrorStats stats; - for (int i = 0; i < nlocal; ++i) { - EXPECT_FP_LE_WITH_EPS(v[i][0], v_ref[tag[i]].x, epsilon); - EXPECT_FP_LE_WITH_EPS(v[i][1], v_ref[tag[i]].y, epsilon); - EXPECT_FP_LE_WITH_EPS(v[i][2], v_ref[tag[i]].z, epsilon); - } - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -void EXPECT_TORQUES(const std::string &name, Atom *atom, const std::vector &t_ref, - double epsilon) -{ - SCOPED_TRACE("EXPECT_TORQUES: " + name); - double **t = atom->torque; - tagint *tag = atom->tag; - const int nlocal = atom->nlocal; - ASSERT_EQ(nlocal + 1, t_ref.size()); - ErrorStats stats; - for (int i = 0; i < nlocal; ++i) { - EXPECT_FP_LE_WITH_EPS(t[i][0], t_ref[tag[i]].x, epsilon); - EXPECT_FP_LE_WITH_EPS(t[i][1], t_ref[tag[i]].y, epsilon); - EXPECT_FP_LE_WITH_EPS(t[i][2], t_ref[tag[i]].z, epsilon); - } - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -void EXPECT_OMEGA(const std::string &name, Atom *atom, const std::vector &w_ref, - double epsilon) -{ - SCOPED_TRACE("EXPECT_OMEGA: " + name); - double **w = atom->omega; - tagint *tag = atom->tag; - const int nlocal = atom->nlocal; - ASSERT_EQ(nlocal + 1, w_ref.size()); - ErrorStats stats; - for (int i = 0; i < nlocal; ++i) { - EXPECT_FP_LE_WITH_EPS(w[i][0], w_ref[tag[i]].x, epsilon); - EXPECT_FP_LE_WITH_EPS(w[i][1], w_ref[tag[i]].y, epsilon); - EXPECT_FP_LE_WITH_EPS(w[i][2], w_ref[tag[i]].z, epsilon); - } - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -void EXPECT_ANGMOM(const std::string &name, Atom *atom, const std::vector &l_ref, - double epsilon) -{ - SCOPED_TRACE("EXPECT_ANGMOM: " + name); - double **angmom = atom->angmom; - tagint *tag = atom->tag; - const int nlocal = atom->nlocal; - ASSERT_EQ(nlocal + 1, l_ref.size()); - ErrorStats stats; - for (int i = 0; i < nlocal; ++i) { - EXPECT_FP_LE_WITH_EPS(angmom[i][0], l_ref[tag[i]].x, epsilon); - EXPECT_FP_LE_WITH_EPS(angmom[i][1], l_ref[tag[i]].y, epsilon); - EXPECT_FP_LE_WITH_EPS(angmom[i][2], l_ref[tag[i]].z, epsilon); - } - if (print_stats) std::cerr << name << " stats: " << stats << std::endl; -} - -// common read_yaml_file function -bool read_yaml_file(const char *infile, TestConfig &config) -{ - auto reader = TestConfigReader(config); - if (reader.parse_file(infile)) return false; - - config.basename = reader.get_basename(); - return true; -} - -// write out common header items for yaml files -void write_yaml_header(YamlWriter *writer, TestConfig *cfg, const char *version) -{ - // lammps_version - writer->emit("lammps_version", version); - - // tags - writer->emit("tags", cfg->tags_line()); - - // date_generated - std::time_t now = time(nullptr); - std::string block = trim(ctime(&now)); - writer->emit("date_generated", block); - - // epsilon - writer->emit("epsilon", cfg->epsilon); - - // skip tests - block.clear(); - for (const auto &skip : cfg->skip_tests) { - if (block.empty()) - block = skip; - else - block += " " + skip; - } - writer->emit("skip_tests", block); - - // prerequisites - block.clear(); - for (auto &prerequisite : cfg->prerequisites) { - block += prerequisite.first + " " + prerequisite.second + "\n"; - } - writer->emit_block("prerequisites", block); - - // pre_commands - block.clear(); - for (auto &command : cfg->pre_commands) { - block += command + "\n"; - } - writer->emit_block("pre_commands", block); - - // post_commands - block.clear(); - for (auto &command : cfg->post_commands) { - block += command + "\n"; - } - writer->emit_block("post_commands", block); - - // input_file - writer->emit("input_file", cfg->input_file); -} - -// need to be defined in unit test body -extern void generate_yaml_file(const char *, const TestConfig &); - -void usage(std::ostream &out, const char *name) -{ - out << "usage: " << name << " [OPTIONS]\n\n" - << "Available options:\n" - << " -g regenerate yaml file under a new name\n" - << " -d set folder where to find input files\n" - << " -u update the original yaml file\n" - << " -v run tests with verbose output\n" - << " -s run tests with error statistics output\n" - << " -h print this message\n" - << std::endl; -} - -// test configuration settings read from yaml file -TestConfig test_config; - -// whether to print error statistics -bool print_stats = false; - -// whether to print verbose output (i.e. not capturing LAMMPS screen output). -bool verbose = false; - -// location for 'in.*' and 'data.*' files required by tests -#define STRINGIFY(val) XSTR(val) -#define XSTR(val) #val -std::string INPUT_FOLDER = STRINGIFY(TEST_INPUT_FOLDER); - -int main(int argc, char **argv) -{ - MPI_Init(&argc, &argv); - ::testing::InitGoogleMock(&argc, argv); - - if (argc < 2) { - usage(std::cerr, argv[0]); - return 1; - } - - if (!read_yaml_file(argv[1], test_config)) { - std::cerr << "Error parsing yaml file: " << argv[1] << std::endl; - return 2; - } - - // handle arguments passed via environment variable - if (const char *var = getenv("TEST_ARGS")) { - std::vector env = split_words(var); - for (auto arg : env) { - if (arg == "-u") { - generate_yaml_file(argv[1], test_config); - return 0; - } else if (arg == "-s") { - print_stats = true; - } else if (arg == "-v") { - verbose = true; - } - } - } - - int iarg = 2; - while (iarg < argc) { - - if (strcmp(argv[iarg], "-g") == 0) { - if (iarg + 1 < argc) { - generate_yaml_file(argv[iarg + 1], test_config); - MPI_Finalize(); - return 0; - } else { - usage(std::cerr, argv[0]); - MPI_Finalize(); - return 1; - } - } else if (strcmp(argv[iarg], "-u") == 0) { - generate_yaml_file(argv[1], test_config); - MPI_Finalize(); - return 0; - } else if (strcmp(argv[iarg], "-d") == 0) { - if (iarg + 1 < argc) { - INPUT_FOLDER = argv[iarg + 1]; - iarg += 2; - } else { - usage(std::cerr, argv[0]); - MPI_Finalize(); - return 1; - } - } else if (strcmp(argv[iarg], "-s") == 0) { - print_stats = true; - ++iarg; - } else if (strcmp(argv[iarg], "-v") == 0) { - verbose = true; - ++iarg; - } else { - std::cerr << "unknown option: " << argv[iarg] << "\n\n"; - usage(std::cerr, argv[0]); - MPI_Finalize(); - return 1; - } - } - - int rv = RUN_ALL_TESTS(); - MPI_Finalize(); - return rv; -} diff --git a/unittest/granular/test_main.h b/unittest/granular/test_main.h deleted file mode 100644 index b7263e197fa..00000000000 --- a/unittest/granular/test_main.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - 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. -------------------------------------------------------------------------- */ - -#ifndef TEST_MAIN_H -#define TEST_MAIN_H - -#include "pointers.h" - -#include "gtest/gtest.h" -#include "test_config.h" - -#include -#include -#include - -extern TestConfig test_config; -extern bool print_stats; -extern bool verbose; -extern std::string INPUT_FOLDER; - -// convenience method to write out common entries -void write_yaml_header(class YamlWriter *writer, TestConfig *cfg, const char *version); - -#define EXPECT_FP_LE_WITH_EPS(val1, val2, eps) \ - do { \ - const double diff = fabs(val1 - val2); \ - const double div = std::min(fabs(val1), fabs(val2)); \ - const double err = (div == 0.0) ? diff : diff / div; \ - stats.add(err); \ - EXPECT_PRED_FORMAT2(::testing::DoubleLE, err, eps); \ - } while (0); - -void EXPECT_STRESS(const std::string &name, double *stress, const stress_t &expected_stress, - double epsilon); -void EXPECT_FORCES(const std::string &name, LAMMPS_NS::Atom *atom, - const std::vector &f_ref, double epsilon); -void EXPECT_POSITIONS(const std::string &name, LAMMPS_NS::Atom *atom, - const std::vector &x_ref, double epsilon); -void EXPECT_VELOCITIES(const std::string &name, LAMMPS_NS::Atom *atom, - const std::vector &v_ref, double epsilon); -void EXPECT_TORQUES(const std::string &name, LAMMPS_NS::Atom *atom, - const std::vector &t_ref, double epsilon); -void EXPECT_OMEGA(const std::string &name, LAMMPS_NS::Atom *atom, - const std::vector &w_ref, double epsilon); -void EXPECT_ANGMOM(const std::string &name, LAMMPS_NS::Atom *atom, - const std::vector &l_ref, double epsilon); - -#endif diff --git a/unittest/granular/tests/clump_tetra.mol b/unittest/granular/tests/clump_tetra.mol deleted file mode 100644 index 699b8832077..00000000000 --- a/unittest/granular/tests/clump_tetra.mol +++ /dev/null @@ -1,33 +0,0 @@ -# tetrahedral 4-sphere rigid clump for the DEM granular clump test -# regular tetrahedron, edge length 1.0, unit-diameter spheres (adjacent spheres touch); -# per-sphere mass = density 1.0 * (4/3)*pi*(0.5)^3 = 0.5235988 - -4 atoms - -Coords - -1 0.0 0.0 0.0 -2 1.0 0.0 0.0 -3 0.5 0.8660254 0.0 -4 0.5 0.2886751 0.8164966 - -Types - -1 1 -2 1 -3 1 -4 1 - -Diameters - -1 1.0 -2 1.0 -3 1.0 -4 1.0 - -Masses - -1 0.5235988 -2 0.5235988 -3 0.5235988 -4 0.5235988 diff --git a/unittest/granular/tests/dem01-granular-hooke-3d-si.yaml b/unittest/granular/tests/dem01-granular-hooke-3d-si.yaml deleted file mode 100644 index fdb70f3e48a..00000000000 --- a/unittest/granular/tests/dem01-granular-hooke-3d-si.yaml +++ /dev/null @@ -1,62 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 15:51:20 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - en 0.8 - kt 8235.0 - xmu 0.0 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 250 150 300 -analytic_enable: yes -analytic_model: freefall -analytic_tol: 1e-09 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 1.9343750000000071e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.0404597405984767e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 3.0031074554089127e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.4524999999999859e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.1257159049368028e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 -8.1728409506318989e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem01-hooke-2d-lj.yaml b/unittest/granular/tests/dem01-hooke-2d-lj.yaml deleted file mode 100644 index 7f684480b01..00000000000 --- a/unittest/granular/tests/dem01-hooke-2d-lj.yaml +++ /dev/null @@ -1,57 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 15:51:19 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke -pre_commands: ! | - units lj - dimension 2 - boundary f f p - atom_style sphere - region box block -0.5 0.5 0.0 1.0 -0.1 0.1 units box - create_box 1 box - create_atoms 1 single 0.0 ${y0} 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 -1.0 0.0 - fix integr all nve/sphere disc - fix twod all enforce2d - fix ywall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 yplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - gnorm 10.0 - diam 0.2 - dens 2600.0 - grav 9.81 - y0 0.5 -pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 -pair_coeff: ! | - * * -run_segments: ! |- - 250 150 300 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 1.9343750000000071e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 9.8142846897904992e-02 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 9.6957624468093959e-02 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 -2.4524999999999859e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.4883590261689112e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -1.4364636856851367e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem01-hooke-3d-si.yaml b/unittest/granular/tests/dem01-hooke-3d-si.yaml deleted file mode 100644 index 3ce77899162..00000000000 --- a/unittest/granular/tests/dem01-hooke-3d-si.yaml +++ /dev/null @@ -1,60 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 15:51:18 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - gnorm 10.0 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 -pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 -pair_coeff: ! | - * * -run_segments: ! |- - 250 150 300 -analytic_enable: yes -analytic_model: freefall -analytic_tol: 1e-09 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 1.9343750000000071e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 9.8142846897904992e-02 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 9.6957624468093959e-02 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.4524999999999859e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.4883590261689112e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.4364636856851367e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem01-hookehistory-3d-si.yaml b/unittest/granular/tests/dem01-hookehistory-3d-si.yaml deleted file mode 100644 index 51a653f9b02..00000000000 --- a/unittest/granular/tests/dem01-hookehistory-3d-si.yaml +++ /dev/null @@ -1,61 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 15:51:19 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - gnorm 10.0 - xmu 0.5 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 250 150 300 -analytic_enable: yes -analytic_model: freefall -analytic_tol: 1e-09 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 1.9343750000000071e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 9.8142846897904992e-02 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 9.6957624468093959e-02 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.4524999999999859e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.4883590261689112e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.4364636856851367e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem02-hooke-2d-lj.yaml b/unittest/granular/tests/dem02-hooke-2d-lj.yaml deleted file mode 100644 index a2e15bf319a..00000000000 --- a/unittest/granular/tests/dem02-hooke-2d-lj.yaml +++ /dev/null @@ -1,65 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:06:32 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke -pre_commands: ! | - units lj - dimension 2 - boundary f f p - atom_style sphere - region box block -0.5 0.5 0.0 1.0 -0.1 0.1 units box - create_box 1 box - create_atoms 1 single 0.0 ${y0} 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 -1.0 0.0 - fix integr all nve/sphere disc - fix twod all enforce2d - fix ywall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 yplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - gnorm 2.0 - diam 0.2 - dens 2600.0 - grav 9.81 - y0 0.5 -pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 -pair_coeff: ! | - * * -run_segments: ! |- - 286 300 300 300 300 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 9.8790620000001342e-02 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 3.9315623776710512e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.4019147961738940e-01 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 3.3053395303137117e-01 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 5.0092585709258959e-02 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 -2.8023040176776459e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 6.2828413950094575e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -2.3147158604990428e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 5.1675618297202830e-01 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 -1.7498219058701125e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem02-hooke-3d-si.yaml b/unittest/granular/tests/dem02-hooke-3d-si.yaml deleted file mode 100644 index 1f1139d8eaf..00000000000 --- a/unittest/granular/tests/dem02-hooke-3d-si.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:01:22 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - gnorm 2.0 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 -pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 -pair_coeff: ! | - * * -run_segments: ! |- - 286 300 300 300 300 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 9.8790620000001342e-02 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 3.9315623776710512e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 1.4019147961738940e-01 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 3.3053395303137117e-01 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 5.0092585709258959e-02 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.8023040176776459e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 6.2828413950094575e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.3147158604990428e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 5.1675618297202830e-01 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.7498219058701125e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem02-hookehistory-3d-si.yaml b/unittest/granular/tests/dem02-hookehistory-3d-si.yaml deleted file mode 100644 index cf0e95719fc..00000000000 --- a/unittest/granular/tests/dem02-hookehistory-3d-si.yaml +++ /dev/null @@ -1,65 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:06:33 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 0.001 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e4 - gnorm 2.0 - xmu 0.5 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 286 300 300 300 300 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 9.8790620000001342e-02 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 3.9315623776710512e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 1.4019147961738940e-01 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 3.3053395303137117e-01 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 5.0092585709258959e-02 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.8023040176776459e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 6.2828413950094575e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.3147158604990428e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 5.1675618297202830e-01 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.7498219058701125e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem02-restitution-3d-si.yaml b/unittest/granular/tests/dem02-restitution-3d-si.yaml deleted file mode 100644 index c6f0c036ac0..00000000000 --- a/unittest/granular/tests/dem02-restitution-3d-si.yaml +++ /dev/null @@ -1,65 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:05:36 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.1 bin - timestep 2.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - knorm 1.0e6 - en 0.9 - kt 8235.0 - xmu 0.0 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 - radius 0.1 - h0 0.5 - bounce_k 1 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 1300 350 800 -analytic_enable: yes -analytic_model: bounce_height -analytic_tol: 0.015 -analytic_segment: 2 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 1.6842200000001106e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.7959300714534190e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.0202265181015850e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.5505999999998483e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.1749852791550288e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 6.0538527915514628e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem03-elastic-3d-si.yaml b/unittest/granular/tests/dem03-elastic-3d-si.yaml deleted file mode 100644 index 13e28ea28fd..00000000000 --- a/unittest/granular/tests/dem03-elastic-3d-si.yaml +++ /dev/null @@ -1,96 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:25:05 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.005 0.005 -0.001 0.003 -0.005 0.005 units box - create_box 2 box - create_atoms 1 single 0.0 ${y1} 0.0 units box - create_atoms 2 single 0.0 ${y2} 0.0 units box - set type 1 diameter ${diam} density ${dens1} - set type 2 diameter ${diam} density ${dens2} - comm_modify vel yes - neighbor 0.0005 bin - timestep 2.0e-6 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 -1.0 0.0 - fix integr all nve/sphere - fix ywall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution yplane ${ylo} ${yhi} -input_file: -natoms: 2 -variables: ! | - diam 0.001 - dens1 10000.0 - dens2 10000.0 - knorm 1.0e3 - en 1.0 - kt 800.0 - xmu 0.0 - grav 9.81 - ylo 0.0 - yhi 0.0018 - y1 0.00045 - y2 0.00135 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 200 200 200 200 200 -analytic_enable: yes -analytic_model: stack_energy -analytic_tol: 5e-04 -analytic_segment: 4 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 4.1684173029886483e-04 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 1.3831303477676166e-03 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 4.4919993452677758e-04 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 1.3507035560466720e-03 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 4.1825802027107992e-04 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 1.3815735012746196e-03 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 4.4695822989225211e-04 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 1.3528370633113184e-03 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 4.2108853140521607e-04 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 1.3787259677965739e-03 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 6.0382831813026297e-02 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 -5.9409910101324431e-02 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -1.1772563285642577e-01 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 1.1914259797246207e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.7483079908222401e-01 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 -1.7374004998063819e-01 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 -2.2609762372881306e-01 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 2.2626922777377567e-01 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 2.7253050689536862e-01 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 -2.7337133152454407e-01 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem03-granular-hooke-3d-si.yaml b/unittest/granular/tests/dem03-granular-hooke-3d-si.yaml deleted file mode 100644 index 5dce37ae1b9..00000000000 --- a/unittest/granular/tests/dem03-granular-hooke-3d-si.yaml +++ /dev/null @@ -1,92 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:21:33 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.005 0.005 -0.001 0.003 -0.005 0.005 units box - create_box 2 box - create_atoms 1 single 0.0 ${y1} 0.0 units box - create_atoms 2 single 0.0 ${y2} 0.0 units box - set type 1 diameter ${diam} density ${dens1} - set type 2 diameter ${diam} density ${dens2} - comm_modify vel yes - neighbor 0.0005 bin - timestep 2.0e-6 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 -1.0 0.0 - fix integr all nve/sphere - fix ywall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution yplane ${ylo} ${yhi} -input_file: -natoms: 2 -variables: ! | - diam 0.001 - dens1 20000.0 - dens2 10000.0 - knorm 1.0e3 - en 0.9 - kt 800.0 - xmu 0.0 - grav 9.81 - ylo 0.0 - yhi 0.0018 - y1 0.00045 - y2 0.00135 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 200 200 200 200 200 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 4.2750880271217798e-04 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 1.3734203173575415e-03 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 4.2715206575450295e-04 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 1.3662268109844195e-03 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 4.4014238279789215e-04 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 1.3633340934951286e-03 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 4.3312222813520244e-04 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 1.3714096021600378e-03 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 4.2927809294012869e-04 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 1.3634702759875576e-03 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 -1.8728439704170926e-02 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 3.1549487146115240e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 3.6373844571441424e-02 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 -2.4067317240859665e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -5.4960369002835900e-02 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 2.8159785192102209e-02 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 3.0370223149721643e-02 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 8.7370989479275268e-02 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 2.4272767801346431e-02 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 -6.6012830063635633e-02 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem03-hooke-3d-si.yaml b/unittest/granular/tests/dem03-hooke-3d-si.yaml deleted file mode 100644 index a8b480bea01..00000000000 --- a/unittest/granular/tests/dem03-hooke-3d-si.yaml +++ /dev/null @@ -1,88 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:19:10 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.005 0.005 -0.001 0.003 -0.005 0.005 units box - create_box 1 box - create_atoms 1 single 0.0 ${y1} 0.0 units box - create_atoms 1 single 0.0 ${y2} 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.0005 bin - timestep 2.0e-6 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 -1.0 0.0 - fix integr all nve/sphere - fix ywall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 yplane ${ylo} ${yhi} -input_file: -natoms: 2 -variables: ! | - diam 0.001 - dens 10000.0 - knorm 1.0e3 - gnorm 5.0 - grav 9.81 - ylo 0.0 - yhi 0.0018 - y1 0.00045 - y2 0.00135 -pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 -pair_coeff: ! | - * * -run_segments: ! |- - 200 200 200 200 200 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 4.1687420671793478e-04 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 1.3830977848181261e-03 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 4.4913694832445444e-04 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 1.3507665141123094e-03 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 4.1834731207972275e-04 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 1.3814843954145124e-03 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 4.4684922629991178e-04 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 1.3529464724372667e-03 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 4.2120998421449340e-04 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 1.3786049346145681e-03 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 6.0281633633810908e-02 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 -5.9309696025505169e-02 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -1.1729083122580830e-01 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 1.1870496648880484e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.7383820109148707e-01 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 -1.7275067935620653e-01 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 -2.2435859855183826e-01 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 2.2452959487657986e-01 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 2.6988630475923114e-01 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 -2.7072285993549766e-01 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem03-unequal-3d-si.yaml b/unittest/granular/tests/dem03-unequal-3d-si.yaml deleted file mode 100644 index 28b9f3a99d4..00000000000 --- a/unittest/granular/tests/dem03-unequal-3d-si.yaml +++ /dev/null @@ -1,90 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:21:33 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.005 0.005 -0.001 0.003 -0.005 0.005 units box - create_box 2 box - create_atoms 1 single 0.0 ${y1} 0.0 units box - create_atoms 2 single 0.0 ${y2} 0.0 units box - set type 1 diameter ${diam} density ${dens1} - set type 2 diameter ${diam} density ${dens2} - comm_modify vel yes - neighbor 0.0005 bin - timestep 2.0e-6 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 -1.0 0.0 - fix integr all nve/sphere - fix ywall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 yplane ${ylo} ${yhi} -input_file: -natoms: 2 -variables: ! | - diam 0.001 - dens1 20000.0 - dens2 10000.0 - knorm 1.0e3 - gnorm 5.0 - grav 9.81 - ylo 0.0 - yhi 0.0018 - y1 0.00045 - y2 0.00135 -pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 -pair_coeff: ! | - * * -run_segments: ! |- - 200 200 200 200 200 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 4.2564259190155403e-04 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 1.3784504245448229e-03 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 4.2419204241835777e-04 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 1.3676835119071059e-03 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 4.4768918750241992e-04 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 1.3505043382620952e-03 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 4.2886535472112509e-04 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 1.3879033127905253e-03 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 4.2574868806846548e-04 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 1.3580705579185179e-03 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 -5.2592792245950440e-02 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 4.4896523781940878e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.1605339985404901e-01 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 -5.0363078598220956e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -1.2003433195161962e-01 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 1.3728012616841667e-01 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 -3.3707822776607608e-03 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 3.1193281017891328e-01 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 1.7584400185422766e-01 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 -4.7515633024618298e-01 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 3 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 4 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem04-granular-3d-si.yaml b/unittest/granular/tests/dem04-granular-3d-si.yaml deleted file mode 100644 index 2355609eae4..00000000000 --- a/unittest/granular/tests/dem04-granular-3d-si.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:39:30 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p f f - atom_style sphere - region box block -5.0 5.0 -1.0 1.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${u0} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 2857.0 - gt 50.0 - xmu 0.5 - grav 1.0 - u0 1.0 - radius 0.5 - z0 0.49994764 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} damping coeff_restitution -run_segments: ! |- - 2000 2000 3000 -analytic_enable: yes -analytic_model: slip_cessation -analytic_tol: 0.005 -analytic_segment: 2 -run_pos: ! |2 - 0 1 3.6001999998805151e-01 0.0000000000000000e+00 4.9994764011743803e-01 - 1 1 6.5478363567795406e-01 0.0000000000000000e+00 4.9994764012498077e-01 - 2 1 1.0834423236247468e+00 0.0000000000000000e+00 4.9994764012239951e-01 -run_vel: ! |2 - 0 1 8.0005000138420557e-01 0.0000000000000000e+00 -2.5345589839426964e-09 - 1 1 7.1532076566893166e-01 0.0000000000000000e+00 -2.3253258400576456e-10 - 2 1 7.1428655875330471e-01 0.0000000000000000e+00 -2.4852012027712798e-11 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 1.3089970949302940e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 3.2116282128709091e-03 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 2.6202718039662139e-06 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 9.9974999307899148e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.4233961716553385e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.4285672062334340e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem04-hookehistory-3d-si.yaml b/unittest/granular/tests/dem04-hookehistory-3d-si.yaml deleted file mode 100644 index 8e1f87b737d..00000000000 --- a/unittest/granular/tests/dem04-hookehistory-3d-si.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 18:24:06 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units lj - dimension 3 - boundary p f f - atom_style sphere - region box block -5.0 5.0 -1.0 1.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${u0} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - gnorm 10.0 - xmu 0.5 - grav 1.0 - u0 1.0 - radius 0.5 - z0 0.49994764 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 2000 1000 1500 -analytic_enable: yes -analytic_model: slip_cessation -analytic_tol: 0.005 -analytic_segment: 2 -run_pos: ! |2 - 0 1 3.6001999998766032e-01 0.0000000000000000e+00 4.9994764011821508e-01 - 1 1 5.1019159646854051e-01 0.0000000000000000e+00 4.9994764012018406e-01 - 2 1 7.2449285403938413e-01 0.0000000000000000e+00 4.9994764012212656e-01 -run_vel: ! |2 - 0 1 8.0005000121165126e-01 0.0000000000000000e+00 -2.1894600790323674e-09 - 1 1 7.1627101956161254e-01 0.0000000000000000e+00 7.9160543657078750e-10 - 2 1 7.1408828278339231e-01 0.0000000000000000e+00 -1.8055543482175481e-10 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 1.3089970734175041e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -6.6770417936071497e-02 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.0645337090957297e-03 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 9.9974999394174546e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.4186449021919252e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.4295585860830191e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem04-hookehistory-mu02-3d-si.yaml b/unittest/granular/tests/dem04-hookehistory-mu02-3d-si.yaml deleted file mode 100644 index f3fcf573a07..00000000000 --- a/unittest/granular/tests/dem04-hookehistory-mu02-3d-si.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular unstable -date_generated: Fri May 29 18:24:07 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units lj - dimension 3 - boundary p f f - atom_style sphere - region box block -5.0 5.0 -1.0 1.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${u0} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - gnorm 10.0 - xmu 0.2 - grav 1.0 - u0 1.0 - radius 0.5 - z0 0.49994764 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 5000 3000 2000 -analytic_enable: yes -analytic_model: slip_cessation -analytic_tol: 0.005 -analytic_segment: 2 -run_pos: ! |2 - 0 1 9.0002000002244098e-01 0.0000000000000000e+00 4.9994764012162163e-01 - 1 1 1.3469570518343204e+00 0.0000000000000000e+00 4.9994764012242288e-01 - 2 1 1.6326712117809838e+00 0.0000000000000000e+00 4.9994764012243476e-01 -run_vel: ! |2 - 0 1 8.0002000004788232e-01 0.0000000000000000e+00 -5.5866548574272763e-12 - 1 1 7.1460456306198483e-01 0.0000000000000000e+00 5.1633308959063600e-12 - 2 1 7.1428881832023994e-01 0.0000000000000000e+00 -7.1821801507704452e-15 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 5.2359878382119314e-02 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.7575722353025908e-03 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -3.2148536923392229e-04 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 9.9989999976056754e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.4269771846900607e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.4285559083987927e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem04-hookehistory-mu10-3d-si.yaml b/unittest/granular/tests/dem04-hookehistory-mu10-3d-si.yaml deleted file mode 100644 index e7cb51cc821..00000000000 --- a/unittest/granular/tests/dem04-hookehistory-mu10-3d-si.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 18:24:07 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units lj - dimension 3 - boundary p f f - atom_style sphere - region box block -5.0 5.0 -1.0 1.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${u0} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - gnorm 10.0 - xmu 1.0 - grav 1.0 - u0 1.0 - radius 0.5 - z0 0.49994764 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 1000 1000 1500 -analytic_enable: yes -analytic_model: slip_cessation -analytic_tol: 0.005 -analytic_segment: 2 -run_pos: ! |2 - 0 1 1.8001999988915854e-01 0.0000000000000000e+00 4.9994764015760984e-01 - 1 1 3.2648825313140839e-01 0.0000000000000000e+00 4.9994764011821557e-01 - 2 1 5.4079422853874992e-01 0.0000000000000000e+00 4.9994764012526222e-01 -run_vel: ! |2 - 0 1 8.0009999652499675e-01 0.0000000000000000e+00 3.7088475860776442e-09 - 1 1 7.1442951561054957e-01 0.0000000000000000e+00 -2.1894324241942362e-09 - 2 1 7.1417392029987881e-01 0.0000000000000000e+00 3.1368561291478882e-10 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 2.6179920205531310e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -9.4993601987550816e-02 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 5.3165417254795759e-03 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 9.9950001737502192e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.4278524219472684e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.4291303985005972e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem04-opencyl-rim-3d.yaml b/unittest/granular/tests/dem04-opencyl-rim-3d.yaml deleted file mode 100644 index 06e574f94c4..00000000000 --- a/unittest/granular/tests/dem04-opencyl-rim-3d.yaml +++ /dev/null @@ -1,63 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri Jul 3 13:07:49 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: | - atom sphere - pair granular -pre_commands: | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -3.0 3.0 -3.0 3.0 units box - create_box 1 box - create_atoms 1 single 1.45 0.0 0.25 units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx0} 0.0 ${vz0} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: | - region cyl cylinder z 0.0 0.0 ${rad} ${zlo} ${zhi} units box open 3 - fix wreg all wall/gran/region granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} damping coeff_restitution region cyl - fix integr all nve/sphere -input_file: -natoms: 1 -variables: | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 2857.0 - gt 50.0 - xmu 0.5 - rad 1.0 - zlo 0.0 - zhi 2.0 - vx0 -0.43 - vz0 -0.26 -pair_style: granular -pair_coeff: | - * * hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} damping coeff_restitution -run_segments: |- - 600 600 800 -run_pos: |2 - 0 1 1.4649172516992330e+00 0.0000000000000000e+00 2.5590025675929823e-01 - 1 1 1.5133734660423841e+00 0.0000000000000000e+00 2.8047164415352149e-01 - 2 1 1.5779817518332522e+00 0.0000000000000000e+00 3.1323349401248585e-01 -run_vel: |2 - 0 1 4.0380178619273527e-01 0.0000000000000000e+00 2.0476156161839568e-01 - 1 1 4.0380178619273527e-01 0.0000000000000000e+00 2.0476156161839568e-01 - 2 1 4.0380178619273527e-01 0.0000000000000000e+00 2.0476156161839568e-01 -run_torque: |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: |2 - 0 1 0.0000000000000000e+00 1.3665989122173849e-02 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.3665989122173849e-02 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 1.3665989122173849e-02 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-granular-oblique-3d.yaml b/unittest/granular/tests/dem05-granular-oblique-3d.yaml deleted file mode 100644 index e8ffdca7705..00000000000 --- a/unittest/granular/tests/dem05-granular-oblique-3d.yaml +++ /dev/null @@ -1,60 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:45:25 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 2857.0 - xmu 0.3 - vx_in 4.0 - vz_in 1.0 - radius 0.5 - z0 0.55 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 400 400 -analytic_enable: yes -analytic_model: oblique_impact -analytic_tol: 0.005 -analytic_segment: 1 -run_pos: ! |2 - 0 1 3.0902795539247691e-01 0.0000000000000000e+00 5.0654764149609222e-01 - 1 1 5.8331710158354588e-01 0.0000000000000000e+00 5.7864005331889168e-01 -run_vel: ! |2 - 0 1 3.4286143273883534e+00 0.0000000000000000e+00 9.0115514778494654e-01 - 1 1 3.4286143273883534e+00 0.0000000000000000e+00 9.0115514778494654e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 2.8569283630582687e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.8569283630582687e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-granular-oblique-steep-3d.yaml b/unittest/granular/tests/dem05-granular-oblique-steep-3d.yaml deleted file mode 100644 index 12b12a38bcc..00000000000 --- a/unittest/granular/tests/dem05-granular-oblique-steep-3d.yaml +++ /dev/null @@ -1,60 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:45:25 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 2857.0 - xmu 0.3 - vx_in 6.0 - vz_in 1.0 - radius 0.5 - z0 0.55 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 400 400 -analytic_enable: yes -analytic_model: oblique_impact -analytic_tol: 0.005 -analytic_segment: 1 -run_pos: ! |2 - 0 1 4.6902795539247633e-01 0.0000000000000000e+00 5.0654764149609222e-01 - 1 1 9.0331710158355505e-01 0.0000000000000000e+00 5.7864005331889168e-01 -run_vel: ! |2 - 0 1 5.4286143273883489e+00 0.0000000000000000e+00 9.0115514778494654e-01 - 1 1 5.4286143273883489e+00 0.0000000000000000e+00 9.0115514778494654e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 2.8569283630582687e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.8569283630582687e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-hertz-oblique-3d.yaml b/unittest/granular/tests/dem05-hertz-oblique-3d.yaml deleted file mode 100644 index 5316cf32bca..00000000000 --- a/unittest/granular/tests/dem05-hertz-oblique-3d.yaml +++ /dev/null @@ -1,54 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 16:47:21 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hertz/history -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran hertz/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e5 - gnorm 10.0 - xmu 0.3 - vx_in 1.0 - vz_in 1.0 - z0 0.55 -pair_style: gran/hertz/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 400 400 -run_pos: ! |2 - 0 1 4.0000000000000119e-02 0.0000000000000000e+00 5.1000000000000445e-01 - 1 1 7.1039114481321816e-02 0.0000000000000000e+00 5.0143479228817511e-01 -run_vel: ! |2 - 0 1 1.0000000000000000e+00 0.0000000000000000e+00 -1.0000000000000000e+00 - 1 1 4.3229008746243802e-01 0.0000000000000000e+00 9.9321877551794191e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.8385495626877999e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-hookehistory-grazing-3d.yaml b/unittest/granular/tests/dem05-hookehistory-grazing-3d.yaml deleted file mode 100644 index e37d4fdac5b..00000000000 --- a/unittest/granular/tests/dem05-hookehistory-grazing-3d.yaml +++ /dev/null @@ -1,58 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 18:27:20 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-5 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - gnorm 10.0 - xmu 0.5 - vx_in 4.0 - vz_in 1.0 - z0 0.55 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 4000 4000 -analytic_enable: yes -analytic_model: energy_dissipation -analytic_tol: 0.001 -analytic_segment: 1 -run_pos: ! |2 - 0 1 3.0175077594998145e-01 0.0000000000000000e+00 5.0647290772730569e-01 - 1 1 5.4591857348327422e-01 0.0000000000000000e+00 5.7786219665344374e-01 -run_vel: ! |2 - 0 1 3.0520974691666085e+00 0.0000000000000000e+00 8.9236611157415258e-01 - 1 1 3.0520974691666085e+00 0.0000000000000000e+00 8.9236611157415258e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 4.7395126541669219e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 4.7395126541669219e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-hookehistory-oblique-3d.yaml b/unittest/granular/tests/dem05-hookehistory-oblique-3d.yaml deleted file mode 100644 index 53e5e8641fc..00000000000 --- a/unittest/granular/tests/dem05-hookehistory-oblique-3d.yaml +++ /dev/null @@ -1,54 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 18:24:08 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair gran/hooke/history -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - gnorm 10.0 - xmu 0.3 - vx_in 1.0 - vz_in 1.0 - z0 0.55 -pair_style: gran/hooke/history ${knorm} NULL ${gnorm} NULL ${xmu} 1 -pair_coeff: ! | - * * -run_segments: ! |- - 400 400 -run_pos: ! |2 - 0 1 6.9915886195579688e-02 0.0000000000000000e+00 5.0649254641902497e-01 - 1 1 1.0830228471953378e-01 0.0000000000000000e+00 5.7799092670137819e-01 -run_vel: ! |2 - 0 1 4.7982998154942136e-01 0.0000000000000000e+00 8.9372975352958750e-01 - 1 1 4.7982998154942136e-01 0.0000000000000000e+00 8.9372975352958750e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 2.6008500922528892e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.6008500922528892e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-mindlin-grazing-3d.yaml b/unittest/granular/tests/dem05-mindlin-grazing-3d.yaml deleted file mode 100644 index de6d20ad1a8..00000000000 --- a/unittest/granular/tests/dem05-mindlin-grazing-3d.yaml +++ /dev/null @@ -1,60 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:00:25 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - emod 1.0e5 - poisson 0.3 - en 0.9 - xmu 0.3 - vx_in 4.0 - vz_in 1.0 - radius 0.5 - z0 0.55 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 400 400 -analytic_enable: yes -analytic_model: oblique_impact -analytic_tol: 0.01 -analytic_segment: 1 -run_pos: ! |2 - 0 1 3.1172041749065410e-01 0.0000000000000000e+00 4.9759860836448910e-01 - 1 1 5.8602030731393207e-01 0.0000000000000000e+00 5.6960684220551705e-01 -run_vel: ! |2 - 0 1 3.4306826637513415e+00 0.0000000000000000e+00 8.9772445416218305e-01 - 1 1 3.4287244525972307e+00 0.0000000000000000e+00 9.0007006540976098e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 5.4673449251821393e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 2.8465866812432719e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.8563777370138284e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-mindlin-rescale-grazing-3d.yaml b/unittest/granular/tests/dem05-mindlin-rescale-grazing-3d.yaml deleted file mode 100644 index 65ad213578b..00000000000 --- a/unittest/granular/tests/dem05-mindlin-rescale-grazing-3d.yaml +++ /dev/null @@ -1,60 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:02:46 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin_rescale NULL 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - emod 1.0e5 - poisson 0.3 - en 0.9 - xmu 0.3 - vx_in 4.0 - vz_in 1.0 - radius 0.5 - z0 0.55 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} tangential mindlin_rescale NULL 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 400 400 -analytic_enable: yes -analytic_model: oblique_impact -analytic_tol: 0.01 -analytic_segment: 1 -run_pos: ! |2 - 0 1 3.1172041749065410e-01 0.0000000000000000e+00 4.9759860836448910e-01 - 1 1 5.8602033781312823e-01 0.0000000000000000e+00 5.6960684220551705e-01 -run_vel: ! |2 - 0 1 3.4306826637513415e+00 0.0000000000000000e+00 8.9772445416218305e-01 - 1 1 3.4287248466434699e+00 0.0000000000000000e+00 9.0007006540976098e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 5.4673449251821393e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 2.8465866812432719e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.8563757667826315e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-mindlin-steep-3d.yaml b/unittest/granular/tests/dem05-mindlin-steep-3d.yaml deleted file mode 100644 index cb297db7479..00000000000 --- a/unittest/granular/tests/dem05-mindlin-steep-3d.yaml +++ /dev/null @@ -1,60 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:02:47 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -10.0 10.0 -2.0 2.0 -0.5 5.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - emod 1.0e5 - poisson 0.3 - en 0.9 - xmu 0.3 - vx_in 6.0 - vz_in 1.0 - radius 0.5 - z0 0.55 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 400 400 -analytic_enable: yes -analytic_model: oblique_impact -analytic_tol: 0.01 -analytic_segment: 1 -run_pos: ! |2 - 0 1 4.7172041749065485e-01 0.0000000000000000e+00 4.9759860836448910e-01 - 1 1 9.0602030731395800e-01 0.0000000000000000e+00 5.6960684220551705e-01 -run_vel: ! |2 - 0 1 5.4306826637513543e+00 0.0000000000000000e+00 8.9772445416218305e-01 - 1 1 5.4287244525972449e+00 0.0000000000000000e+00 9.0007006540976098e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 5.4673449251821393e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 2.8465866812432719e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 2.8563777370138284e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem05-superellipsoid-3d.yaml b/unittest/granular/tests/dem05-superellipsoid-3d.yaml deleted file mode 100644 index e923ae54349..00000000000 --- a/unittest/granular/tests/dem05-superellipsoid-3d.yaml +++ /dev/null @@ -1,69 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 17:13:26 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom ellipsoid - pair granular/superellipsoid -pre_commands: ! | - units si - dimension 3 - boundary p p p - atom_style ellipsoid superellipsoid - region box block 0.0 20.0 0.0 20.0 0.0 20.0 units box - create_box 1 box - create_atoms 1 single 8.0 10.0 10.0 units box - create_atoms 1 single 12.0 10.5 10.0 units box - set type 1 shape 1.5 1.0 1.0 - set type 1 block 4.0 4.0 - set type 1 mass 1.0 - group moving id 1 - velocity moving set ${vx} 0.0 0.0 - comm_modify vel yes - neighbor 0.5 bin - timestep 0.002 -post_commands: ! | - fix integr all nve/asphere -input_file: -natoms: 2 -variables: ! | - knorm 1000.0 - kt 285.0 - xmu 0.5 - vx 3.0 -pair_style: granular/superellipsoid -pair_coeff: ! | - * * hooke ${knorm} 0.0 tangential linear_history ${kt} 0.0 ${xmu} damping mass_velocity -run_segments: ! |- - 150 150 300 -run_pos: ! |2 - 0 1 8.9000000000000341e+00 1.0000000000000000e+01 1.0000000000000000e+01 - 0 2 1.2000000000000000e+01 1.0500000000000000e+01 1.0000000000000000e+01 - 1 1 9.8000000000000682e+00 1.0000000000000000e+01 1.0000000000000000e+01 - 1 2 1.2000000000000000e+01 1.0500000000000000e+01 1.0000000000000000e+01 - 2 1 1.0720492576829887e+01 9.7985163057660145e+00 1.0000000000000000e+01 - 2 2 1.2879507423170244e+01 1.0701483694233985e+01 1.0000000000000000e+01 -run_vel: ! |2 - 0 1 3.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 3.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 2.9163267014654626e-01 -6.3129594762241270e-01 0.0000000000000000e+00 - 2 2 2.7083673298534547e+00 6.3129594762241270e-01 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_angmom: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.3906948439836406e-01 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 2.3906948439836501e-01 -... diff --git a/unittest/granular/tests/dem06-nonlinear-3d.yaml b/unittest/granular/tests/dem06-nonlinear-3d.yaml deleted file mode 100644 index 2b7ede55210..00000000000 --- a/unittest/granular/tests/dem06-nonlinear-3d.yaml +++ /dev/null @@ -1,54 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 17:01:11 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - fix viscous/nonlinear -pre_commands: ! | - units lj - dimension 3 - boundary p p p - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-3 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix drag all viscous/nonlinear ${rho_gas} ${mu_gas} -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - grav 1.0 - rho_gas 1.0 - mu_gas 0.01 -pair_style: none -pair_coeff: ! "" -run_segments: ! |- - 3000 3000 -analytic_enable: yes -analytic_model: terminal_velocity_schiller_naumann -analytic_tol: 0.003 -analytic_segment: 1 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 1.5809200923214353e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.8140520398950208e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.1101919348314218e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.1380267440674114e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem06-viscous-linear-3d.yaml b/unittest/granular/tests/dem06-viscous-linear-3d.yaml deleted file mode 100644 index 4d275b2b817..00000000000 --- a/unittest/granular/tests/dem06-viscous-linear-3d.yaml +++ /dev/null @@ -1,53 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 17:01:10 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - fix viscous -pre_commands: ! | - units lj - dimension 3 - boundary p p p - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-3 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix drag all viscous ${gamma} -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - grav 1.0 - gamma 1.0 -pair_style: none -pair_coeff: ! "" -run_segments: ! |- - 3000 3000 -analytic_enable: yes -analytic_model: terminal_velocity_linear -analytic_tol: 0.001 -analytic_segment: 1 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.2977873174828856e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.1322983668891478e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -5.2190718319175311e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -5.2359331056476077e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem07-rolling-3d-si.yaml b/unittest/granular/tests/dem07-rolling-3d-si.yaml deleted file mode 100644 index 281843bd156..00000000000 --- a/unittest/granular/tests/dem07-rolling-3d-si.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:05:00 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - set group all omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 5.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} ${gr} ${mur} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.5 - kr 1000.0 - gr 0.0 - mur 0.1 - grav 10.0 - omega0 5.0 - radius 0.5 - z0 0.49947640 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} ${gr} ${mur} damping coeff_restitution -run_segments: ! |- - 400 400 400 -analytic_enable: yes -analytic_model: rolling_decay -analytic_tol: 0.002 -analytic_segment: 1 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122518783e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122440679e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122440157e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 3.6554007748158375e-10 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -8.0570150455366688e-13 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.2779732633888120e-14 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 -2.6179938682164716e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -2.6179938779784406e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -2.6179938779914969e-01 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 4.0012500027402673e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 3.0012500029235105e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 2.0012500029230398e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem07-rolling-mu005-3d-si.yaml b/unittest/granular/tests/dem07-rolling-mu005-3d-si.yaml deleted file mode 100644 index 4e558aaeccb..00000000000 --- a/unittest/granular/tests/dem07-rolling-mu005-3d-si.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:05:46 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - set group all omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 5.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} ${gr} ${mur} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.5 - kr 1000.0 - gr 0.0 - mur 0.05 - grav 10.0 - omega0 5.0 - radius 0.5 - z0 0.49947640 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} ${gr} ${mur} damping coeff_restitution -run_segments: ! |- - 400 400 400 -analytic_enable: yes -analytic_model: rolling_decay -analytic_tol: 0.002 -analytic_segment: 1 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122518783e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122440679e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122440157e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 3.6554007748158375e-10 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -8.0570150455366688e-13 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.2779732633888120e-14 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 -1.3089969341082358e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -1.3089969389892203e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -1.3089969389957484e-01 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 4.5006250013701363e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 4.0006250014617537e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 3.5006250014615818e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml b/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml deleted file mode 100644 index 009d4a15867..00000000000 --- a/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:05:47 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - set group all omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 5.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} ${gr} ${mur} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.5 - kr 1000.0 - gr 0.0 - mur 0.2 - grav 10.0 - omega0 5.0 - radius 0.5 - z0 0.49947640 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} ${gr} ${mur} damping coeff_restitution -run_segments: ! |- - 400 400 400 -analytic_enable: yes -analytic_model: rolling_decay -analytic_tol: 0.002 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122518783e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122440679e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9947640122440157e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 3.6554007748158375e-10 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -8.0570150455366688e-13 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 4.2779732633888120e-14 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 -5.2359877364329432e-01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 -5.2359877559568813e-01 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -4.2926935568635449e-01 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 3.0025000054805515e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.0025000058470344e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 -8.2871219748150218e-02 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem08-dmt-twosphere-3d.yaml b/unittest/granular/tests/dem08-dmt-twosphere-3d.yaml deleted file mode 100644 index 25c38296fbf..00000000000 --- a/unittest/granular/tests/dem08-dmt-twosphere-3d.yaml +++ /dev/null @@ -1,57 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:15:55 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 0.0 units box - create_atoms 1 single ${sep} 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 1.0 - dens 1.0 - emod 1000.0 - ndamp 0.0 - poiss 0.3 - coh 10.0 - reff 0.25 - sep 0.99999 -pair_style: granular -pair_coeff: ! | - * * dmt ${emod} ${ndamp} ${poiss} ${coh} tangential linear_nohistory 0.0 0.0 -run_segments: ! |- - 0 -analytic_enable: yes -analytic_model: pulloff_dmt -analytic_tol: 0.001 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 9.9999000000000005e-01 0.0000000000000000e+00 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem08-dmt-wall-3d.yaml b/unittest/granular/tests/dem08-dmt-wall-3d.yaml deleted file mode 100644 index 690591bc386..00000000000 --- a/unittest/granular/tests/dem08-dmt-wall-3d.yaml +++ /dev/null @@ -1,53 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:13:56 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary p p f - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular dmt ${emod} ${ndamp} ${poiss} ${coh} tangential linear_nohistory 0.0 0.0 zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - emod 1000.0 - ndamp 0.0 - poiss 0.3 - coh 10.0 - reff 0.5 - z0 0.49999 -pair_style: granular -pair_coeff: ! | - * * dmt ${emod} ${ndamp} ${poiss} ${coh} tangential linear_nohistory 0.0 0.0 -run_segments: ! |- - 0 -analytic_enable: yes -analytic_model: pulloff_dmt -analytic_tol: 0.001 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 4.9998999999999999e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem08-jkr-twosphere-3d.yaml b/unittest/granular/tests/dem08-jkr-twosphere-3d.yaml deleted file mode 100644 index 58ffff88dd5..00000000000 --- a/unittest/granular/tests/dem08-jkr-twosphere-3d.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:17:46 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single -0.49 0.0 0.0 units box - create_atoms 1 single 0.49 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - group left id 1 - group right id 2 - velocity left set ${vx} 0.0 0.0 - velocity right set -${vx} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 1.0 - dens 1.0 - emod 1000.0 - ndamp 0.5 - poiss 0.3 - coh 10.0 - vx 0.2 -pair_style: granular -pair_coeff: ! | - * * jkr ${emod} ${ndamp} ${poiss} ${coh} tangential linear_nohistory 0.0 0.0 -run_segments: ! |- - 300 300 300 -run_pos: ! |2 - 0 1 -4.2641676718091220e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 4.2641676718091220e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -3.8512652637383976e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 3.8512652637383976e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 -4.6064450092024889e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 4.6064450092024889e-01 0.0000000000000000e+00 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 1.5047209159976185e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 -1.5047209159976185e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -5.4628895343275052e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 5.4628895343275052e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 -1.2861344465081543e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 1.2861344465081543e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem09-normal-3d.yaml b/unittest/granular/tests/dem09-normal-3d.yaml deleted file mode 100644 index f4306a7ab42..00000000000 --- a/unittest/granular/tests/dem09-normal-3d.yaml +++ /dev/null @@ -1,68 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:23:00 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single -0.6 0.0 0.0 units box - create_atoms 1 single 0.6 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - group left id 1 - group right id 2 - velocity left set ${vin} 0.0 0.0 - velocity right set -${vin} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 8235.0 - xmu 0.0 - vin 1.0 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 600 400 -analytic_enable: yes -analytic_model: collision_restitution -analytic_tol: 0.015 -analytic_segment: 1 -run_pos: ! |2 - 0 1 -5.0353900742137636e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 5.0353900742137636e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -5.7561510662887283e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 5.7561510662887283e-01 0.0000000000000000e+00 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 -9.0095124009353200e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 9.0095124009353200e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -9.0095124009353200e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 9.0095124009353200e-01 0.0000000000000000e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem09-shear-3d.yaml b/unittest/granular/tests/dem09-shear-3d.yaml deleted file mode 100644 index d0a5585b2ea..00000000000 --- a/unittest/granular/tests/dem09-shear-3d.yaml +++ /dev/null @@ -1,74 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:23:01 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single -0.6 -${yoff} 0.0 units box - create_atoms 1 single 0.6 ${yoff} 0.0 units box - set group all diameter ${diam} density ${dens} - group left id 1 - group right id 2 - velocity left set ${vin} 0.0 0.0 - velocity right set -${vin} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 8235.0 - gt 50.0 - xmu 0.5 - vin 1.0 - yoff 0.2 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} damping coeff_restitution -run_segments: ! |- - 800 500 500 -run_pos: ! |2 - 0 1 -4.5721360502337977e-01 -2.0682503598665403e-01 0.0000000000000000e+00 - 0 2 4.5721360502337977e-01 2.0682503598665403e-01 0.0000000000000000e+00 - 1 1 -5.1855655278669244e-01 -2.7155447493780210e-01 0.0000000000000000e+00 - 1 2 5.1855655278669244e-01 2.7155447493780210e-01 0.0000000000000000e+00 - 2 1 -5.7989950055002448e-01 -3.3628391388894091e-01 0.0000000000000000e+00 - 2 2 5.7989950055002448e-01 3.3628391388894091e-01 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 -6.1342947763313160e-01 -6.4729438951150120e-01 0.0000000000000000e+00 - 0 2 6.1342947763313160e-01 6.4729438951150120e-01 0.0000000000000000e+00 - 1 1 -6.1342947763313160e-01 -6.4729438951150120e-01 0.0000000000000000e+00 - 1 2 6.1342947763313160e-01 6.4729438951150120e-01 0.0000000000000000e+00 - 2 1 -6.1342947763313160e-01 -6.4729438951150120e-01 0.0000000000000000e+00 - 2 2 6.1342947763313160e-01 6.4729438951150120e-01 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 3.0920772446785488e-01 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 3.0920772446785488e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 3.0920772446785488e-01 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 3.0920772446785488e-01 - 2 1 0.0000000000000000e+00 0.0000000000000000e+00 3.0920772446785488e-01 - 2 2 0.0000000000000000e+00 0.0000000000000000e+00 3.0920772446785488e-01 -... diff --git a/unittest/granular/tests/dem09-spin-identical-3d.yaml b/unittest/granular/tests/dem09-spin-identical-3d.yaml deleted file mode 100644 index 13b09300389..00000000000 --- a/unittest/granular/tests/dem09-spin-identical-3d.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:27:07 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -3.0 3.0 -3.0 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 -0.5 units box - create_atoms 1 single 0.0 0.0 0.5 units box - set group all diameter ${diam} density ${dens} - group lower id 1 - group upper id 2 - velocity lower set 0.0 0.0 ${vin} - velocity upper set 0.0 0.0 -${vin} - set group lower omega 0.0 ${omega0} 0.0 - set group upper omega 0.0 -${omega0} 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.9 - kt 2857.0 - xmu 0.5 - vin 1.0 - omega0 10.0 - radius 0.5 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 300 300 -analytic_enable: yes -analytic_model: spin_no_friction -analytic_tol: 1e-08 -analytic_segment: 1 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -5.3957705702513448e-01 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 5.3957705702513448e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -5.9363413143075683e-01 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 5.9363413143075683e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -9.0095124009357486e-01 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 9.0095124009357486e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -9.0095124009357486e-01 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 9.0095124009357486e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 1.0000000000000000e+01 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 -1.0000000000000000e+01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.0000000000000000e+01 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 -1.0000000000000000e+01 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem09-spin-unequal-3d.yaml b/unittest/granular/tests/dem09-spin-unequal-3d.yaml deleted file mode 100644 index 5601d16a212..00000000000 --- a/unittest/granular/tests/dem09-spin-unequal-3d.yaml +++ /dev/null @@ -1,68 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:27:27 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -4.0 4.0 -4.0 4.0 -3.0 6.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 3.0 units box - create_atoms 1 single 0.0 0.0 0.0 units box - set atom 1 diameter 1.0 density 1.0 - set atom 2 diameter 5.0 density 1000.0 - group small id 1 - velocity small set 0.0 0.0 -${vin} - set group small omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - knorm 1.0e4 - en 0.8 - kt 2857.0 - xmu 0.4 - vin 1.0 - omega0 20.0 - radius 0.5 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 300 300 -analytic_enable: yes -analytic_model: spin_impact -analytic_tol: 0.02 -analytic_segment: 1 -run_pos: ! |2 - 0 2 -2.8969776486214750e-07 0.0000000000000000e+00 -7.1860176501039462e-07 - 0 1 3.6212220607768651e-02 0.0000000000000000e+00 3.0298252206263290e+00 - 1 2 -6.3899055008225046e-07 0.0000000000000000e+00 -1.5831933446778052e-06 - 1 1 7.9873818760281157e-02 0.0000000000000000e+00 3.0778991680848002e+00 -run_vel: ! |2 - 0 2 -5.8215464203350324e-06 0.0000000000000000e+00 -1.4409859661123544e-05 - 0 1 7.2769330254188036e-01 0.0000000000000000e+00 8.0123245764044204e-01 - 1 2 -5.8215464203350324e-06 0.0000000000000000e+00 -1.4409859661123544e-05 - 1 1 7.2769330254188036e-01 0.0000000000000000e+00 8.0123245764044204e-01 -run_torque: ! |2 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 2 0.0000000000000000e+00 -5.8059846795852549e-06 0.0000000000000000e+00 - 0 1 0.0000000000000000e+00 1.6386010968536660e+01 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 -5.8059846795852549e-06 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.6386010968536660e+01 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem09-spin-wall-3d.yaml b/unittest/granular/tests/dem09-spin-wall-3d.yaml deleted file mode 100644 index 1c00d251ab7..00000000000 --- a/unittest/granular/tests/dem09-spin-wall-3d.yaml +++ /dev/null @@ -1,56 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:26:37 2026 -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -3.0 3.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 0.5 units box - set group all diameter ${diam} density ${dens} - velocity all set 0.0 0.0 -${vin} - set group all omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 2.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.8 - kt 2857.0 - xmu 0.4 - vin 1.0 - omega0 20.0 - radius 0.5 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution -run_segments: ! |- - 300 300 -run_pos: ! |2 - 0 1 3.6165446118597538e-02 0.0000000000000000e+00 5.2987935455441326e-01 - 1 1 7.9766117446636989e-02 0.0000000000000000e+00 5.7802911027285397e-01 -run_vel: ! |2 - 0 1 7.2667785546732910e-01 0.0000000000000000e+00 8.0249592864059416e-01 - 1 1 7.2667785546732910e-01 0.0000000000000000e+00 8.0249592864059416e-01 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 1.6366610722663381e+01 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 1.6366610722663381e+01 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem10-aor-spheres-3d.yaml b/unittest/granular/tests/dem10-aor-spheres-3d.yaml deleted file mode 100644 index 5e012f611e9..00000000000 --- a/unittest/granular/tests/dem10-aor-spheres-3d.yaml +++ /dev/null @@ -1,59 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular slow -date_generated: Fri May 29 19:55:45 2026 -epsilon: 1e-04 -skip_tests: -prerequisites: ! | - atom sphere - pair granular - fix pour -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - lattice sc 1.0 - region box block -4.0 4.0 -4.0 4.0 -0.5 10.0 units box - create_box 1 box - region pourreg block -1.2 1.2 -1.2 1.2 3.0 4.5 units box - comm_modify vel yes - neighbor 0.3 bin - timestep 5.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution zplane 0.0 NULL - fix xwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution xplane -3.5 3.5 - fix ywall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution yplane -3.5 3.5 - fix ins all pour ${npour} 1 ${seed} region pourreg diam one ${diam} dens ${dens} ${dens} -input_file: -natoms: 0 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.3 - kt 8235.0 - gt 50.0 - xmu 1.0 - kr 500.0 - gr 50.0 - mur 0.5 - grav 2.0 - npour 120 - seed 5783 - floor 0.0 - aor_lo 15.0 - aor_hi 55.0 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution -run_segments: ! |- - 85000 -analytic_enable: yes -analytic_model: angle_of_repose -analytic_tol: 1 -analytic_segment: 0 -analytic_only: yes -... diff --git a/unittest/granular/tests/dem10-clump-3d.yaml b/unittest/granular/tests/dem10-clump-3d.yaml deleted file mode 100644 index 25e500585a4..00000000000 --- a/unittest/granular/tests/dem10-clump-3d.yaml +++ /dev/null @@ -1,99 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular unstable -date_generated: Fri May 29 20:04:18 2026 -epsilon: 5e-09 -skip_tests: -prerequisites: ! | - atom sphere - atom molecular - pair granular - fix rigid/small -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style hybrid sphere molecular - region box block -4.0 4.0 -4.0 4.0 -0.5 8.0 units box - create_box 1 box - thermo_style custom step atoms - molecule clump ${input_dir}/clump_tetra.mol - create_atoms 0 single 0.0 0.0 1.8 mol clump ${seed} units box - comm_modify vel yes - neighbor 0.3 bin - timestep 5.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all rigid/small molecule - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 4 -variables: ! | - knorm 1.0e4 - en 0.5 - kt 8235.0 - gt 50.0 - xmu 0.5 - kr 500.0 - gr 20.0 - mur 0.3 - grav 10.0 - seed 9183 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution -run_segments: ! |- - 500 600 900 -run_pos: ! |2 - 0 3 7.6373032311001010e-02 4.3111580828023505e-01 1.0593571167912552e+00 - 0 1 -4.8850505236768405e-01 -3.4191991520584136e-01 1.3480239023923331e+00 - 0 2 4.9813070634874052e-01 -3.5544514586172393e-01 1.5104029273856192e+00 - 0 4 -8.5998686292057494e-02 2.6624925278733030e-01 2.0322160534308091e+00 - 1 1 -5.0771835260875209e-01 -4.4344293625692133e-01 6.5387667797709770e-01 - 1 3 6.3698915182779745e-02 3.7704612771436657e-01 6.3714361435021549e-01 - 1 2 4.6973036480341390e-01 -5.1069733690331787e-01 8.5405372566989868e-01 - 1 4 -1.4521854668652895e-01 -6.9101576320310720e-02 1.5073767940396148e+00 - 2 1 -5.2896130718552115e-01 -6.8450608049715811e-01 4.9452628826676526e-01 - 2 3 8.1984785940240112e-02 -2.0540109453749511e-02 9.2568061566695903e-01 - 2 2 4.5596215920559890e-01 -8.5535425185674907e-01 5.2166791119512146e-01 - 2 4 -8.3444395669849875e-02 -9.0486744061122371e-01 1.3622564097295320e+00 -run_vel: ! |2 - 0 3 2.3332465444979558e-18 -2.0426375529701143e-18 -2.4999999999999578e+00 - 0 1 7.6024133014468737e-19 -6.6557429874607152e-19 -2.4999999999999578e+00 - 0 2 -1.2471812832345153e-19 1.0942178640749272e-19 -2.4999999999999578e+00 - 0 4 -2.9687729817465718e-18 2.5988191841551263e-18 -2.4999999999999578e+00 - 1 1 -1.3597227718487903e-01 -7.0073586340847027e-01 -1.1423402288721125e+00 - 1 3 -1.3917530408709752e-01 -6.5099921273441186e-01 1.1870666236110698e+00 - 1 2 -2.2051062407542993e-01 -1.1972634114018752e+00 -8.9636679354022941e-01 - 1 4 -5.0475236950014457e-01 -2.8657483708269869e+00 -3.6146544265833913e-02 - 2 1 -5.6064937307483929e-02 -4.8460006088888941e-01 -9.6499414866511521e-03 - 2 3 -6.7677019596737747e-02 -6.7720134486671413e-01 3.0340514406032859e-01 - 2 2 -6.2376240026430330e-02 -5.2156191068560964e-01 -1.3286949366014274e-02 - 2 4 -1.2028500158084943e-01 -8.5164897736423140e-01 -6.9890184942041772e-02 -run_torque: ! |2 - 0 3 1.3936403135124937e-14 5.9004418477470738e-15 2.6441878737413236e-23 - 0 1 1.4376359121259208e-15 1.3433795943847979e-14 1.7442140406574703e-23 - 0 2 1.2891943276390966e-14 2.1147972205626594e-14 8.9997395387817957e-24 - 0 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -6.7241112704858582e-06 4.6811491884485532e-06 -8.6151263110671237e-08 - 1 3 -1.4203339168799833e-05 1.5458165924798036e-06 1.0822162352027125e-06 - 1 2 -7.4792278983139753e-06 -3.1353325959687495e-06 1.1683674983133837e-06 - 1 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 2 1 9.1744794746289546e+00 -5.4905288685730653e+00 1.8802912336742540e-06 - 2 3 -7.2684502857862193e-06 7.1520252087357449e-07 1.3938822009615075e-06 - 2 2 -3.6453202932550919e-06 -1.3976187272512683e-06 -4.8640903271274652e-07 - 2 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 3 -4.7709937751400701e-18 -5.4499858564899497e-18 2.9065204129112147e-22 - 0 1 -4.7709937751400701e-18 -5.4499858564899497e-18 2.9065204129112147e-22 - 0 2 -4.7709937751400701e-18 -5.4499858564899497e-18 2.9065204129112147e-22 - 0 4 -4.7709937751400701e-18 -5.4499858564899497e-18 2.9065204129112147e-22 - 1 1 2.5419809787220666e+00 -4.2655214036622002e-01 1.2602911435649705e-02 - 1 3 2.5419809787220666e+00 -4.2655214036622002e-01 1.2602911435649705e-02 - 1 2 2.5419809787220666e+00 -4.2655214036622002e-01 1.2602911435649705e-02 - 1 4 2.5419809787220666e+00 -4.2655214036622002e-01 1.2602911435649705e-02 - 2 1 4.0952539882644023e-01 -6.7344986589142175e-02 -2.6242308894206416e-02 - 2 3 4.0952539882644023e-01 -6.7344986589142175e-02 -2.6242308894206416e-02 - 2 2 4.0952539882644023e-01 -6.7344986589142175e-02 -2.6242308894206416e-02 - 2 4 4.0952539882644023e-01 -6.7344986589142175e-02 -2.6242308894206416e-02 -... diff --git a/unittest/granular/tests/dem10-settle-spheres-3d.yaml b/unittest/granular/tests/dem10-settle-spheres-3d.yaml deleted file mode 100644 index e385a2d2897..00000000000 --- a/unittest/granular/tests/dem10-settle-spheres-3d.yaml +++ /dev/null @@ -1,195 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 19:52:45 2026 -epsilon: 5e-09 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - lattice sc 1.0 - region box block -3.0 3.0 -3.0 3.0 -0.5 6.0 units box - create_box 1 box - region blk block -1.5 1.5 -1.5 1.5 0.4 2.4 units box - create_atoms 1 region blk - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.3 bin - timestep 5.0e-4 -post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 18 -variables: ! | - diam 1.0 - dens 1.0 - knorm 1.0e4 - en 0.5 - kt 8235.0 - gt 50.0 - xmu 0.5 - kr 500.0 - gr 20.0 - mur 0.3 - grav 10.0 -pair_style: granular -pair_coeff: ! | - * * hooke ${knorm} ${en} tangential linear_history ${kt} ${gt} ${xmu} rolling sds ${kr} ${gr} ${mur} damping coeff_restitution -run_segments: ! |- - 600 600 -run_pos: ! |2 - 0 1 -1.0000000000000000e+00 -1.0000000000000000e+00 5.5000000000000593e-01 - 0 2 0.0000000000000000e+00 -1.0000000000000000e+00 5.5000000000000593e-01 - 0 3 1.0000000000000000e+00 -1.0000000000000000e+00 5.5000000000000593e-01 - 0 4 -1.0000000000000000e+00 0.0000000000000000e+00 5.5000000000000593e-01 - 0 5 0.0000000000000000e+00 0.0000000000000000e+00 5.5000000000000593e-01 - 0 6 1.0000000000000000e+00 0.0000000000000000e+00 5.5000000000000593e-01 - 0 7 -1.0000000000000000e+00 1.0000000000000000e+00 5.5000000000000593e-01 - 0 8 0.0000000000000000e+00 1.0000000000000000e+00 5.5000000000000593e-01 - 0 9 1.0000000000000000e+00 1.0000000000000000e+00 5.5000000000000593e-01 - 0 10 -1.0000000000000000e+00 -1.0000000000000000e+00 1.5500000000000074e+00 - 0 11 0.0000000000000000e+00 -1.0000000000000000e+00 1.5500000000000074e+00 - 0 12 1.0000000000000000e+00 -1.0000000000000000e+00 1.5500000000000074e+00 - 0 13 -1.0000000000000000e+00 0.0000000000000000e+00 1.5500000000000074e+00 - 0 14 0.0000000000000000e+00 0.0000000000000000e+00 1.5500000000000074e+00 - 0 15 1.0000000000000000e+00 0.0000000000000000e+00 1.5500000000000074e+00 - 0 16 -1.0000000000000000e+00 1.0000000000000000e+00 1.5500000000000074e+00 - 0 17 0.0000000000000000e+00 1.0000000000000000e+00 1.5500000000000074e+00 - 0 18 1.0000000000000000e+00 1.0000000000000000e+00 1.5500000000000074e+00 - 1 1 -1.0000000000000000e+00 -1.0000000000000000e+00 5.6034428789549495e-01 - 1 2 0.0000000000000000e+00 -1.0000000000000000e+00 5.6034428789549495e-01 - 1 3 1.0000000000000000e+00 -1.0000000000000000e+00 5.6034428789549495e-01 - 1 4 -1.0000000000000000e+00 0.0000000000000000e+00 5.6034428789549495e-01 - 1 5 0.0000000000000000e+00 0.0000000000000000e+00 5.6034428789549495e-01 - 1 6 1.0000000000000000e+00 0.0000000000000000e+00 5.6034428789549495e-01 - 1 7 -1.0000000000000000e+00 1.0000000000000000e+00 5.6034428789549495e-01 - 1 8 0.0000000000000000e+00 1.0000000000000000e+00 5.6034428789549495e-01 - 1 9 1.0000000000000000e+00 1.0000000000000000e+00 5.6034428789549495e-01 - 1 10 -1.0000000000000000e+00 -1.0000000000000000e+00 1.8109819622337475e+00 - 1 11 0.0000000000000000e+00 -1.0000000000000000e+00 1.8109819622337475e+00 - 1 12 1.0000000000000000e+00 -1.0000000000000000e+00 1.8109819622337475e+00 - 1 13 -1.0000000000000000e+00 0.0000000000000000e+00 1.8109819622337475e+00 - 1 14 0.0000000000000000e+00 0.0000000000000000e+00 1.8109819622337475e+00 - 1 15 1.0000000000000000e+00 0.0000000000000000e+00 1.8109819622337475e+00 - 1 16 -1.0000000000000000e+00 1.0000000000000000e+00 1.8109819622337475e+00 - 1 17 0.0000000000000000e+00 1.0000000000000000e+00 1.8109819622337475e+00 - 1 18 1.0000000000000000e+00 1.0000000000000000e+00 1.8109819622337475e+00 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 3 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 4 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 5 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 6 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 7 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 8 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 9 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999494e+00 - 0 10 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 11 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 12 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 13 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 14 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 15 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 16 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 17 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 0 18 0.0000000000000000e+00 0.0000000000000000e+00 -2.9999999999999454e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 3 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 4 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 5 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 6 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 7 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 8 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 9 0.0000000000000000e+00 0.0000000000000000e+00 -9.7940207923332279e-01 - 1 10 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 11 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 12 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 13 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 14 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 15 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 16 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 17 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 - 1 18 0.0000000000000000e+00 0.0000000000000000e+00 3.4803309033102192e-02 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 3 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 5 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 6 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 7 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 8 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 9 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 10 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 11 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 12 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 13 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 14 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 15 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 16 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 17 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 18 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 3 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 5 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 6 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 7 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 8 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 9 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 10 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 11 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 12 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 13 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 14 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 15 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 16 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 17 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 18 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 3 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 5 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 6 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 7 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 8 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 9 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 10 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 11 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 12 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 13 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 14 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 15 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 16 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 17 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 18 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 3 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 5 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 6 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 7 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 8 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 9 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 10 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 11 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 12 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 13 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 14 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 15 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 16 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 17 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 18 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem11-hertz-twosphere-3d.yaml b/unittest/granular/tests/dem11-hertz-twosphere-3d.yaml deleted file mode 100644 index 19875949a68..00000000000 --- a/unittest/granular/tests/dem11-hertz-twosphere-3d.yaml +++ /dev/null @@ -1,68 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:14:09 2026 -epsilon: 1e-09 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -3.0 3.0 -2.0 2.0 -2.0 2.0 units box - create_box 1 box - create_atoms 1 single -0.5 0.0 0.0 units box - create_atoms 1 single 0.5 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - group left id 1 - group right id 2 - velocity left set ${vin} 0.0 0.0 - velocity right set -${vin} 0.0 0.0 - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-4 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 1.0 - dens 1.0 - emod 1.0e5 - poisson 0.3 - vin 1.0 - vrela 2.0 - mred_factor 0.5 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} 1.0 ${poisson} tangential mindlin NULL 0.0 0.0 damping coeff_restitution -run_segments: ! |- - 120 220 -analytic_enable: yes -analytic_model: hertz_normal_impact -analytic_tol: 0.01 -analytic_segment: 0 -run_pos: ! |2 - 0 1 -4.9168282211655673e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 4.9168282211655673e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -5.0950724834877426e-01 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 5.0950724834877426e-01 0.0000000000000000e+00 0.0000000000000000e+00 -run_vel: ! |2 - 0 1 3.6997917196395481e-02 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 -3.6997917196395481e-02 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 -1.0000003913834976e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 1.0000003913834976e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/dem11-hertz-wall-3d.yaml b/unittest/granular/tests/dem11-hertz-wall-3d.yaml deleted file mode 100644 index 81a58625ce0..00000000000 --- a/unittest/granular/tests/dem11-hertz-wall-3d.yaml +++ /dev/null @@ -1,58 +0,0 @@ ---- -lammps_version: 30 Mar 2026 -tags: granular -date_generated: Fri May 29 21:14:10 2026 -epsilon: 1e-09 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -pre_commands: ! | - units lj - dimension 3 - boundary f f f - atom_style sphere - region box block -2.0 2.0 -2.0 2.0 -0.5 3.0 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 0.5 units box - set group all diameter ${diam} density ${dens} - velocity all set 0.0 0.0 -${vin} - comm_modify vel yes - neighbor 0.3 bin - timestep 1.0e-4 -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} 1.0 ${poisson} tangential mindlin NULL 0.0 0.0 damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 1.0 - dens 1.0 - emod 1.0e5 - poisson 0.3 - vin 1.0 - vrela 1.0 - mred_factor 1.0 - floor 0.0 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} 1.0 ${poisson} tangential mindlin NULL 0.0 0.0 damping coeff_restitution -run_segments: ! |- - 160 200 -analytic_enable: yes -analytic_model: hertz_normal_impact -analytic_tol: 0.01 -analytic_segment: 0 -run_pos: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 4.8902088380884362e-01 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 5.0368149689066244e-01 -run_vel: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.8127588706772991e-02 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.0000000212158540e+00 -run_torque: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -run_omega: ! |2 - 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 - 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -... diff --git a/unittest/granular/tests/test_dem01_hooke.yaml b/unittest/granular/tests/test_dem01_hooke.yaml deleted file mode 100644 index 1feaf709629..00000000000 --- a/unittest/granular/tests/test_dem01_hooke.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -lammps_version: unknown -date_generated: unknown -epsilon: 1.0e-13 -skip_tests: none -prerequisites: ! | - atom sphere - pair gran/hooke -diameter: 2.0 -density: 1.0 -knorm: 1000.0 -ktang: NULL -gnorm: 10.0 -gtang: NULL -xmu: 0.1 -damp: 0 -pair_style: gran/hooke ${knorm} ${ktang} ${gnorm} ${gtang} ${xmu} ${damp} -gravity: 1.0 vector 0.0 0.0 -1.0 -wall: wall/gran hooke ${knorm} ${ktang} ${gnorm} ${gtang} ${xmu} ${damp} zplane 0.0 NULL contacts -input_file: in.dem01_lj -steps1: 1100 -steps2: 200 -steps3: 500 From febf8774c0b8cd954bf3cd10de6fc3b39dca9c1d Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Tue, 21 Jul 2026 17:46:19 -0600 Subject: [PATCH 02/12] Add tempfile to unittest/granular --- unittest/granular/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 unittest/granular/temp diff --git a/unittest/granular/temp b/unittest/granular/temp new file mode 100644 index 00000000000..4be40b2f3af --- /dev/null +++ b/unittest/granular/temp @@ -0,0 +1 @@ +tempfile From 1236e80f260ae4e479ca78cc7bf26582dd764dac Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Tue, 21 Jul 2026 17:47:13 -0600 Subject: [PATCH 03/12] add verified granular unittests --- unittest/granular/CMakeLists.txt | 117 +++++ unittest/granular/README_MAPPING.md | 66 +++ unittest/granular/test_analytic_models.cpp | 395 +++++++++++++++ unittest/granular/test_analytic_models.h | 31 ++ unittest/granular/test_config.h | 136 +++++ unittest/granular/test_config_reader.cpp | 468 ++++++++++++++++++ unittest/granular/test_config_reader.h | 76 +++ unittest/granular/test_dem_01.cpp | 39 ++ unittest/granular/test_dem_02.cpp | 39 ++ unittest/granular/test_dem_03.cpp | 39 ++ unittest/granular/test_dem_04.cpp | 39 ++ unittest/granular/test_dem_05.cpp | 39 ++ unittest/granular/test_dem_06.cpp | 39 ++ unittest/granular/test_dem_07.cpp | 39 ++ unittest/granular/test_dem_08.cpp | 39 ++ unittest/granular/test_dem_common.cpp | 301 +++++++++++ unittest/granular/test_dem_common.h | 27 + unittest/granular/test_main.cpp | 319 ++++++++++++ unittest/granular/test_main.h | 58 +++ .../tests/dem01-hertzmindlin-cof-3d-si.yaml | 72 +++ .../tests/dem02-oblique-cof-3d-si.yaml | 69 +++ .../tests/dem03-rolling-cof-3d-si.yaml | 71 +++ .../tests/dem04-dmt-twosphere-cof-3d-si.yaml | 64 +++ .../tests/dem05-spin-headon-cof-3d-si.yaml | 72 +++ .../tests/dem06-spin-unequal-cof-3d-si.yaml | 75 +++ .../tests/dem07-wall-normal-cof-3d-si.yaml | 73 +++ .../tests/dem08-twosphere-normal-3d-si.yaml | 70 +++ 27 files changed, 2872 insertions(+) create mode 100644 unittest/granular/CMakeLists.txt create mode 100644 unittest/granular/README_MAPPING.md create mode 100644 unittest/granular/test_analytic_models.cpp create mode 100644 unittest/granular/test_analytic_models.h create mode 100644 unittest/granular/test_config.h create mode 100644 unittest/granular/test_config_reader.cpp create mode 100644 unittest/granular/test_config_reader.h create mode 100644 unittest/granular/test_dem_01.cpp create mode 100644 unittest/granular/test_dem_02.cpp create mode 100644 unittest/granular/test_dem_03.cpp create mode 100644 unittest/granular/test_dem_04.cpp create mode 100644 unittest/granular/test_dem_05.cpp create mode 100644 unittest/granular/test_dem_06.cpp create mode 100644 unittest/granular/test_dem_07.cpp create mode 100644 unittest/granular/test_dem_08.cpp create mode 100644 unittest/granular/test_dem_common.cpp create mode 100644 unittest/granular/test_dem_common.h create mode 100644 unittest/granular/test_main.cpp create mode 100644 unittest/granular/test_main.h create mode 100644 unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem02-oblique-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem03-rolling-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml diff --git a/unittest/granular/CMakeLists.txt b/unittest/granular/CMakeLists.txt new file mode 100644 index 00000000000..ef0d81c8fae --- /dev/null +++ b/unittest/granular/CMakeLists.txt @@ -0,0 +1,117 @@ +# -*- CMake -*- file for tests using DEM / granular models + +function(extract_tags out yaml_file) + file(STRINGS ${yaml_file} TAGS_LINE REGEX "^tags:") + string(REPLACE "tags:" "" TAGS_LINE "${TAGS_LINE}") + string(REGEX MATCHALL "[^, \t\r\n]+" TAGS "${TAGS_LINE}") + set(${out} "${TAGS}" PARENT_SCOPE) +endfunction() + +# build support library +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + string(REPLACE "/" "\\\\" TEST_INPUT_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/tests") +else() + set(TEST_INPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/tests) +endif() +add_library(granular_tests STATIC + ../error_stats.cpp + ../yaml_writer.cpp + test_config_reader.cpp + test_analytic_models.cpp + test_dem_common.cpp + test_main.cpp) +if(YAML_FOUND) + target_compile_definitions(granular_tests PRIVATE TEST_INPUT_FOLDER=${TEST_INPUT_FOLDER}) +else() + # we always use static linkage with local compiled libyaml + target_compile_definitions(granular_tests PRIVATE TEST_INPUT_FOLDER=${TEST_INPUT_FOLDER} YAML_DECLARE_STATIC) +endif() +target_include_directories(granular_tests PRIVATE "${LAMMPS_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/..") +target_link_libraries(granular_tests PUBLIC GTest::GMock Yaml::Yaml lammps) + +# propagate sanitizer options to test tools +if(ENABLE_SANITIZER AND (NOT (ENABLE_SANITIZER STREQUAL "none"))) + target_compile_options(granular_tests PUBLIC -fsanitize=${ENABLE_SANITIZER}) + target_link_options(granular_tests PUBLIC -fsanitize=${ENABLE_SANITIZER}) +endif() + +# prepare environment for testers +if(WIN32) + set(GRANULAR_TEST_ENVIRONMENT PYTHONPATH=${TEST_INPUT_FOLDER}) +else() + set(GRANULAR_TEST_ENVIRONMENT PYTHONPATH=${TEST_INPUT_FOLDER}:${LAMMPS_PYTHON_DIR}:$ENV{PYTHONPATH}) +endif() +list(APPEND GRANULAR_TEST_ENVIRONMENT "PYTHONUNBUFFERED=1") +list(APPEND GRANULAR_TEST_ENVIRONMENT "PYTHONDONTWRITEBYTECODE=1") +list(APPEND GRANULAR_TEST_ENVIRONMENT "OMP_PROC_BIND=false") +list(APPEND GRANULAR_TEST_ENVIRONMENT "OMP_NUM_THREADS=4") +list(APPEND GRANULAR_TEST_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") +get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(BUILD_IS_MULTI_CONFIG) + set(LAMMPS_LIB_PATH ${CMAKE_BINARY_DIR}/$) +else() + set(LAMMPS_LIB_PATH ${CMAKE_BINARY_DIR}) +endif() +if(APPLE) + list(APPEND GRANULAR_TEST_ENVIRONMENT "DYLD_LIBRARY_PATH=${LAMMPS_LIB_PATH}:$ENV{DYLD_LIBRARY_PATH}") +elseif(WIN32) + list(APPEND GRANULAR_TEST_ENVIRONMENT "LAMMPSDLLPATH=${LAMMPS_LIB_PATH}") +else() + list(APPEND GRANULAR_TEST_ENVIRONMENT "LD_LIBRARY_PATH=${LAMMPS_LIB_PATH}:$ENV{LD_LIBRARY_PATH}") +endif() + +# helper to register all YAML files matching a prefix with a given test driver +function(register_dem_tests driver prefix label) + file(GLOB DEM_TESTS LIST_DIRECTORIES false CONFIGURE_DEPENDS ${TEST_INPUT_FOLDER}/${prefix}-*.yaml) + foreach(TEST ${DEM_TESTS}) + string(REGEX REPLACE "^.*${prefix}-(.*)\.yaml" "${label}:\\1" TNAME ${TEST}) + extract_tags(TEST_TAGS ${TEST}) + list(FIND TEST_TAGS "no${CMAKE_SYSTEM_NAME}" _SKIPME) + if(_SKIPME GREATER_EQUAL 0) + continue() + endif() + add_test(NAME ${TNAME} COMMAND ${driver} ${TEST}) + set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "${GRANULAR_TEST_ENVIRONMENT}") + set_tests_properties(${TNAME} PROPERTIES LABELS "${TEST_TAGS}") + endforeach() +endfunction() + +# DEM-01: sphere sliding then rolling without slipping on a rough surface +add_executable(test_dem_01 test_dem_01.cpp) +target_link_libraries(test_dem_01 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_01 dem01 DEM01) + +# DEM-02: oblique collision of a sphere with a flat wall +add_executable(test_dem_02 test_dem_02.cpp) +target_link_libraries(test_dem_02 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_02 dem02 DEM02) + +# DEM-03: spinning sphere damped by rolling resistance (rolling sds) +add_executable(test_dem_03 test_dem_03.cpp) +target_link_libraries(test_dem_03 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_03 dem03 DEM03) + +# DEM-04: cohesive/adhesive contact (DMT pull-off force) +add_executable(test_dem_04 test_dem_04.cpp) +target_link_libraries(test_dem_04 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_04 dem04 DEM04) + +# DEM-05: two identical spinning spheres, head-on collision +add_executable(test_dem_05 test_dem_05.cpp) +target_link_libraries(test_dem_05 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_05 dem05 DEM05) + +# DEM-06: unequal-size spinning sphere impacting a heavy/rigid partner +add_executable(test_dem_06 test_dem_06.cpp) +target_link_libraries(test_dem_06 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_06 dem06 DEM06) + +# DEM-07: elastic Hertzian normal impact of a sphere on a wall +add_executable(test_dem_07 test_dem_07.cpp) +target_link_libraries(test_dem_07 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_07 dem07 DEM07) + +# DEM-08: elastic Hertzian normal impact of two spheres +add_executable(test_dem_08 test_dem_08.cpp) +target_link_libraries(test_dem_08 PRIVATE lammps granular_tests) +register_dem_tests(test_dem_08 dem08 DEM08) diff --git a/unittest/granular/README_MAPPING.md b/unittest/granular/README_MAPPING.md new file mode 100644 index 00000000000..94a32f12ad5 --- /dev/null +++ b/unittest/granular/README_MAPPING.md @@ -0,0 +1,66 @@ +# unittest/granular replacement — mapping notes + +Only the 8 tests derived from your scripts are here, renumbered 01-08 +(sequentially, in original scenario order). Everything else has been +removed — no leftover placeholders for unimplemented categories, no +unused test_dem_0N.cpp files. + +## What's unchanged (kept from the existing directory) + +Generic test *harness* files — not test content, and match LAMMPS' own +documented design for `unittest/granular`: + +- `CMakeLists.txt` — trimmed to register exactly 8 executables/test sets +- `test_config.h`, `test_config_reader.{h,cpp}` +- `test_dem_common.{h,cpp}`, `test_main.{h,cpp}` +- `test_analytic_models.{h,cpp}` — already implements every closed-form + model these 8 tests need (`slip_cessation`, `oblique_impact`, + `rolling_decay`, `pulloff_dmt`, `collision_restitution`, `spin_impact`) + +## Script → test mapping (new numbering) + +| # | Your script | New file | analytic_model | +|---|---|---|---| +| 01 | `sphere_sliding_rolling.in` | `dem01-hertzmindlin-cof-3d-si.yaml` | `slip_cessation` | +| 02 | `oblique_impact.in` | `dem02-oblique-cof-3d-si.yaml` | `oblique_impact` | +| 03 | `sphere_pure_rolling.in` | `dem03-rolling-cof-3d-si.yaml` | `rolling_decay` | +| 04 | `in.cohesive_dmt` | `dem04-dmt-twosphere-cof-3d-si.yaml` | `pulloff_dmt` | +| 05 | `angular_sphere_impact.in` | `dem05-spin-headon-cof-3d-si.yaml` | `collision_restitution` | +| 06 | `in.angular_bidisperse` | `dem06-spin-unequal-cof-3d-si.yaml` | `spin_impact` | +| 07 | `normal_contact_cof.in` | `dem07-wall-normal-cof-3d-si.yaml` | `hertz_normal_impact` | +| 08 | `in.normal_simple` | `dem08-twosphere-normal-3d-si.yaml` | `hertz_normal_impact` | + +Two of these (02, 06) have their geometry relabeled — not their physics +changed — to match axis conventions `test_analytic_models.cpp` hard-codes +(e.g. `oblique_impact` reads `v[i][0]`/`v[i][2]` specifically). Every +material property, density, diameter, velocity, friction coefficient, and +restitution coefficient is transcribed unchanged from your original +scripts. See the previous round's notes below for exact per-file details. + +## What you still need to do — this is important + +**I could not run LAMMPS in this environment.** Each of the 8 YAML files +has a real `prerequisites`/`pre_commands`/`variables`/`pair_style`/ +`pair_coeff`/`post_commands` block built from your script, plus a +placeholder `run_segments` guess, but the `run_pos`/`run_vel`/ +`run_torque`/`run_omega` reference blocks are marked `# TODO: regenerate`. + +Generate the real reference data by building LAMMPS with `GRANULAR` + +testing enabled and running, e.g.: + +``` +test_dem_01 tests/dem01-hertzmindlin-cof-3d-si.yaml -g new.yaml +``` + +or update in place with `-u`, then check with `-s` (per-quantity error +stats) that `analytic_segment` lands where the model expects (e.g. peak +compression for `hertz_normal_impact`, post-rebound free flight for +`oblique_impact`/`spin_impact`) and retune `run_segments` if not. + +Per-file notes carried over from before: +- `dem01` (from `sphere_sliding_rolling.in`) and `dem03` (from + `sphere_pure_rolling.in`): source scripts used gravity magnitude `1.0` + (not standard 9.81) — kept as literally scripted, verify that's intended. +- `dem01`: source script had a 10,000-step settle phase before applying + sliding velocity; this version places the sphere directly at contact + instead, so the early transient will differ slightly from your original. diff --git a/unittest/granular/test_analytic_models.cpp b/unittest/granular/test_analytic_models.cpp new file mode 100644 index 00000000000..7f4fba5bb3e --- /dev/null +++ b/unittest/granular/test_analytic_models.cpp @@ -0,0 +1,395 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// Closed-form ("analytic") reference solutions for the DEM verification +// tests. Each model is selected by name from the YAML 'analytic_model' key +// and reads its parameters from the 'variables' block, so new functional +// forms can be exercised purely from YAML once implemented here. + +#include "test_analytic_models.h" + +#include "atom.h" +#include "lammps.h" +#include "math_const.h" +#include "update.h" + +#include "gtest/gtest.h" + +#include +#include +#include + +using namespace LAMMPS_NS; + +// parse the variables block into name->double (non-numeric values are skipped) +static std::map as_doubles(const TestConfig &cfg) +{ + std::map vars; + for (const auto &v : cfg.variables) { + try { + vars[v.first] = std::stod(v.second); + } catch (std::exception &) { + // ignore non-numeric variables (e.g. NULL placeholders) + } + } + return vars; +} + +// local index of the atom with the given tag, or -1 if not present on this rank +static int find_local(LAMMPS *lmp, tagint id) +{ + for (int i = 0; i < lmp->atom->nlocal; ++i) + if (lmp->atom->tag[i] == id) return i; + return -1; +} + +// relative-error comparison consistent with the regression epsilon checks +static void expect_rel(double expected, double actual, double tol, const std::string &what) +{ + const double denom = std::max(std::fabs(expected), 1.0e-300); + const double relerr = std::fabs(actual - expected) / denom; + EXPECT_LE(relerr, tol) << what << ": expected " << expected << " got " << actual; +} + +static double var_or(const std::map &vars, const std::string &name, + double fallback) +{ + auto it = vars.find(name); + return (it != vars.end()) ? it->second : fallback; +} + +void check_analytic_model(const TestConfig &cfg, LAMMPS *lmp, int segment) +{ + if (!cfg.analytic_enable) return; + + int target = cfg.analytic_segment; + if (target < 0) target = (int) cfg.run_segments.size() - 1; + if (segment != target) return; + + const auto vars = as_doubles(cfg); + const double t = (double) lmp->update->ntimestep * lmp->update->dt; + + if (cfg.analytic_model == "freefall") { + // ballistic motion of atom 1 before any contact: z = z0 - g t^2/2, vz = -g t. + // velocity-Verlet integrates constant acceleration exactly, so this is tight. + const double g = var_or(vars, "grav", 0.0); + const double z0 = var_or(vars, "z0", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "freefall: atom with tag 1 not found"; + expect_rel(z0 - 0.5 * g * t * t, lmp->atom->x[i][2], cfg.analytic_tol, "freefall z"); + expect_rel(-g * t, lmp->atom->v[i][2], cfg.analytic_tol, "freefall vz"); + } else if (cfg.analytic_model == "bounce_height") { + // hard-sphere limit: the apex (center) height after the k-th bounce is + // h_k = r + e^(2k) (h0 - r). + // Evaluated at a free-flight segment via energy conservation, + // apex = z + vz^2/(2g), so the segment need not end exactly at the apex. + // The match is approximate (soft-sphere, finite stiffness) -> loose tol. + const double g = var_or(vars, "grav", 0.0); + const double e = var_or(vars, "restitution", var_or(vars, "en", 1.0)); + const double r = var_or(vars, "radius", 0.0); + const double h0 = var_or(vars, "h0", 0.0); + const double k = var_or(vars, "bounce_k", 1.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "bounce_height: atom with tag 1 not found"; + const double z = lmp->atom->x[i][2]; + const double vz = lmp->atom->v[i][2]; + const double apex = z + vz * vz / (2.0 * g); + expect_rel(r + std::pow(e, 2.0 * k) * (h0 - r), apex, cfg.analytic_tol, "bounce_height apex"); + } else if (cfg.analytic_model == "stack_energy") { + // Two particles (tags 1 lower, 2 upper) stacked between a floor (ylo) + // and ceiling (yhi). For the elastic (e=1) linear-spring case the total + // mechanical energy KE + gravitational PE + contact spring PE is + // conserved; compare it to the initial value (particles start at rest). + // Masses and radii are read from the live simulation so the comparison + // does not depend on reproducing LAMMPS' mass formula. + const double g = var_or(vars, "grav", 0.0); + const double kn = var_or(vars, "knorm", 0.0); + const double ylo = var_or(vars, "ylo", 0.0); + const double yhi = var_or(vars, "yhi", 0.0); + const double y1_0 = var_or(vars, "y1", 0.0); + const double y2_0 = var_or(vars, "y2", 0.0); + const int i1 = find_local(lmp, 1); + const int i2 = find_local(lmp, 2); + ASSERT_GE(i1, 0) << "stack_energy: atom with tag 1 not found"; + ASSERT_GE(i2, 0) << "stack_energy: atom with tag 2 not found"; + const double m1 = lmp->atom->rmass[i1]; + const double m2 = lmp->atom->rmass[i2]; + const double r1 = lmp->atom->radius[i1]; + const double r2 = lmp->atom->radius[i2]; + + // linear-spring contact PE from the three possible overlaps: + // lower particle vs floor, the pair, upper particle vs ceiling + auto spring_pe = [&](double ya, double yb) { + const double df = std::max(0.0, r1 - (ya - ylo)); + const double dc = std::max(0.0, (yb + r2) - yhi); + const double dpp = std::max(0.0, (r1 + r2) - (yb - ya)); + return 0.5 * kn * (df * df + dc * dc + dpp * dpp); + }; + + const double e0 = (m1 * g * y1_0 + m2 * g * y2_0) + spring_pe(y1_0, y2_0); + const double ya = lmp->atom->x[i1][1]; + const double yb = lmp->atom->x[i2][1]; + const double va = lmp->atom->v[i1][1]; + const double vb = lmp->atom->v[i2][1]; + const double ec = 0.5 * m1 * va * va + 0.5 * m2 * vb * vb + (m1 * g * ya + m2 * g * yb) + + spring_pe(ya, yb); + expect_rel(e0, ec, cfg.analytic_tol, "stack_energy total energy"); + } else if (cfg.analytic_model == "slip_cessation") { + // sphere (tag 1) launched along +x with no spin on a rough floor (normal +z): + // kinetic friction decelerates u and spins it up about +y until the no-slip + // condition u = omega_y r is reached. Thereafter u = 5 u0/7 and omega_y = u/r. + // Evaluate at a segment past the slip-cessation time t_s = 2 u0 / (7 mu g). + const double u0 = var_or(vars, "u0", 0.0); + const double r = var_or(vars, "radius", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "slip_cessation: atom with tag 1 not found"; + const double u_final = 5.0 * u0 / 7.0; + expect_rel(u_final, lmp->atom->v[i][0], cfg.analytic_tol, "slip_cessation vx"); + expect_rel(u_final / r, lmp->atom->omega[i][1], cfg.analytic_tol, "slip_cessation omega_y"); + } else if (cfg.analytic_model == "oblique_impact") { + // grazing impact of sphere (tag 1) on a wall with normal +z, in the + // gross-sliding regime (tangential velocity never reverses during + // contact). With approach velocity (vx_in, 0, -vz_in) and no spin: + // vz_out = en vz_in, vx_out = vx_in - mu(1+en) vz_in, + // omega_y_out = (5/2) mu (1+en) vz_in / r. + // Evaluate at a free-flight segment after the rebound. + const double vx_in = var_or(vars, "vx_in", 0.0); + const double vz_in = var_or(vars, "vz_in", 0.0); + const double en = var_or(vars, "en", 1.0); + const double mu = var_or(vars, "xmu", 0.0); + const double r = var_or(vars, "radius", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "oblique_impact: atom with tag 1 not found"; + const double dvt = mu * (1.0 + en) * vz_in; // tangential velocity decrement + expect_rel(en * vz_in, lmp->atom->v[i][2], cfg.analytic_tol, "oblique_impact vz_out"); + expect_rel(vx_in - dvt, lmp->atom->v[i][0], cfg.analytic_tol, "oblique_impact vx_out"); + expect_rel(2.5 * dvt / r, lmp->atom->omega[i][1], cfg.analytic_tol, "oblique_impact omega_y"); + } else if (cfg.analytic_model == "terminal_velocity_linear") { + // particle (tag 1) falling under gravity g with linear (Stokes) drag + // F = -gamma v reaches terminal speed v_term = m g / gamma. + const double g = var_or(vars, "grav", 0.0); + const double gamma = var_or(vars, "gamma", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "terminal_velocity_linear: atom with tag 1 not found"; + const double m = lmp->atom->rmass[i]; + expect_rel(m * g / gamma, -lmp->atom->v[i][2], cfg.analytic_tol, + "terminal_velocity_linear"); + } else if (cfg.analytic_model == "terminal_velocity_schiller_naumann") { + // particle (tag 1) falling under gravity g with Schiller-Naumann drag + // (quiescent gas): terminal speed solves m g = 1/2 Cd rho_g pi r^2 v^2. + const double g = var_or(vars, "grav", 0.0); + const double rho = var_or(vars, "rho_gas", 0.0); + const double mu = var_or(vars, "mu_gas", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "terminal_velocity_schiller_naumann: atom with tag 1 not found"; + const double m = lmp->atom->rmass[i]; + const double r = lmp->atom->radius[i]; + const double area = MathConst::MY_PI * r * r; + const double mg = m * g; + auto drag = [&](double v) { + if (v <= 0.0) return 0.0; + const double re = rho * v * (2.0 * r) / mu; + const double cd = (24.0 / re) * (1.0 + 0.15 * std::pow(re, 0.687)); + return 0.5 * cd * rho * area * v * v; + }; + // bracket then bisect for the terminal speed (drag is monotone in v) + double vlo = 0.0, vhi = 1.0; + int guard = 0; + while ((drag(vhi) < mg) && (guard++ < 200)) vhi *= 2.0; + for (int it = 0; it < 100; ++it) { + const double vm = 0.5 * (vlo + vhi); + if (drag(vm) < mg) + vlo = vm; + else + vhi = vm; + } + expect_rel(0.5 * (vlo + vhi), -lmp->atom->v[i][2], cfg.analytic_tol, + "terminal_velocity_schiller_naumann"); + } else if (cfg.analytic_model == "energy_dissipation") { + // For a frictional collision with no external forces (no gravity) the + // total mechanical (translational + rotational) kinetic energy of the + // sphere (tag 1) must not increase. This guards against the + // grazing-impact energy-injection bug of the classic tangential model. + // Initial state: velocity (vx_in, 0, -vz_in) with no spin; sphere moment + // of inertia I = (2/5) m r^2. analytic_tol is the (small) fractional + // excess over the initial energy that is tolerated. + const double vx_in = var_or(vars, "vx_in", 0.0); + const double vz_in = var_or(vars, "vz_in", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "energy_dissipation: atom with tag 1 not found"; + const double m = lmp->atom->rmass[i]; + const double r = lmp->atom->radius[i]; + const double *v = lmp->atom->v[i]; + const double *w = lmp->atom->omega[i]; + const double e_init = 0.5 * m * (vx_in * vx_in + vz_in * vz_in); + const double ke_tr = 0.5 * m * (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + const double ke_rot = 0.5 * (0.4 * m * r * r) * (w[0] * w[0] + w[1] * w[1] + w[2] * w[2]); + const double e_final = ke_tr + ke_rot; + EXPECT_LE(e_final, e_init * (1.0 + cfg.analytic_tol)) + << "energy_dissipation: final energy " << e_final << " exceeds initial " << e_init; + } else if (cfg.analytic_model == "rolling_decay") { + // sphere (tag 1) spinning about +y on a flat wall, damped only by the + // rolling-resistance torque M = mu_r R N (N = m g). In the gross-rolling + // (Coulomb-capped) regime the spin decays linearly: + // omega_y(t) = omega0 - (5 mu_r g)/(2 R) t. + const double g = var_or(vars, "grav", 0.0); + const double mur = var_or(vars, "mur", 0.0); + const double omega0 = var_or(vars, "omega0", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "rolling_decay: atom with tag 1 not found"; + const double r = lmp->atom->radius[i]; + expect_rel(omega0 - (5.0 * mur * g) / (2.0 * r) * t, lmp->atom->omega[i][1], cfg.analytic_tol, + "rolling_decay omega_y"); + } else if (cfg.analytic_model == "pulloff_dmt") { + // DMT cohesive contact held at (near-)zero overlap: the normal force on + // particle (tag 1) has magnitude equal to the pull-off force + // F_pull = 4 pi gamma R_eff + // since the Hertzian part ~0 at delta~0. gamma = variable 'coh', + // R_eff = variable 'reff' (= R for a wall, R/2 for two equal spheres). + const double coh = var_or(vars, "coh", 0.0); + const double reff = var_or(vars, "reff", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "pulloff_dmt: atom with tag 1 not found"; + const double *f = lmp->atom->f[i]; + const double fmag = std::sqrt(f[0] * f[0] + f[1] * f[1] + f[2] * f[2]); + expect_rel(4.0 * MathConst::MY_PI * coh * reff, fmag, cfg.analytic_tol, "pulloff_dmt force"); + } else if (cfg.analytic_model == "collision_restitution") { + // head-on collision of two equal spheres (tags 1,2) moving along x at + // +/- vin: the total x-momentum stays ~0 and the relative normal speed + // reverses with the coefficient of restitution e: + // -(v1x - v2x)/(2 vin) = e. + const double en = var_or(vars, "en", 1.0); + const double vin = var_or(vars, "vin", 0.0); + const int i1 = find_local(lmp, 1); + const int i2 = find_local(lmp, 2); + ASSERT_GE(i1, 0) << "collision_restitution: atom with tag 1 not found"; + ASSERT_GE(i2, 0) << "collision_restitution: atom with tag 2 not found"; + const double m1 = lmp->atom->rmass[i1]; + const double m2 = lmp->atom->rmass[i2]; + const double v1 = lmp->atom->v[i1][0]; + const double v2 = lmp->atom->v[i2][0]; + EXPECT_LE(std::fabs(m1 * v1 + m2 * v2), cfg.analytic_tol * (m1 + m2) * vin) + << "collision_restitution: total x-momentum not conserved"; + expect_rel(en, -(v1 - v2) / (2.0 * vin), cfg.analytic_tol, "collision_restitution e"); + } else if (cfg.analytic_model == "angle_of_repose") { + // coarse, statistical estimate of a settled heap's angle of repose: + // atan(H / R), where H is the peak height above the floor and R is the + // largest horizontal distance from the (horizontal) centroid. Asserted + // to lie within a band [aor_lo, aor_hi] degrees (variables). + const double floor = var_or(vars, "floor", 0.0); + const double lo = var_or(vars, "aor_lo", 0.0); + const double hi = var_or(vars, "aor_hi", 90.0); + double **x = lmp->atom->x; + const int nlocal = lmp->atom->nlocal; + ASSERT_GT(nlocal, 0) << "angle_of_repose: no atoms"; + double xc = 0.0, yc = 0.0, zmax = -1.0e300; + for (int k = 0; k < nlocal; ++k) { + xc += x[k][0]; + yc += x[k][1]; + if (x[k][2] > zmax) zmax = x[k][2]; + } + xc /= nlocal; + yc /= nlocal; + double rmax = 0.0; + for (int k = 0; k < nlocal; ++k) { + const double dx = x[k][0] - xc, dy = x[k][1] - yc; + const double rr = std::sqrt(dx * dx + dy * dy); + if (rr > rmax) rmax = rr; + } + const double angle = + (rmax > 0.0) ? std::atan((zmax - floor) / rmax) * 180.0 / MathConst::MY_PI : 90.0; + EXPECT_GE(angle, lo) << "angle_of_repose " << angle << " deg is below the band"; + EXPECT_LE(angle, hi) << "angle_of_repose " << angle << " deg is above the band"; + } else if (cfg.analytic_model == "hertz_normal_impact") { + // Elastic Hertzian normal impact at peak compression (Chung & Ooi 2011, + // Tests 1 & 2). This segment must be timed to land at peak compression, + // where the relative normal velocity is ~0 and all relative kinetic + // energy is stored as Hertzian elastic potential energy. For a contact + // force F = K delta^{3/2}, that PE is (2/5) K delta^{5/2} = (2/5) F delta, + // so (1/2) mu_red V_rela^2 = (2/5) P_max alpha_max. The 2/5 factor is + // the signature of the 3/2 power law (a linear spring would give 1/2); + // the relation is independent of the stiffness convention. mu_red is + // mred_factor * m (1/2 for two equal spheres, 1 for a sphere on a rigid + // wall) and V_rela is the relative approach speed (2*vin for two spheres, + // vin for a wall) -- both supplied via the variables block. + const double vrela = var_or(vars, "vrela", 0.0); + const double mredf = var_or(vars, "mred_factor", 1.0); + const double floor = var_or(vars, "floor", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "hertz_normal_impact: atom with tag 1 not found"; + const double m = lmp->atom->rmass[i]; + const double mred = mredf * m; + // peak overlap: two-sphere (tags 1,2) or sphere-on-wall (single atom) + double alpha; + if (lmp->atom->nlocal >= 2) { + const int j = find_local(lmp, 2); + ASSERT_GE(j, 0) << "hertz_normal_impact: atom with tag 2 not found"; + const double dx = lmp->atom->x[i][0] - lmp->atom->x[j][0]; + const double dy = lmp->atom->x[i][1] - lmp->atom->x[j][1]; + const double dz = lmp->atom->x[i][2] - lmp->atom->x[j][2]; + alpha = lmp->atom->radius[i] + lmp->atom->radius[j] - + std::sqrt(dx * dx + dy * dy + dz * dz); + } else { + alpha = lmp->atom->radius[i] - (lmp->atom->x[i][2] - floor); + } + ASSERT_GT(alpha, 0.0) << "hertz_normal_impact: atoms not in contact (segment " + "not timed at peak compression?)"; + const double fx = lmp->atom->f[i][0]; + const double fy = lmp->atom->f[i][1]; + const double fz = lmp->atom->f[i][2]; + const double pmax = std::sqrt(fx * fx + fy * fy + fz * fz); + const double ke = 0.5 * mred * vrela * vrela; + const double pe = 0.4 * pmax * alpha; // (2/5) P_max alpha_max + expect_rel(ke, pe, cfg.analytic_tol, "hertz_normal_impact peak energy balance"); + } else if (cfg.analytic_model == "spin_impact") { + // A sphere (tag 1) impacts a much heavier/rigid partner -- a wall or a + // large dense sphere -- approaching normally in -z at speed vin while + // spinning about +y with omega0 (Chung & Ooi 2011, Tests 6 and 8). The + // spin gives a contact-point tangential velocity ~r*omega0 along x; in + // the gross-sliding regime the Coulomb friction impulse mu(1+en) vin + // (per unit mass) acts throughout contact, so for the spinning sphere + // vz_out = en vin (rebound), + // vx_out = mu (1+en) vin, + // omega_y_out = omega0 - (5/2) mu (1+en) vin / r. + // Evaluate at a free-flight segment after rebound (needs omega0 large + // enough that the contact never sticks). + const double vin = var_or(vars, "vin", 0.0); + const double w0 = var_or(vars, "omega0", 0.0); + const double en = var_or(vars, "en", 1.0); + const double mu = var_or(vars, "xmu", 0.0); + const double r = var_or(vars, "radius", 0.0); + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "spin_impact: atom with tag 1 not found"; + const double dvt = mu * (1.0 + en) * vin; + expect_rel(en * vin, lmp->atom->v[i][2], cfg.analytic_tol, "spin_impact vz_out"); + expect_rel(dvt, lmp->atom->v[i][0], cfg.analytic_tol, "spin_impact vx_out"); + expect_rel(w0 - 2.5 * dvt / r, lmp->atom->omega[i][1], cfg.analytic_tol, + "spin_impact omega_y"); + } else if (cfg.analytic_model == "spin_no_friction") { + // Two identical spheres (tags 1,2) collide head-on along z while spinning + // about y with equal and opposite omega0, arranged so the relative + // tangential velocity at the contact point is zero (Chung & Ooi 2011, + // Test 7). No tangential force should be generated: each sphere's spin + // is preserved and it gains no tangential (x,y) velocity. This guards + // against a model spuriously creating friction from spin alone. + const double w0 = var_or(vars, "omega0", 0.0); + const double tol = cfg.analytic_tol; + const int i = find_local(lmp, 1); + ASSERT_GE(i, 0) << "spin_no_friction: atom with tag 1 not found"; + expect_rel(w0, lmp->atom->omega[i][1], tol, "spin_no_friction omega_y preserved"); + EXPECT_LE(std::fabs(lmp->atom->v[i][0]), tol) << "spin_no_friction: spurious vx"; + EXPECT_LE(std::fabs(lmp->atom->v[i][1]), tol) << "spin_no_friction: spurious vy"; + } else { + ADD_FAILURE() << "unknown analytic_model: '" << cfg.analytic_model << "'"; + } +} diff --git a/unittest/granular/test_analytic_models.h b/unittest/granular/test_analytic_models.h new file mode 100644 index 00000000000..1bf6267b22b --- /dev/null +++ b/unittest/granular/test_analytic_models.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- ---------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#ifndef TEST_ANALYTIC_MODELS_H +#define TEST_ANALYTIC_MODELS_H + +#include "test_config.h" + +namespace LAMMPS_NS { +class LAMMPS; +} + +// Evaluate the closed-form ("analytic") model selected in the YAML config +// after run segment `segment` has completed. Does nothing unless +// cfg.analytic_enable is set and `segment` matches cfg.analytic_segment +// (a negative analytic_segment means "the last segment"). Parameters are +// taken from the cfg.variables block; the relevant per-atom state is read +// from the live LAMMPS instance and compared with cfg.analytic_tol. +void check_analytic_model(const TestConfig &cfg, LAMMPS_NS::LAMMPS *lmp, int segment); + +#endif diff --git a/unittest/granular/test_config.h b/unittest/granular/test_config.h new file mode 100644 index 00000000000..48068d5e1e2 --- /dev/null +++ b/unittest/granular/test_config.h @@ -0,0 +1,136 @@ +/* -*- c++ -*- ---------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +#include +#include +#include +#include +#include + +struct coord_t { + double x, y, z; +}; + +struct stress_t { + double xx, yy, zz, xy, xz, yz; +}; + +class TestConfig { +public: + std::string lammps_version; + std::string date_generated; + std::string basename; + double epsilon; + std::set skip_tests; + std::vector> prerequisites; + std::vector pre_commands; + std::vector post_commands; + std::vector tags; + std::string input_file; + std::string pair_style; + std::string bond_style; + std::string angle_style; + std::string dihedral_style; + std::string improper_style; + std::string kspace_style; + std::vector pair_coeff; + std::vector bond_coeff; + std::vector angle_coeff; + std::vector dihedral_coeff; + std::vector improper_coeff; + std::vector equilibrium; + std::vector> extract; + // granular/DEM specific: ${var} substitution and multi-segment runs + std::vector> variables; + std::vector run_segments; + // optional analytic (closed-form) verification + bool analytic_enable; + std::string analytic_model; + double analytic_tol; + int analytic_segment; + // when true, record/compare only the analytic check (no per-atom regression). + // used for chaotic bulk tests (e.g. angle of repose) whose trajectories are not + // bit-reproducible across newton on/off or platforms -- only the bulk analytic + // observable is robust. The generator then omits the run_pos/run_vel/... blocks. + bool analytic_only; + int natoms; + double init_energy; + double run_energy; + double init_vdwl; + double run_vdwl; + double init_coul; + double run_coul; + stress_t init_stress; + stress_t run_stress; + double global_scalar; + std::vector global_vector; + std::vector init_forces; + std::vector run_forces; + // per-segment captured state, indexed [segment][tag] + std::vector> seg_pos; + std::vector> seg_vel; + std::vector> seg_torque; + std::vector> seg_omega; + std::vector> seg_angmom; + + TestConfig() : + lammps_version(""), date_generated(""), basename(""), epsilon(1.0e-14), input_file(""), + pair_style("zero"), bond_style("zero"), angle_style("zero"), dihedral_style("zero"), + improper_style("zero"), kspace_style("none"), analytic_enable(false), analytic_model(""), + analytic_tol(1.0e-2), analytic_segment(-1), analytic_only(false), natoms(0), init_energy(0), + run_energy(0), + init_vdwl(0), run_vdwl(0), init_coul(0), run_coul(0), init_stress({0, 0, 0, 0, 0, 0}), + run_stress({0, 0, 0, 0, 0, 0}), global_scalar(0) + { + skip_tests.clear(); + prerequisites.clear(); + pre_commands.clear(); + post_commands.clear(); + pair_coeff.clear(); + bond_coeff.clear(); + angle_coeff.clear(); + dihedral_coeff.clear(); + improper_coeff.clear(); + extract.clear(); + variables.clear(); + run_segments.clear(); + init_forces.clear(); + run_forces.clear(); + seg_pos.clear(); + seg_vel.clear(); + seg_torque.clear(); + seg_omega.clear(); + seg_angmom.clear(); + global_vector.clear(); + } + TestConfig(const TestConfig &) = delete; + TestConfig &operator=(const TestConfig &) = delete; + + [[nodiscard]] std::string tags_line() const + { + if (tags.size() > 0) { + std::stringstream line; + line << tags[0]; + for (size_t i = 1; i < tags.size(); i++) { + line << ", " << tags[i]; + } + return line.str(); + } + return "generated"; + } +}; + +#endif diff --git a/unittest/granular/test_config_reader.cpp b/unittest/granular/test_config_reader.cpp new file mode 100644 index 00000000000..9a730f9c7d9 --- /dev/null +++ b/unittest/granular/test_config_reader.cpp @@ -0,0 +1,468 @@ +/* ---------------------------------------------------------------------- + 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 "test_config_reader.h" +#include "test_config.h" +#include "utils.h" +#include "yaml.h" + +#include + +#include +#include +#include +#include +#include +#include + +using LAMMPS_NS::utils::split_words; +using LAMMPS_NS::utils::trim; + +TestConfigReader::TestConfigReader(TestConfig &config) : config(config) +{ + consumers["lammps_version"] = &TestConfigReader::lammps_version; + consumers["tags"] = &TestConfigReader::tags; + consumers["date_generated"] = &TestConfigReader::date_generated; + consumers["epsilon"] = &TestConfigReader::epsilon; + consumers["skip_tests"] = &TestConfigReader::skip_tests; + consumers["prerequisites"] = &TestConfigReader::prerequisites; + consumers["pre_commands"] = &TestConfigReader::pre_commands; + consumers["post_commands"] = &TestConfigReader::post_commands; + consumers["input_file"] = &TestConfigReader::input_file; + consumers["extract"] = &TestConfigReader::extract; + consumers["natoms"] = &TestConfigReader::natoms; + consumers["init_stress"] = &TestConfigReader::init_stress; + consumers["run_stress"] = &TestConfigReader::run_stress; + consumers["init_forces"] = &TestConfigReader::init_forces; + consumers["run_forces"] = &TestConfigReader::run_forces; + consumers["run_pos"] = &TestConfigReader::run_pos; + consumers["run_vel"] = &TestConfigReader::run_vel; + consumers["run_torque"] = &TestConfigReader::run_torque; + consumers["run_omega"] = &TestConfigReader::run_omega; + consumers["run_angmom"] = &TestConfigReader::run_angmom; + + consumers["variables"] = &TestConfigReader::variables; + consumers["run_segments"] = &TestConfigReader::run_segments; + consumers["analytic_enable"] = &TestConfigReader::analytic_enable; + consumers["analytic_model"] = &TestConfigReader::analytic_model; + consumers["analytic_tol"] = &TestConfigReader::analytic_tol; + consumers["analytic_segment"] = &TestConfigReader::analytic_segment; + consumers["analytic_only"] = &TestConfigReader::analytic_only; + + consumers["pair_style"] = &TestConfigReader::pair_style; + consumers["pair_coeff"] = &TestConfigReader::pair_coeff; + consumers["init_vdwl"] = &TestConfigReader::init_vdwl; + consumers["init_coul"] = &TestConfigReader::init_coul; + consumers["run_vdwl"] = &TestConfigReader::run_vdwl; + consumers["run_coul"] = &TestConfigReader::run_coul; + + consumers["global_scalar"] = &TestConfigReader::global_scalar; + consumers["global_vector"] = &TestConfigReader::global_vector; + + consumers["bond_style"] = &TestConfigReader::bond_style; + consumers["bond_coeff"] = &TestConfigReader::bond_coeff; + consumers["angle_style"] = &TestConfigReader::angle_style; + consumers["angle_coeff"] = &TestConfigReader::angle_coeff; + consumers["dihedral_style"] = &TestConfigReader::dihedral_style; + consumers["dihedral_coeff"] = &TestConfigReader::dihedral_coeff; + consumers["improper_style"] = &TestConfigReader::improper_style; + consumers["improper_coeff"] = &TestConfigReader::improper_coeff; + consumers["init_energy"] = &TestConfigReader::init_energy; + consumers["run_energy"] = &TestConfigReader::run_energy; + consumers["equilibrium"] = &TestConfigReader::equilibrium; +} + +void TestConfigReader::skip_tests(const yaml_event_t &event) +{ + config.skip_tests.clear(); + for (auto &word : split_words((char *)event.data.scalar.value)) + config.skip_tests.insert(word); +} + +void TestConfigReader::prerequisites(const yaml_event_t &event) +{ + config.prerequisites.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string key, value; + + while (true) { + data >> key >> value; + if (data.eof()) break; + config.prerequisites.emplace_back(key, value); + } +} + +void TestConfigReader::pre_commands(const yaml_event_t &event) +{ + config.pre_commands.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.pre_commands.push_back(line); + } +} + +void TestConfigReader::post_commands(const yaml_event_t &event) +{ + config.post_commands.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.post_commands.push_back(line); + } +} + +void TestConfigReader::lammps_version(const yaml_event_t &event) +{ + config.lammps_version = (char *)event.data.scalar.value; +} + +void TestConfigReader::date_generated(const yaml_event_t &event) +{ + config.date_generated = (char *)event.data.scalar.value; +} + +void TestConfigReader::epsilon(const yaml_event_t &event) +{ + config.epsilon = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::input_file(const yaml_event_t &event) +{ + config.input_file = (char *)event.data.scalar.value; +} + +void TestConfigReader::extract(const yaml_event_t &event) +{ + config.extract.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string name; + int value; + while (true) { + data >> name >> value; + if (data.eof()) break; + config.extract.emplace_back(name, value); + } +} + +void TestConfigReader::natoms(const yaml_event_t &event) +{ + config.natoms = atoi((char *)event.data.scalar.value); +} + +void TestConfigReader::init_stress(const yaml_event_t &event) +{ + stress_t stress; + sscanf((char *)event.data.scalar.value, "%lg %lg %lg %lg %lg %lg", &stress.xx, &stress.yy, + &stress.zz, &stress.xy, &stress.xz, &stress.yz); + config.init_stress = stress; +} + +void TestConfigReader::run_stress(const yaml_event_t &event) +{ + stress_t stress; + sscanf((char *)event.data.scalar.value, "%lg %lg %lg %lg %lg %lg", &stress.xx, &stress.yy, + &stress.zz, &stress.xy, &stress.xz, &stress.yz); + config.run_stress = stress; +} + +void TestConfigReader::init_forces(const yaml_event_t &event) +{ + config.init_forces.clear(); + config.init_forces.resize(config.natoms + 1); + std::stringstream data((const char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + int tag = 0; + coord_t xyz; + sscanf(line.c_str(), "%d %lg %lg %lg", &tag, &xyz.x, &xyz.y, &xyz.z); + config.init_forces[tag] = xyz; + } +} + +void TestConfigReader::run_forces(const yaml_event_t &event) +{ + config.run_forces.clear(); + config.run_forces.resize(config.natoms + 1); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + int tag; + coord_t xyz; + sscanf(line.c_str(), "%d %lg %lg %lg", &tag, &xyz.x, &xyz.y, &xyz.z); + config.run_forces[tag] = xyz; + } +} + +// parse a multi-segment per-atom block. Each line is "segment tag x y z"; +// rows are routed into target[segment][tag], growing the storage as needed. +static void parse_segment_block(std::vector> &target, const char *value) +{ + target.clear(); + std::stringstream data(value); + std::string line; + + while (std::getline(data, line, '\n')) { + int seg = 0, tag = 0; + coord_t xyz{0.0, 0.0, 0.0}; + if (sscanf(line.c_str(), "%d %d %lg %lg %lg", &seg, &tag, &xyz.x, &xyz.y, &xyz.z) != 5) + continue; + if ((seg < 0) || (tag < 0)) continue; + if ((int)target.size() <= seg) target.resize(seg + 1); + if ((int)target[seg].size() <= tag) target[seg].resize(tag + 1); + target[seg][tag] = xyz; + } +} + +void TestConfigReader::run_pos(const yaml_event_t &event) +{ + parse_segment_block(config.seg_pos, (const char *)event.data.scalar.value); +} + +void TestConfigReader::run_vel(const yaml_event_t &event) +{ + parse_segment_block(config.seg_vel, (const char *)event.data.scalar.value); +} + +void TestConfigReader::run_torque(const yaml_event_t &event) +{ + parse_segment_block(config.seg_torque, (const char *)event.data.scalar.value); +} + +void TestConfigReader::run_omega(const yaml_event_t &event) +{ + parse_segment_block(config.seg_omega, (const char *)event.data.scalar.value); +} + +void TestConfigReader::run_angmom(const yaml_event_t &event) +{ + parse_segment_block(config.seg_angmom, (const char *)event.data.scalar.value); +} + +void TestConfigReader::variables(const yaml_event_t &event) +{ + config.variables.clear(); + std::stringstream data((const char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + std::stringstream parts(line); + std::string name, value; + parts >> name; + if (name.empty()) continue; + // the value is the remainder of the line (may contain spaces) + std::getline(parts, value); + value = trim(value); + config.variables.emplace_back(name, value); + } +} + +void TestConfigReader::run_segments(const yaml_event_t &event) +{ + config.run_segments.clear(); + std::stringstream data((const char *)event.data.scalar.value); + std::string word; + + while (data >> word) { + try { + config.run_segments.push_back(std::stoi(word)); + } catch (std::exception &) { + // ignore non-integer tokens + } + } +} + +void TestConfigReader::analytic_enable(const yaml_event_t &event) +{ + const std::string value = trim((const char *)event.data.scalar.value); + config.analytic_enable = + (value == "yes") || (value == "true") || (value == "on") || (value == "1"); +} + +void TestConfigReader::analytic_model(const yaml_event_t &event) +{ + config.analytic_model = trim((const char *)event.data.scalar.value); +} + +void TestConfigReader::analytic_tol(const yaml_event_t &event) +{ + config.analytic_tol = atof((const char *)event.data.scalar.value); +} + +void TestConfigReader::analytic_segment(const yaml_event_t &event) +{ + config.analytic_segment = atoi((const char *)event.data.scalar.value); +} + +void TestConfigReader::analytic_only(const yaml_event_t &event) +{ + const std::string value = trim((const char *)event.data.scalar.value); + config.analytic_only = + (value == "yes") || (value == "true") || (value == "on") || (value == "1"); +} + +void TestConfigReader::pair_style(const yaml_event_t &event) +{ + config.pair_style = (char *)event.data.scalar.value; +} + +void TestConfigReader::pair_coeff(const yaml_event_t &event) +{ + config.pair_coeff.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.pair_coeff.push_back(line); + } +} + +void TestConfigReader::bond_style(const yaml_event_t &event) +{ + config.bond_style = (char *)event.data.scalar.value; +} + +void TestConfigReader::bond_coeff(const yaml_event_t &event) +{ + config.bond_coeff.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.bond_coeff.push_back(line); + } +} + +void TestConfigReader::angle_style(const yaml_event_t &event) +{ + config.angle_style = (char *)event.data.scalar.value; +} + +void TestConfigReader::angle_coeff(const yaml_event_t &event) +{ + config.angle_coeff.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.angle_coeff.push_back(line); + } +} + +void TestConfigReader::dihedral_style(const yaml_event_t &event) +{ + config.dihedral_style = (char *)event.data.scalar.value; +} + +void TestConfigReader::dihedral_coeff(const yaml_event_t &event) +{ + config.dihedral_coeff.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.dihedral_coeff.push_back(line); + } +} + +void TestConfigReader::improper_style(const yaml_event_t &event) +{ + config.improper_style = (char *)event.data.scalar.value; +} + +void TestConfigReader::improper_coeff(const yaml_event_t &event) +{ + config.improper_coeff.clear(); + std::stringstream data((char *)event.data.scalar.value); + std::string line; + + while (std::getline(data, line, '\n')) { + config.improper_coeff.push_back(line); + } +} + +void TestConfigReader::equilibrium(const yaml_event_t &event) +{ + std::stringstream data((char *)event.data.scalar.value); + config.equilibrium.clear(); + double value; + std::size_t num; + data >> num; + for (std::size_t i = 0; i < num; ++i) { + data >> value; + if (data.eof()) break; + config.equilibrium.push_back(value); + } +} + +void TestConfigReader::init_vdwl(const yaml_event_t &event) +{ + config.init_vdwl = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::init_coul(const yaml_event_t &event) +{ + config.init_coul = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::run_vdwl(const yaml_event_t &event) +{ + config.run_vdwl = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::run_coul(const yaml_event_t &event) +{ + config.run_coul = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::init_energy(const yaml_event_t &event) +{ + config.init_energy = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::run_energy(const yaml_event_t &event) +{ + config.run_energy = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::global_scalar(const yaml_event_t &event) +{ + config.global_scalar = atof((char *)event.data.scalar.value); +} + +void TestConfigReader::global_vector(const yaml_event_t &event) +{ + std::stringstream data((char *)event.data.scalar.value); + config.global_vector.clear(); + double value; + std::size_t num; + data >> num; + for (std::size_t i = 0; i < num; ++i) { + data >> value; + config.global_vector.push_back(value); + } +} + +void TestConfigReader::tags(const yaml_event_t &event) +{ + std::stringstream data((char *)event.data.scalar.value); + config.tags.clear(); + for (std::string tag; std::getline(data, tag, ' ');) { + const auto addme = trim(tag); + if (addme.size() > 0) config.tags.push_back(addme); + } +} diff --git a/unittest/granular/test_config_reader.h b/unittest/granular/test_config_reader.h new file mode 100644 index 00000000000..c5f04e743c7 --- /dev/null +++ b/unittest/granular/test_config_reader.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- ---------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#ifndef TEST_CONFIG_READER_H +#define TEST_CONFIG_READER_H + +#include "test_config.h" +#include "../yaml_reader.h" + +class TestConfigReader : public YamlReader { + TestConfig &config; + +public: + TestConfigReader(TestConfig &config); + TestConfigReader() = delete; + const TestConfigReader &operator=(TestConfig &) = delete; + + void skip_tests(const yaml_event_t &event); + void prerequisites(const yaml_event_t &event); + void pre_commands(const yaml_event_t &event); + void post_commands(const yaml_event_t &event); + void lammps_version(const yaml_event_t &event); + void date_generated(const yaml_event_t &event); + void epsilon(const yaml_event_t &event); + void input_file(const yaml_event_t &event); + void extract(const yaml_event_t &event); + void natoms(const yaml_event_t &event); + void init_stress(const yaml_event_t &event); + void run_stress(const yaml_event_t &event); + void init_forces(const yaml_event_t &event); + void run_forces(const yaml_event_t &event); + void run_pos(const yaml_event_t &event); + void run_vel(const yaml_event_t &event); + void run_torque(const yaml_event_t &event); + void run_omega(const yaml_event_t &event); + void run_angmom(const yaml_event_t &event); + void variables(const yaml_event_t &event); + void run_segments(const yaml_event_t &event); + void analytic_enable(const yaml_event_t &event); + void analytic_model(const yaml_event_t &event); + void analytic_tol(const yaml_event_t &event); + void analytic_segment(const yaml_event_t &event); + void analytic_only(const yaml_event_t &event); + void pair_style(const yaml_event_t &event); + void pair_coeff(const yaml_event_t &event); + void bond_style(const yaml_event_t &event); + void bond_coeff(const yaml_event_t &event); + void angle_style(const yaml_event_t &event); + void angle_coeff(const yaml_event_t &event); + void dihedral_style(const yaml_event_t &event); + void dihedral_coeff(const yaml_event_t &event); + void improper_style(const yaml_event_t &event); + void improper_coeff(const yaml_event_t &event); + void equilibrium(const yaml_event_t &event); + void init_vdwl(const yaml_event_t &event); + void init_coul(const yaml_event_t &event); + void run_vdwl(const yaml_event_t &event); + void run_coul(const yaml_event_t &event); + void init_energy(const yaml_event_t &event); + void run_energy(const yaml_event_t &event); + void global_scalar(const yaml_event_t &event); + void global_vector(const yaml_event_t &event); + void tags(const yaml_event_t &event); +}; + +#endif diff --git a/unittest/granular/test_dem_01.cpp b/unittest/granular/test_dem_01.cpp new file mode 100644 index 00000000000..645f5bbc4e9 --- /dev/null +++ b/unittest/granular/test_dem_01.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 01: sphere sliding then rolling without slipping on a rough wall. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem01-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem01, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem01, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_02.cpp b/unittest/granular/test_dem_02.cpp new file mode 100644 index 00000000000..4aea1e37786 --- /dev/null +++ b/unittest/granular/test_dem_02.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 02: oblique collision of a sphere with a flat wall. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem02-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem02, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem02, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_03.cpp b/unittest/granular/test_dem_03.cpp new file mode 100644 index 00000000000..9bde2a74114 --- /dev/null +++ b/unittest/granular/test_dem_03.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 03: a spinning sphere damped to rest by rolling resistance (rolling sds). +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem03-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem03, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem03, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_04.cpp b/unittest/granular/test_dem_04.cpp new file mode 100644 index 00000000000..1d000515d4d --- /dev/null +++ b/unittest/granular/test_dem_04.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 04: cohesive/adhesive contact -- the DMT pull-off force. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem04-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem04, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem04, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_05.cpp b/unittest/granular/test_dem_05.cpp new file mode 100644 index 00000000000..e40360600dc --- /dev/null +++ b/unittest/granular/test_dem_05.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 05: two identical spinning spheres, head-on collision. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem05-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem05, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem05, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_06.cpp b/unittest/granular/test_dem_06.cpp new file mode 100644 index 00000000000..e3df7783b25 --- /dev/null +++ b/unittest/granular/test_dem_06.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 06: an unequal-size spinning sphere impacting a heavy/rigid partner. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem06-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem06, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem06, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_07.cpp b/unittest/granular/test_dem_07.cpp new file mode 100644 index 00000000000..077ee167731 --- /dev/null +++ b/unittest/granular/test_dem_07.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 07: elastic Hertzian normal impact of a sphere on a wall. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem07-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem07, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem07, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_08.cpp b/unittest/granular/test_dem_08.cpp new file mode 100644 index 00000000000..24c5f926bf2 --- /dev/null +++ b/unittest/granular/test_dem_08.cpp @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// DEM verification test 08: elastic Hertzian normal impact of two spheres. +// All test logic is shared via test_dem_common; the reference systems +// live in tests/dem08-*.yaml. + +#include "test_dem_common.h" +#include "test_main.h" + +#include "info.h" + +#include "gtest/gtest.h" + +using namespace LAMMPS_NS; + +TEST(Dem08, newton_on) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(true, "newton on"); +} + +TEST(Dem08, newton_off) +{ + if (!Info::has_package("GRANULAR")) GTEST_SKIP(); + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + run_dem_trajectory_test(false, "newton off"); +} diff --git a/unittest/granular/test_dem_common.cpp b/unittest/granular/test_dem_common.cpp new file mode 100644 index 00000000000..000d8a3ca14 --- /dev/null +++ b/unittest/granular/test_dem_common.cpp @@ -0,0 +1,301 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +// Shared implementation for the DEM verification test drivers +// (test_dem_01 ... test_dem_11). Every driver builds its system entirely +// from the YAML file: a 'variables' block provides ${var} substitution, +// 'pre_commands' create the geometry, 'pair_style'/'pair_coeff' set the +// contact model, and 'post_commands' add the integrator, gravity and walls. +// The trajectory is run in segments ('run_segments') and per-atom positions, +// velocities, torques and angular velocities are compared against the +// recorded reference after each segment, together with any analytic model +// selected in the YAML. Driver-specific behaviour lives in the YAML files +// and in test_analytic_models.cpp, so the drivers themselves only differ in +// the GoogleTest suite name. + +#include "test_dem_common.h" + +#include "test_analytic_models.h" +#include "test_config.h" +#include "test_main.h" +#include "yaml_writer.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "atom.h" +#include "force.h" +#include "info.h" +#include "input.h" + +#include "fmt/format.h" + +#include +#include +#include +#include + +using ::testing::HasSubstr; +using ::testing::StartsWith; + +using namespace LAMMPS_NS; + +static void cleanup_lammps(LAMMPS *&lmp, const TestConfig &cfg) +{ + (void) cfg; + delete lmp; + lmp = nullptr; +} + +static LAMMPS *init_lammps(LAMMPS::argv &args, const TestConfig &cfg, const bool newton) +{ + LAMMPS *lmp = new LAMMPS(args, MPI_COMM_WORLD); + + // check if prerequisite styles are available + Info *info = new Info(lmp); + int nfail = 0; + for (const auto &prerequisite : cfg.prerequisites) { + if (!info->has_style(prerequisite.first, prerequisite.second)) ++nfail; + } + delete info; + if (nfail > 0) { + cleanup_lammps(lmp, cfg); + return nullptr; + } + + // utility lambda to improve readability + auto command = [&](const std::string &line) { + lmp->input->one(line); + }; + + // newton must be set before the simulation box is created in pre_commands + command(newton ? "newton on" : "newton off"); + command("variable input_dir index " + INPUT_FOLDER); + + // user-defined variables enable ${var} substitution in all command strings + for (const auto &var : cfg.variables) + command("variable " + var.first + " index " + var.second); + + // build the system geometry (units, atom_style, region, create_atoms, set, ...) + for (const auto &pre_command : cfg.pre_commands) + command(pre_command); + + // contact model + command("pair_style " + cfg.pair_style); + for (const auto &pair_coeff : cfg.pair_coeff) + command("pair_coeff " + pair_coeff); + + // integrator, gravity, walls, ... + for (const auto &post_command : cfg.post_commands) + command(post_command); + + command("run 0 post no"); + return lmp; +} + +// run all segments and compare per-atom state against the reference after each +static void run_and_check(LAMMPS *lmp, const TestConfig &cfg, double epsilon, + const std::string &label) +{ + auto command = [&](const std::string &line) { + lmp->input->one(line); + }; + + const bool has_torque = lmp->atom->torque_flag; + const bool has_omega = lmp->atom->omega_flag; + const bool has_angmom = lmp->atom->angmom_flag; + + for (std::size_t i = 0; i < cfg.run_segments.size(); ++i) { + command("run " + std::to_string(cfg.run_segments[i]) + " post no"); + const std::string tag = label + ", seg " + std::to_string(i); + + if (i < cfg.seg_pos.size()) + EXPECT_POSITIONS("run_pos (" + tag + ")", lmp->atom, cfg.seg_pos[i], epsilon); + if (i < cfg.seg_vel.size()) + EXPECT_VELOCITIES("run_vel (" + tag + ")", lmp->atom, cfg.seg_vel[i], epsilon); + if (has_torque && (i < cfg.seg_torque.size())) + EXPECT_TORQUES("run_torque (" + tag + ")", lmp->atom, cfg.seg_torque[i], epsilon); + if (has_omega && (i < cfg.seg_omega.size())) + EXPECT_OMEGA("run_omega (" + tag + ")", lmp->atom, cfg.seg_omega[i], epsilon); + if (has_angmom && (i < cfg.seg_angmom.size())) + EXPECT_ANGMOM("run_angmom (" + tag + ")", lmp->atom, cfg.seg_angmom[i], epsilon); + + check_analytic_model(cfg, lmp, (int) i); + } +} + +// re-generate yaml file with current settings. + +void generate_yaml_file(const char *outfile, const TestConfig &config) +{ + LAMMPS::argv args = {"DEM", "-log", "none", "-echo", "screen", "-nocite"}; + LAMMPS *lmp = nullptr; + try { + lmp = init_lammps(args, config, true); + } catch (std::exception &e) { + FAIL() << e.what(); + } + if (!lmp) { + std::cerr << "One or more prerequisite styles are not available " + "in this LAMMPS configuration:\n"; + for (auto prerequisite : config.prerequisites) + std::cerr << prerequisite.first << "_style " << prerequisite.second << "\n"; + return; + } + + const int natoms = lmp->atom->natoms; + YamlWriter writer(outfile); + + // write yaml header + write_yaml_header(&writer, &test_config, lmp->version); + + // natoms + writer.emit("natoms", natoms); + + // variables block (echo back verbatim) + std::string block; + for (const auto &var : config.variables) + block += var.first + " " + var.second + "\n"; + writer.emit_block("variables", block); + + // pair style and coefficients + writer.emit("pair_style", config.pair_style); + block.clear(); + for (const auto &pair_coeff : config.pair_coeff) + block += pair_coeff + "\n"; + writer.emit_block("pair_coeff", block); + + // run segments + block.clear(); + for (std::size_t i = 0; i < config.run_segments.size(); ++i) { + if (i) block += " "; + block += std::to_string(config.run_segments[i]); + } + writer.emit_block("run_segments", block); + + // optional analytic check flags (echo back if enabled) + if (config.analytic_enable) { + writer.emit("analytic_enable", std::string("yes")); + writer.emit("analytic_model", config.analytic_model); + writer.emit("analytic_tol", config.analytic_tol); + writer.emit("analytic_segment", (long) config.analytic_segment); + if (config.analytic_only) writer.emit("analytic_only", std::string("yes")); + } + + auto command = [&](const std::string &line) { + lmp->input->one(line); + }; + + // For analytic-only (chaotic bulk) tests -- e.g. angle of repose -- the + // trajectory is not bit-reproducible across newton on/off or platforms, so + // we record no per-atom reference. Only the bulk analytic observable is + // robust; it is checked live during the test (check_analytic_model). We + // still execute the run segments so the reference reflects a completed run. + if (config.analytic_only) { + for (std::size_t i = 0; i < config.run_segments.size(); ++i) + command("run " + std::to_string(config.run_segments[i]) + " post no"); + cleanup_lammps(lmp, config); + return; + } + + const bool has_torque = lmp->atom->torque_flag; + const bool has_omega = lmp->atom->omega_flag; + const bool has_angmom = lmp->atom->angmom_flag; + std::string pos_block, vel_block, torque_block, omega_block, angmom_block; + + // iterate over local atoms by tag; granular/atomic systems have no atom map. + // rows are keyed by (segment, tag), so the emission order is irrelevant. + for (std::size_t i = 0; i < config.run_segments.size(); ++i) { + command("run " + std::to_string(config.run_segments[i]) + " post no"); + auto *x = lmp->atom->x; + auto *v = lmp->atom->v; + auto *t = lmp->atom->torque; + auto *w = lmp->atom->omega; + auto *angmom = lmp->atom->angmom; + tagint *tag = lmp->atom->tag; + const int local = lmp->atom->nlocal; + for (int j = 0; j < local; ++j) { + const tagint id = tag[j]; + pos_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, x[j][0], + x[j][1], x[j][2]); + vel_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, v[j][0], + v[j][1], v[j][2]); + if (has_torque) + torque_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, + t[j][0], t[j][1], t[j][2]); + if (has_omega) + omega_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, + w[j][0], w[j][1], w[j][2]); + if (has_angmom) + angmom_block += fmt::format("{:3} {:3} {:23.16e} {:23.16e} {:23.16e}\n", i, id, + angmom[j][0], angmom[j][1], angmom[j][2]); + } + } + writer.emit_block("run_pos", pos_block); + writer.emit_block("run_vel", vel_block); + if (has_torque) writer.emit_block("run_torque", torque_block); + if (has_omega) writer.emit_block("run_omega", omega_block); + if (has_angmom) writer.emit_block("run_angmom", angmom_block); + + cleanup_lammps(lmp, config); +} + +void run_dem_trajectory_test(bool newton, const std::string &label) +{ + LAMMPS::argv args = {"DEM", "-log", "none", "-echo", "screen", "-nocite"}; + + ::testing::internal::CaptureStdout(); + LAMMPS *lmp = nullptr; + try { + lmp = init_lammps(args, test_config, newton); + } catch (std::exception &e) { + std::string output = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << output; + FAIL() << e.what(); + } + std::string output = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << output; + + if (!lmp) { + std::cerr << "One or more prerequisite styles are not available " + "in this LAMMPS configuration:\n"; + for (auto &prerequisite : test_config.prerequisites) + std::cerr << prerequisite.first << "_style " << prerequisite.second << "\n"; + GTEST_SKIP(); + } + + EXPECT_THAT(output, StartsWith("LAMMPS (")); + EXPECT_THAT(output, HasSubstr("Loop time")); + + // abort if running in parallel and not all atoms are local + const int nlocal = lmp->atom->nlocal; + ASSERT_EQ(lmp->atom->natoms, nlocal); + + // when requesting newton off, only compare if the pair style honored it + if (!newton && (lmp->force->newton_pair != 0)) { + if (!verbose) ::testing::internal::CaptureStdout(); + cleanup_lammps(lmp, test_config); + if (!verbose) ::testing::internal::GetCapturedStdout(); + GTEST_SKIP() << "pair style forces newton pair on"; + } + + double epsilon = test_config.epsilon; + + if (!verbose) ::testing::internal::CaptureStdout(); + run_and_check(lmp, test_config, epsilon, label); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + if (!verbose) ::testing::internal::CaptureStdout(); + cleanup_lammps(lmp, test_config); + if (!verbose) ::testing::internal::GetCapturedStdout(); +} diff --git a/unittest/granular/test_dem_common.h b/unittest/granular/test_dem_common.h new file mode 100644 index 00000000000..e1f0ae34c55 --- /dev/null +++ b/unittest/granular/test_dem_common.h @@ -0,0 +1,27 @@ +/* -*- c++ -*- ---------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#ifndef TEST_DEM_COMMON_H +#define TEST_DEM_COMMON_H + +#include + +// Shared trajectory-comparison body for all DEM test drivers. Builds a +// LAMMPS instance from the global test_config (newton on or off), runs the +// configured 'run_segments' and compares per-atom positions, velocities, +// torques and angular velocities -- plus any enabled analytic model -- +// against the recorded reference. The per-driver TEST() fixtures only set +// up the package/skip guards and then call this with the newton flag. +void run_dem_trajectory_test(bool newton, const std::string &label); + +#endif diff --git a/unittest/granular/test_main.cpp b/unittest/granular/test_main.cpp new file mode 100644 index 00000000000..e41f0fc847d --- /dev/null +++ b/unittest/granular/test_main.cpp @@ -0,0 +1,319 @@ +/* ---------------------------------------------------------------------- + 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 "test_main.h" + +#include "atom.h" +#include "error_stats.h" +#include "pointers.h" +#include "test_config.h" +#include "test_config_reader.h" +#include "yaml_writer.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include + +using LAMMPS_NS::Atom; +using LAMMPS_NS::LAMMPS; +using LAMMPS_NS::tagint; +using LAMMPS_NS::utils::split_words; +using LAMMPS_NS::utils::trim; + +void EXPECT_STRESS(const std::string &name, double *stress, const stress_t &expected_stress, + double epsilon) +{ + SCOPED_TRACE("EXPECT_STRESS: " + name); + ErrorStats stats; + EXPECT_FP_LE_WITH_EPS(stress[0], expected_stress.xx, epsilon); + EXPECT_FP_LE_WITH_EPS(stress[1], expected_stress.yy, epsilon); + EXPECT_FP_LE_WITH_EPS(stress[2], expected_stress.zz, epsilon); + EXPECT_FP_LE_WITH_EPS(stress[3], expected_stress.xy, epsilon); + EXPECT_FP_LE_WITH_EPS(stress[4], expected_stress.xz, epsilon); + EXPECT_FP_LE_WITH_EPS(stress[5], expected_stress.yz, epsilon); + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +void EXPECT_FORCES(const std::string &name, Atom *atom, const std::vector &f_ref, + double epsilon) +{ + SCOPED_TRACE("EXPECT_FORCES: " + name); + double **f = atom->f; + tagint *tag = atom->tag; + const int nlocal = atom->nlocal; + ASSERT_EQ(nlocal + 1, f_ref.size()); + ErrorStats stats; + for (int i = 0; i < nlocal; ++i) { + EXPECT_FP_LE_WITH_EPS(f[i][0], f_ref[tag[i]].x, epsilon); + EXPECT_FP_LE_WITH_EPS(f[i][1], f_ref[tag[i]].y, epsilon); + EXPECT_FP_LE_WITH_EPS(f[i][2], f_ref[tag[i]].z, epsilon); + } + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +void EXPECT_POSITIONS(const std::string &name, Atom *atom, const std::vector &x_ref, + double epsilon) +{ + SCOPED_TRACE("EXPECT_POSITIONS: " + name); + double **x = atom->x; + tagint *tag = atom->tag; + const int nlocal = atom->nlocal; + ASSERT_EQ(nlocal + 1, x_ref.size()); + ErrorStats stats; + for (int i = 0; i < nlocal; ++i) { + EXPECT_FP_LE_WITH_EPS(x[i][0], x_ref[tag[i]].x, epsilon); + EXPECT_FP_LE_WITH_EPS(x[i][1], x_ref[tag[i]].y, epsilon); + EXPECT_FP_LE_WITH_EPS(x[i][2], x_ref[tag[i]].z, epsilon); + } + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +void EXPECT_VELOCITIES(const std::string &name, Atom *atom, const std::vector &v_ref, + double epsilon) +{ + SCOPED_TRACE("EXPECT_VELOCITIES: " + name); + double **v = atom->v; + tagint *tag = atom->tag; + const int nlocal = atom->nlocal; + ASSERT_EQ(nlocal + 1, v_ref.size()); + ErrorStats stats; + for (int i = 0; i < nlocal; ++i) { + EXPECT_FP_LE_WITH_EPS(v[i][0], v_ref[tag[i]].x, epsilon); + EXPECT_FP_LE_WITH_EPS(v[i][1], v_ref[tag[i]].y, epsilon); + EXPECT_FP_LE_WITH_EPS(v[i][2], v_ref[tag[i]].z, epsilon); + } + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +void EXPECT_TORQUES(const std::string &name, Atom *atom, const std::vector &t_ref, + double epsilon) +{ + SCOPED_TRACE("EXPECT_TORQUES: " + name); + double **t = atom->torque; + tagint *tag = atom->tag; + const int nlocal = atom->nlocal; + ASSERT_EQ(nlocal + 1, t_ref.size()); + ErrorStats stats; + for (int i = 0; i < nlocal; ++i) { + EXPECT_FP_LE_WITH_EPS(t[i][0], t_ref[tag[i]].x, epsilon); + EXPECT_FP_LE_WITH_EPS(t[i][1], t_ref[tag[i]].y, epsilon); + EXPECT_FP_LE_WITH_EPS(t[i][2], t_ref[tag[i]].z, epsilon); + } + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +void EXPECT_OMEGA(const std::string &name, Atom *atom, const std::vector &w_ref, + double epsilon) +{ + SCOPED_TRACE("EXPECT_OMEGA: " + name); + double **w = atom->omega; + tagint *tag = atom->tag; + const int nlocal = atom->nlocal; + ASSERT_EQ(nlocal + 1, w_ref.size()); + ErrorStats stats; + for (int i = 0; i < nlocal; ++i) { + EXPECT_FP_LE_WITH_EPS(w[i][0], w_ref[tag[i]].x, epsilon); + EXPECT_FP_LE_WITH_EPS(w[i][1], w_ref[tag[i]].y, epsilon); + EXPECT_FP_LE_WITH_EPS(w[i][2], w_ref[tag[i]].z, epsilon); + } + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +void EXPECT_ANGMOM(const std::string &name, Atom *atom, const std::vector &l_ref, + double epsilon) +{ + SCOPED_TRACE("EXPECT_ANGMOM: " + name); + double **angmom = atom->angmom; + tagint *tag = atom->tag; + const int nlocal = atom->nlocal; + ASSERT_EQ(nlocal + 1, l_ref.size()); + ErrorStats stats; + for (int i = 0; i < nlocal; ++i) { + EXPECT_FP_LE_WITH_EPS(angmom[i][0], l_ref[tag[i]].x, epsilon); + EXPECT_FP_LE_WITH_EPS(angmom[i][1], l_ref[tag[i]].y, epsilon); + EXPECT_FP_LE_WITH_EPS(angmom[i][2], l_ref[tag[i]].z, epsilon); + } + if (print_stats) std::cerr << name << " stats: " << stats << std::endl; +} + +// common read_yaml_file function +bool read_yaml_file(const char *infile, TestConfig &config) +{ + auto reader = TestConfigReader(config); + if (reader.parse_file(infile)) return false; + + config.basename = reader.get_basename(); + return true; +} + +// write out common header items for yaml files +void write_yaml_header(YamlWriter *writer, TestConfig *cfg, const char *version) +{ + // lammps_version + writer->emit("lammps_version", version); + + // tags + writer->emit("tags", cfg->tags_line()); + + // date_generated + std::time_t now = time(nullptr); + std::string block = trim(ctime(&now)); + writer->emit("date_generated", block); + + // epsilon + writer->emit("epsilon", cfg->epsilon); + + // skip tests + block.clear(); + for (const auto &skip : cfg->skip_tests) { + if (block.empty()) + block = skip; + else + block += " " + skip; + } + writer->emit("skip_tests", block); + + // prerequisites + block.clear(); + for (auto &prerequisite : cfg->prerequisites) { + block += prerequisite.first + " " + prerequisite.second + "\n"; + } + writer->emit_block("prerequisites", block); + + // pre_commands + block.clear(); + for (auto &command : cfg->pre_commands) { + block += command + "\n"; + } + writer->emit_block("pre_commands", block); + + // post_commands + block.clear(); + for (auto &command : cfg->post_commands) { + block += command + "\n"; + } + writer->emit_block("post_commands", block); + + // input_file + writer->emit("input_file", cfg->input_file); +} + +// need to be defined in unit test body +extern void generate_yaml_file(const char *, const TestConfig &); + +void usage(std::ostream &out, const char *name) +{ + out << "usage: " << name << " [OPTIONS]\n\n" + << "Available options:\n" + << " -g regenerate yaml file under a new name\n" + << " -d set folder where to find input files\n" + << " -u update the original yaml file\n" + << " -v run tests with verbose output\n" + << " -s run tests with error statistics output\n" + << " -h print this message\n" + << std::endl; +} + +// test configuration settings read from yaml file +TestConfig test_config; + +// whether to print error statistics +bool print_stats = false; + +// whether to print verbose output (i.e. not capturing LAMMPS screen output). +bool verbose = false; + +// location for 'in.*' and 'data.*' files required by tests +#define STRINGIFY(val) XSTR(val) +#define XSTR(val) #val +std::string INPUT_FOLDER = STRINGIFY(TEST_INPUT_FOLDER); + +int main(int argc, char **argv) +{ + MPI_Init(&argc, &argv); + ::testing::InitGoogleMock(&argc, argv); + + if (argc < 2) { + usage(std::cerr, argv[0]); + return 1; + } + + if (!read_yaml_file(argv[1], test_config)) { + std::cerr << "Error parsing yaml file: " << argv[1] << std::endl; + return 2; + } + + // handle arguments passed via environment variable + if (const char *var = getenv("TEST_ARGS")) { + std::vector env = split_words(var); + for (auto arg : env) { + if (arg == "-u") { + generate_yaml_file(argv[1], test_config); + return 0; + } else if (arg == "-s") { + print_stats = true; + } else if (arg == "-v") { + verbose = true; + } + } + } + + int iarg = 2; + while (iarg < argc) { + + if (strcmp(argv[iarg], "-g") == 0) { + if (iarg + 1 < argc) { + generate_yaml_file(argv[iarg + 1], test_config); + MPI_Finalize(); + return 0; + } else { + usage(std::cerr, argv[0]); + MPI_Finalize(); + return 1; + } + } else if (strcmp(argv[iarg], "-u") == 0) { + generate_yaml_file(argv[1], test_config); + MPI_Finalize(); + return 0; + } else if (strcmp(argv[iarg], "-d") == 0) { + if (iarg + 1 < argc) { + INPUT_FOLDER = argv[iarg + 1]; + iarg += 2; + } else { + usage(std::cerr, argv[0]); + MPI_Finalize(); + return 1; + } + } else if (strcmp(argv[iarg], "-s") == 0) { + print_stats = true; + ++iarg; + } else if (strcmp(argv[iarg], "-v") == 0) { + verbose = true; + ++iarg; + } else { + std::cerr << "unknown option: " << argv[iarg] << "\n\n"; + usage(std::cerr, argv[0]); + MPI_Finalize(); + return 1; + } + } + + int rv = RUN_ALL_TESTS(); + MPI_Finalize(); + return rv; +} diff --git a/unittest/granular/test_main.h b/unittest/granular/test_main.h new file mode 100644 index 00000000000..b7263e197fa --- /dev/null +++ b/unittest/granular/test_main.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- ---------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#ifndef TEST_MAIN_H +#define TEST_MAIN_H + +#include "pointers.h" + +#include "gtest/gtest.h" +#include "test_config.h" + +#include +#include +#include + +extern TestConfig test_config; +extern bool print_stats; +extern bool verbose; +extern std::string INPUT_FOLDER; + +// convenience method to write out common entries +void write_yaml_header(class YamlWriter *writer, TestConfig *cfg, const char *version); + +#define EXPECT_FP_LE_WITH_EPS(val1, val2, eps) \ + do { \ + const double diff = fabs(val1 - val2); \ + const double div = std::min(fabs(val1), fabs(val2)); \ + const double err = (div == 0.0) ? diff : diff / div; \ + stats.add(err); \ + EXPECT_PRED_FORMAT2(::testing::DoubleLE, err, eps); \ + } while (0); + +void EXPECT_STRESS(const std::string &name, double *stress, const stress_t &expected_stress, + double epsilon); +void EXPECT_FORCES(const std::string &name, LAMMPS_NS::Atom *atom, + const std::vector &f_ref, double epsilon); +void EXPECT_POSITIONS(const std::string &name, LAMMPS_NS::Atom *atom, + const std::vector &x_ref, double epsilon); +void EXPECT_VELOCITIES(const std::string &name, LAMMPS_NS::Atom *atom, + const std::vector &v_ref, double epsilon); +void EXPECT_TORQUES(const std::string &name, LAMMPS_NS::Atom *atom, + const std::vector &t_ref, double epsilon); +void EXPECT_OMEGA(const std::string &name, LAMMPS_NS::Atom *atom, + const std::vector &w_ref, double epsilon); +void EXPECT_ANGMOM(const std::string &name, LAMMPS_NS::Atom *atom, + const std::vector &l_ref, double epsilon); + +#endif diff --git a/unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml b/unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml new file mode 100644 index 00000000000..732630e1474 --- /dev/null +++ b/unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml @@ -0,0 +1,72 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: sphere_sliding_rolling.in (user script). A sphere launched along +# +x with no spin, on a rough z-plane wall, decelerates by friction and +# spins up until it reaches rolling-without-slipping. Axes already match +# the slip_cessation convention (velocity along x, spin about y, wall +# normal z), so no remapping was needed. +pre_commands: ! | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.5 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${u0} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 1.0 ${xmu} damping coeff_restitution zplane 0.0 1.0 +input_file: +natoms: 1 +variables: ! | + diam 0.005 + dens 2700.0 + emod 1.0e4 + poisson 0.33 + en 1.0 + xmu 0.4 + grav 1.0 + u0 1.0 + radius 0.0025 + dt 1.0e-6 + z0 0.0025 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 1.0 ${xmu} +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. +# As in the source script, gravity magnitude is 1.0 m/s^2 (not standard g); +# the source script also let the sphere settle onto the wall for 10000 +# steps at timestep 0.001 before switching to the fine timestep and giving +# it its sliding velocity -- that settling phase is folded into pre_commands +# here via placing it directly at contact (z0 = radius) rather than +# reproducing the settle run, so the reference trajectory will differ +# slightly in its transient; re-verify analytic_segment placement with -s. +run_segments: ! |- + 2000 1000 1500 +analytic_enable: yes +analytic_model: slip_cessation +analytic_tol: 0.01 +analytic_segment: 2 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem02-oblique-cof-3d-si.yaml b/unittest/granular/tests/dem02-oblique-cof-3d-si.yaml new file mode 100644 index 00000000000..c7e3d9aa075 --- /dev/null +++ b/unittest/granular/tests/dem02-oblique-cof-3d-si.yaml @@ -0,0 +1,69 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: oblique_impact.in (user script). Single sphere striking a rigid +# wall at 25 degrees off the wall normal. Re-expressed with the wall normal +# along +z and the in-plane (tangential) direction along x (the convention +# assumed by test_analytic_models.cpp's oblique_impact model), instead of +# the source script's xplane wall with velocity components in x/y. All +# material and kinematic magnitudes are otherwise unchanged. +pre_commands: ! | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${vx_in} 0.0 -${vz_in} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: ! | + diam 0.005 + dens 2700.0 + emod 7.0e10 + poisson 0.33 + en 0.98 + xmu 0.092 + radius 0.0025 + # theta = 25 deg measured from the wall normal, vin = 3.9 m/s: + # normal component vin*cos(theta) -> vz_in, tangential vin*sin(theta) -> vx_in + vx_in 1.6483 + vz_in 3.5347 + dt 1.0e-8 + z0 0.002550 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow; +# analytic_segment must land on a free-flight window after rebound (not +# mid-contact) for oblique_impact's gross-sliding formula to apply. +run_segments: ! |- + 1300 900 +analytic_enable: yes +analytic_model: oblique_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem03-rolling-cof-3d-si.yaml b/unittest/granular/tests/dem03-rolling-cof-3d-si.yaml new file mode 100644 index 00000000000..06f917e2986 --- /dev/null +++ b/unittest/granular/tests/dem03-rolling-cof-3d-si.yaml @@ -0,0 +1,71 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: sphere_pure_rolling.in (user script). A sphere resting on a +# z-plane wall is given a pure spin (no translation) about y and damped +# to rest by rolling resistance (rolling sds). Axes already match the +# rolling_decay convention in test_analytic_models.cpp, so no remapping +# was needed -- material/kinematic values are transcribed as-is. +pre_commands: ! | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + set group all omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: ! | + diam 0.005 + dens 2700.0 + emod 1.0e4 + poisson 0.33 + en 1.0 + mur 0.05 + kr 1.0e4 + grav 1.0 + omega0 1.0 + radius 0.0025 + dt 1.0e-6 + z0 0.0025 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. +# gravity uses vector magnitude 1.0 (matching the source script's +# "fix grav all gravity 1 vector 0 0 -1"), i.e. grav = 1.0 m/s^2 -- this is +# what the source script actually specified, not standard g; keep as-is +# unless the user intended standard gravity (9.81), in which case update +# both the fix and the "grav" variable together. +run_segments: ! |- + 400 400 400 +analytic_enable: yes +analytic_model: rolling_decay +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml b/unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml new file mode 100644 index 00000000000..d0c87c6c171 --- /dev/null +++ b/unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml @@ -0,0 +1,64 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: in.cohesive_dmt (user script). Two identical spheres start just +# barely touching and are pulled apart; the DMT pull-off force at contact +# is F = 4*pi*gamma*R_eff with R_eff = R/2 for two equal spheres. Axis and +# force-magnitude check are orientation-agnostic, so no remapping was +# needed; values transcribed as-is. +pre_commands: ! | + units si + dimension 3 + boundary p p p + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.05 0.05 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep 1.0e-10 +post_commands: ! | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: ! | + diam 0.02 + dens 2800.0 + emod 4.8e10 + poisson 0.20 + ndamp 0.0 + coh 0.1 + xmu 0.35 + reff 0.005 + radius 0.01 + sep 0.00999999999999999 +pair_style: granular +pair_coeff: ! | + * * dmt ${emod} ${ndamp} ${poisson} ${coh} tangential mindlin NULL 0.0 ${xmu} +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. +# "run 0" (segment length 0) is enough since the spheres start already at +# (near) zero overlap, matching the pulloff_dmt check. +run_segments: ! |- + 0 +analytic_enable: yes +analytic_model: pulloff_dmt +analytic_tol: 0.001 +analytic_segment: 0 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml b/unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml new file mode 100644 index 00000000000..6634a3640a6 --- /dev/null +++ b/unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml @@ -0,0 +1,72 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: angular_sphere_impact.in (user script). Two identical spheres +# collide head-on along x (equal & opposite velocity and spin). Collision +# axis is already x, matching collision_restitution's hardcoded momentum/ +# restitution check along the atom-array x-component, so no remapping was +# needed. The model checks momentum conservation + coefficient of +# restitution along the collision axis; it does not assert on the spin +# components, which the source script sets equal & opposite for coverage +# of the tangential/rolling sub-models but are not asserted here. +pre_commands: ! | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.2 0.2 -0.1 0.1 -0.1 0.1 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + set group left omega 0.0 0.0 ${omega0} + set group right omega 0.0 0.0 -${omega0} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: ! | + diam 0.005 + dens 2700.0 + emod 7.0e10 + poisson 0.33 + en 0.5 + xmu 0.4 + vin 2.0 + omega0 22.0 + radius 0.0025 + dt 1.0e-8 + sep 0.002550 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 0.5 ${xmu} +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. +run_segments: ! |- + 1300 900 +analytic_enable: yes +analytic_model: collision_restitution +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml b/unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml new file mode 100644 index 00000000000..576e603d8ec --- /dev/null +++ b/unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml @@ -0,0 +1,75 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: in.angular_bidisperse (user script). A small, light, spinning +# sphere impacts a much larger and much denser (effectively rigid/immobile) +# stationary sphere. Re-expressed with the approach direction along -z and +# the spin about y (the convention assumed by test_analytic_models.cpp's +# spin_impact model, which treats the heavy partner like a rigid wall), +# instead of the source script's x-axis approach with spin about z. +# Material values (moduli, densities, diameters, friction, restitution) +# are transcribed unchanged from the source script. +pre_commands: ! | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.5 0.5 -0.5 0.5 -0.3 0.6 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + create_atoms 1 single 0.0 0.0 0.0 units box + set atom 1 diameter ${diam_small} density ${dens_small} + set atom 2 diameter ${diam_large} density ${dens_large} + group small id 1 + velocity small set 0.0 0.0 -${vin} + set group small omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: ! | + diam_small 0.2 + dens_small 2700.0 + diam_large 1.0 + dens_large 2.7e6 + emod 7.0e10 + poisson 0.33 + en 0.5 + xmu 0.40 + vin 0.2 + omega0 22.860 + radius 0.1 + dt 1.0e-6 + z0 0.60001 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 0.5 ${xmu} +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. +# analytic_segment must fall in free flight after rebound, with omega0 +# large enough relative to vin that contact stays in gross sliding +# (matches the source script's parameters, but re-verify with -s). +run_segments: ! |- + 300 300 +analytic_enable: yes +analytic_model: spin_impact +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml b/unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml new file mode 100644 index 00000000000..f2a96651a94 --- /dev/null +++ b/unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml @@ -0,0 +1,73 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: normal_contact_cof.in (user script). +# Single sphere normal-impacting a rigid wall, fully elastic (e = 1), +# frictionless tangential response. Re-expressed with the wall normal along +# +z (test_analytic_models.cpp's hertz_normal_impact model assumes a +# z-plane wall) instead of the original script's xplane; all material +# and kinematic values are otherwise unchanged from the source script. +pre_commands: ! | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set 0.0 0.0 -${vin} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: ! | + diam 0.005 + dens 7000.0 + emod 1.0e11 + poisson 0.25 + en 1.0 + vin 3.9 + vrela 3.9 + mred_factor 1.0 + floor 0.0 + radius 0.0025 + dt 1.0e-8 + z0 0.002550 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} ${en} ${poisson} tangential linear_nohistory 0.0 0.0 damping coeff_restitution +# NOTE: run_segments and the run_pos/run_vel/run_torque/run_omega reference +# blocks below are NOT yet generated -- they must be produced by actually +# running the compiled test program against a built LAMMPS+GRANULAR, e.g.: +# test_dem_11 tests/dem11-wall-normal-cof-3d-si.yaml -g new.yaml +# then inspecting/renaming new.yaml, or updating in place with -u. +# The starting gap (z0) is small so contact happens quickly; the first +# analytic_segment should land at (or very near) peak compression -- +# check with -s to see per-quantity error stats and retune if needed. +run_segments: ! |- + 1300 900 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 0 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... diff --git a/unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml b/unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml new file mode 100644 index 00000000000..3b26fa73eef --- /dev/null +++ b/unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml @@ -0,0 +1,70 @@ +--- +lammps_version: REGENERATE +tags: granular, generated +date_generated: REGENERATE +epsilon: 1e-10 +skip_tests: +prerequisites: ! | + atom sphere + pair granular +# Source: in.normal_simple (user script). Two identical spheres, head-on +# elastic normal impact along x (native axis of the source script; no +# remapping needed since hertz_normal_impact's two-sphere branch is +# axis-agnostic). Friction is present in the original pair_coeff (mindlin, +# mu = 0.35) but is irrelevant to a purely normal, non-rotating impact, so +# it is kept for coverage. +pre_commands: ! | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.03 0.03 -0.03 0.03 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: ! | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: ! | + diam 0.02 + dens 2800.0 + emod 4.8e10 + poisson 0.20 + xmu 0.35 + vin 10.0 + vrela 20.0 + mred_factor 0.5 + radius 0.01 + dt 1.0e-10 + sep 0.0101 +pair_style: granular +pair_coeff: ! | + * * hertz/material ${emod} 0.0 ${poisson} tangential mindlin NULL 0.0 ${xmu} +# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow; +# run_segments/reference blocks below are placeholders pending an actual +# LAMMPS run with -u / -g. +run_segments: ! |- + 600 400 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 0 +run_pos: ! |2 + # TODO: regenerate -- see NOTE above +run_vel: ! |2 + # TODO: regenerate -- see NOTE above +run_torque: ! |2 + # TODO: regenerate -- see NOTE above +run_omega: ! |2 + # TODO: regenerate -- see NOTE above +... From 527ffcd11c40c7fa0d60ae83b0af7bbd82559b72 Mon Sep 17 00:00:00 2001 From: zawh4159 Date: Tue, 21 Jul 2026 21:50:02 -0600 Subject: [PATCH 04/12] update and add versions to dem unittests --- unittest/granular/CMakeLists.txt | 16 ++-- unittest/granular/README.md | 92 +++++++++++++++++++ unittest/granular/README_MAPPING.md | 66 ------------- unittest/granular/temp | 1 - unittest/granular/test_dem_01.cpp | 2 +- unittest/granular/test_dem_02.cpp | 2 +- unittest/granular/test_dem_03.cpp | 2 +- unittest/granular/test_dem_04.cpp | 2 +- unittest/granular/test_dem_05.cpp | 2 +- unittest/granular/test_dem_06.cpp | 2 +- unittest/granular/test_dem_07.cpp | 2 +- unittest/granular/test_dem_08.cpp | 2 +- .../tests/dem01-hertz-twosphere-3d-si.yaml | 83 +++++++++++++++++ .../tests/dem01-hertzmindlin-cof-3d-si.yaml | 72 --------------- .../granular/tests/dem01-hooke-2d-lj.yaml | 72 +++++++++++++++ .../tests/dem01-hooke-twosphere-3d-si.yaml | 71 ++++++++++++++ .../dem01-hookehistory-twosphere-3d-si.yaml | 72 +++++++++++++++ .../tests/dem02-hertz-twosphere-3d-si.yaml | 80 ++++++++++++++++ .../dem02-hertzmaterial-twosphere-3d-si.yaml | 81 ++++++++++++++++ .../tests/dem02-oblique-cof-3d-si.yaml | 69 -------------- .../tests/dem03-hertz-wall-3d-si.yaml | 66 +++++++++++++ .../tests/dem03-hertzmaterial-wall-3d-si.yaml | 67 ++++++++++++++ .../tests/dem03-rolling-cof-3d-si.yaml | 71 -------------- .../tests/dem04-dmt-twosphere-cof-3d-si.yaml | 64 ------------- .../tests/dem04-hertz-oblique-3d-si.yaml | 66 +++++++++++++ .../dem04-hookehistory-oblique-3d-si.yaml | 66 +++++++++++++ .../tests/dem04-mindlin-oblique-3d-si.yaml | 66 +++++++++++++ .../dem04-mindlinrescale-oblique-3d-si.yaml | 66 +++++++++++++ .../tests/dem04-oblique-grazing-3d-si.yaml | 66 +++++++++++++ .../tests/dem05-hookehistory-slip-3d-si.yaml | 67 ++++++++++++++ .../tests/dem05-mindlin-slip-3d-si.yaml | 67 ++++++++++++++ .../granular/tests/dem05-slip-mu02-3d-si.yaml | 67 ++++++++++++++ .../tests/dem05-spin-headon-cof-3d-si.yaml | 72 --------------- .../tests/dem06-hookehistory-spin-3d-si.yaml | 83 +++++++++++++++++ .../tests/dem06-mindlin-spin-heavy-3d-si.yaml | 83 +++++++++++++++++ .../tests/dem06-spin-unequal-cof-3d-si.yaml | 75 --------------- .../granular/tests/dem06-spin-wall-3d-si.yaml | 67 ++++++++++++++ .../tests/dem07-hertz-rolling-3d-si.yaml | 68 ++++++++++++++ .../tests/dem07-hooke-rolling-3d-si.yaml | 67 ++++++++++++++ .../tests/dem07-rolling-mu02-3d-si.yaml | 68 ++++++++++++++ .../tests/dem07-wall-normal-cof-3d-si.yaml | 73 --------------- .../tests/dem08-dmt-twosphere-3d-si.yaml | 60 ++++++++++++ .../granular/tests/dem08-dmt-wall-3d-si.yaml | 56 +++++++++++ .../tests/dem08-twosphere-normal-3d-si.yaml | 70 -------------- 44 files changed, 1783 insertions(+), 649 deletions(-) create mode 100644 unittest/granular/README.md delete mode 100644 unittest/granular/README_MAPPING.md delete mode 100644 unittest/granular/temp create mode 100644 unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml delete mode 100644 unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem01-hooke-2d-lj.yaml create mode 100644 unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml create mode 100644 unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml create mode 100644 unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml create mode 100644 unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml delete mode 100644 unittest/granular/tests/dem02-oblique-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem03-hertz-wall-3d-si.yaml create mode 100644 unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml delete mode 100644 unittest/granular/tests/dem03-rolling-cof-3d-si.yaml delete mode 100644 unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml create mode 100644 unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml create mode 100644 unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml create mode 100644 unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml create mode 100644 unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml create mode 100644 unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml create mode 100644 unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml create mode 100644 unittest/granular/tests/dem05-slip-mu02-3d-si.yaml delete mode 100644 unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml create mode 100644 unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml delete mode 100644 unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem06-spin-wall-3d-si.yaml create mode 100644 unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml create mode 100644 unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml create mode 100644 unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml delete mode 100644 unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml create mode 100644 unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml create mode 100644 unittest/granular/tests/dem08-dmt-wall-3d-si.yaml delete mode 100644 unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml diff --git a/unittest/granular/CMakeLists.txt b/unittest/granular/CMakeLists.txt index ef0d81c8fae..e5c32fcc59c 100644 --- a/unittest/granular/CMakeLists.txt +++ b/unittest/granular/CMakeLists.txt @@ -76,42 +76,42 @@ function(register_dem_tests driver prefix label) endforeach() endfunction() -# DEM-01: sphere sliding then rolling without slipping on a rough surface +# DEM-01: two identical spheres, head-on normal collision (coefficient of restitution) add_executable(test_dem_01 test_dem_01.cpp) target_link_libraries(test_dem_01 PRIVATE lammps granular_tests) register_dem_tests(test_dem_01 dem01 DEM01) -# DEM-02: oblique collision of a sphere with a flat wall +# DEM-02: elastic Hertzian normal impact of two spheres (peak contact force) add_executable(test_dem_02 test_dem_02.cpp) target_link_libraries(test_dem_02 PRIVATE lammps granular_tests) register_dem_tests(test_dem_02 dem02 DEM02) -# DEM-03: spinning sphere damped by rolling resistance (rolling sds) +# DEM-03: elastic Hertzian normal impact of a sphere on a wall (peak contact force) add_executable(test_dem_03 test_dem_03.cpp) target_link_libraries(test_dem_03 PRIVATE lammps granular_tests) register_dem_tests(test_dem_03 dem03 DEM03) -# DEM-04: cohesive/adhesive contact (DMT pull-off force) +# DEM-04: oblique impact of a sphere on a wall (gross-sliding friction) add_executable(test_dem_04 test_dem_04.cpp) target_link_libraries(test_dem_04 PRIVATE lammps granular_tests) register_dem_tests(test_dem_04 dem04 DEM04) -# DEM-05: two identical spinning spheres, head-on collision +# DEM-05: sphere sliding then rolling without slipping on a rough wall (slip cessation) add_executable(test_dem_05 test_dem_05.cpp) target_link_libraries(test_dem_05 PRIVATE lammps granular_tests) register_dem_tests(test_dem_05 dem05 DEM05) -# DEM-06: unequal-size spinning sphere impacting a heavy/rigid partner +# DEM-06: spinning sphere impacting a heavy partner / wall (rebound + friction) add_executable(test_dem_06 test_dem_06.cpp) target_link_libraries(test_dem_06 PRIVATE lammps granular_tests) register_dem_tests(test_dem_06 dem06 DEM06) -# DEM-07: elastic Hertzian normal impact of a sphere on a wall +# DEM-07: spinning sphere damped to rest by rolling resistance (rolling sds) add_executable(test_dem_07 test_dem_07.cpp) target_link_libraries(test_dem_07 PRIVATE lammps granular_tests) register_dem_tests(test_dem_07 dem07 DEM07) -# DEM-08: elastic Hertzian normal impact of two spheres +# DEM-08: cohesive/adhesive contact -- the DMT pull-off force add_executable(test_dem_08 test_dem_08.cpp) target_link_libraries(test_dem_08 PRIVATE lammps granular_tests) register_dem_tests(test_dem_08 dem08 DEM08) diff --git a/unittest/granular/README.md b/unittest/granular/README.md new file mode 100644 index 00000000000..911f79f520c --- /dev/null +++ b/unittest/granular/README.md @@ -0,0 +1,92 @@ +# unittest/granular — DEM verification tests + +Verification tests for LAMMPS' granular (DEM) contact models. Each test drives a +small, analytically tractable system entirely from a YAML file and compares the +simulated result against a closed-form solution, and (once recorded) against a +stored per-atom reference trajectory. + +## Layout + +- `test_dem_01..08.cpp` — the eight test drivers. Each is a thin GoogleTest + fixture (`newton_on` / `newton_off`) that hands off to the shared trajectory + runner; all scenario-specific behavior lives in the YAML files. +- `test_dem_common.{cpp,h}` — builds the system from a YAML config, runs it in + segments, and compares positions, velocities, torques, and angular velocities + against the reference plus the selected analytic model. +- `test_analytic_models.{cpp,h}` — the closed-form models selected per test via + the YAML `analytic_model` key. +- `test_config_reader.{cpp,h}`, `test_main.{cpp,h}`, `test_config.h` — YAML + parsing and the test-runner entry point. +- `tests/` — the YAML test definitions, `demNN---.yaml`. + +## Tests + +Each numbered driver runs every `demNN-*.yaml` in `tests/` (registered +automatically by the CMake glob), so a driver may cover several variants of one +scenario across different contact models, dimensions, and parameters. + +| # | scenario | analytic model | +|---|---|---| +| 01 | two-sphere head-on normal collision | `collision_restitution` | +| 02 | two-sphere elastic Hertzian normal impact (peak force) | `hertz_normal_impact` | +| 03 | sphere–wall elastic Hertzian normal impact (peak force) | `hertz_normal_impact` | +| 04 | oblique impact on a wall (gross-sliding friction) | `oblique_impact` | +| 05 | sphere sliding then rolling without slipping | `slip_cessation` | +| 06 | spinning sphere impact (rebound with friction) | `spin_impact` | +| 07 | rolling-resistance decay | `rolling_decay` | +| 08 | cohesive DMT pull-off force | `pulloff_dmt` | + +Variants exercise the `hooke`, `hooke/history`, `hertz`, `hertz/material`, +`mindlin`, and `mindlin/rescale` models, a 2D/LJ-units case, and friction/angle +sweeps. + +## Building + +Configure LAMMPS with testing and the GRANULAR package enabled, then build the +drivers: + + cmake -C ../cmake/presets/most.cmake -D ENABLE_TESTING=on -D PKG_GRANULAR=on ../cmake + cmake --build . --target test_dem_01 test_dem_02 test_dem_03 test_dem_04 \ + test_dem_05 test_dem_06 test_dem_07 test_dem_08 -j + +## Running + +Run a single test file: + + ./test_dem_02 tests/dem02-hertzmaterial-twosphere-3d-si.yaml + +Or run the whole suite through ctest from the build directory: + + ctest -R Dem --output-on-failure + +Options: + +- `-v` — verbose (show LAMMPS screen output). +- `-s` — print per-quantity error statistics. +- `-g ` — regenerate the reference into a new YAML file. +- `-u` — regenerate the reference in place. +- `-d ` — set the folder for any external input files. + +## YAML format + +Each file specifies the system and the checks: + +- `prerequisites`, `pre_commands`, `pair_style`, `pair_coeff`, `post_commands` — + the LAMMPS commands that build the geometry, contact model, and integrator. +- `variables` — `${var}` substitutions used throughout the command blocks. +- `run_segments` — space-separated step counts; the trajectory is compared after + each segment. +- `analytic_model`, `analytic_segment`, `analytic_tol` — which closed-form model + to check, at which segment boundary, and to what relative tolerance. +- `run_pos` / `run_vel` / `run_torque` / `run_omega` — the recorded per-atom + reference, produced by `-g` / `-u`. + +## Regenerating reference data + +After editing a test, regenerate its reference trajectory and confirm it passes: + + ./test_dem_0N tests/.yaml -u + ./test_dem_0N tests/.yaml -s + +The reference is recorded with `newton on`; tests are checked under both +`newton on` and `newton off`. \ No newline at end of file diff --git a/unittest/granular/README_MAPPING.md b/unittest/granular/README_MAPPING.md deleted file mode 100644 index 94a32f12ad5..00000000000 --- a/unittest/granular/README_MAPPING.md +++ /dev/null @@ -1,66 +0,0 @@ -# unittest/granular replacement — mapping notes - -Only the 8 tests derived from your scripts are here, renumbered 01-08 -(sequentially, in original scenario order). Everything else has been -removed — no leftover placeholders for unimplemented categories, no -unused test_dem_0N.cpp files. - -## What's unchanged (kept from the existing directory) - -Generic test *harness* files — not test content, and match LAMMPS' own -documented design for `unittest/granular`: - -- `CMakeLists.txt` — trimmed to register exactly 8 executables/test sets -- `test_config.h`, `test_config_reader.{h,cpp}` -- `test_dem_common.{h,cpp}`, `test_main.{h,cpp}` -- `test_analytic_models.{h,cpp}` — already implements every closed-form - model these 8 tests need (`slip_cessation`, `oblique_impact`, - `rolling_decay`, `pulloff_dmt`, `collision_restitution`, `spin_impact`) - -## Script → test mapping (new numbering) - -| # | Your script | New file | analytic_model | -|---|---|---|---| -| 01 | `sphere_sliding_rolling.in` | `dem01-hertzmindlin-cof-3d-si.yaml` | `slip_cessation` | -| 02 | `oblique_impact.in` | `dem02-oblique-cof-3d-si.yaml` | `oblique_impact` | -| 03 | `sphere_pure_rolling.in` | `dem03-rolling-cof-3d-si.yaml` | `rolling_decay` | -| 04 | `in.cohesive_dmt` | `dem04-dmt-twosphere-cof-3d-si.yaml` | `pulloff_dmt` | -| 05 | `angular_sphere_impact.in` | `dem05-spin-headon-cof-3d-si.yaml` | `collision_restitution` | -| 06 | `in.angular_bidisperse` | `dem06-spin-unequal-cof-3d-si.yaml` | `spin_impact` | -| 07 | `normal_contact_cof.in` | `dem07-wall-normal-cof-3d-si.yaml` | `hertz_normal_impact` | -| 08 | `in.normal_simple` | `dem08-twosphere-normal-3d-si.yaml` | `hertz_normal_impact` | - -Two of these (02, 06) have their geometry relabeled — not their physics -changed — to match axis conventions `test_analytic_models.cpp` hard-codes -(e.g. `oblique_impact` reads `v[i][0]`/`v[i][2]` specifically). Every -material property, density, diameter, velocity, friction coefficient, and -restitution coefficient is transcribed unchanged from your original -scripts. See the previous round's notes below for exact per-file details. - -## What you still need to do — this is important - -**I could not run LAMMPS in this environment.** Each of the 8 YAML files -has a real `prerequisites`/`pre_commands`/`variables`/`pair_style`/ -`pair_coeff`/`post_commands` block built from your script, plus a -placeholder `run_segments` guess, but the `run_pos`/`run_vel`/ -`run_torque`/`run_omega` reference blocks are marked `# TODO: regenerate`. - -Generate the real reference data by building LAMMPS with `GRANULAR` + -testing enabled and running, e.g.: - -``` -test_dem_01 tests/dem01-hertzmindlin-cof-3d-si.yaml -g new.yaml -``` - -or update in place with `-u`, then check with `-s` (per-quantity error -stats) that `analytic_segment` lands where the model expects (e.g. peak -compression for `hertz_normal_impact`, post-rebound free flight for -`oblique_impact`/`spin_impact`) and retune `run_segments` if not. - -Per-file notes carried over from before: -- `dem01` (from `sphere_sliding_rolling.in`) and `dem03` (from - `sphere_pure_rolling.in`): source scripts used gravity magnitude `1.0` - (not standard 9.81) — kept as literally scripted, verify that's intended. -- `dem01`: source script had a 10,000-step settle phase before applying - sliding velocity; this version places the sphere directly at contact - instead, so the early transient will differ slightly from your original. diff --git a/unittest/granular/temp b/unittest/granular/temp deleted file mode 100644 index 4be40b2f3af..00000000000 --- a/unittest/granular/temp +++ /dev/null @@ -1 +0,0 @@ -tempfile diff --git a/unittest/granular/test_dem_01.cpp b/unittest/granular/test_dem_01.cpp index 645f5bbc4e9..121222e8a20 100644 --- a/unittest/granular/test_dem_01.cpp +++ b/unittest/granular/test_dem_01.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 01: sphere sliding then rolling without slipping on a rough wall. +// DEM verification test 01: two identical spheres, head-on normal collision (coefficient of restitution). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem01-*.yaml. diff --git a/unittest/granular/test_dem_02.cpp b/unittest/granular/test_dem_02.cpp index 4aea1e37786..0764020fa5b 100644 --- a/unittest/granular/test_dem_02.cpp +++ b/unittest/granular/test_dem_02.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 02: oblique collision of a sphere with a flat wall. +// DEM verification test 02: elastic Hertzian normal impact of two spheres (peak contact force). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem02-*.yaml. diff --git a/unittest/granular/test_dem_03.cpp b/unittest/granular/test_dem_03.cpp index 9bde2a74114..949cb49d712 100644 --- a/unittest/granular/test_dem_03.cpp +++ b/unittest/granular/test_dem_03.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 03: a spinning sphere damped to rest by rolling resistance (rolling sds). +// DEM verification test 03: elastic Hertzian normal impact of a sphere on a wall (peak contact force). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem03-*.yaml. diff --git a/unittest/granular/test_dem_04.cpp b/unittest/granular/test_dem_04.cpp index 1d000515d4d..d30e0761878 100644 --- a/unittest/granular/test_dem_04.cpp +++ b/unittest/granular/test_dem_04.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 04: cohesive/adhesive contact -- the DMT pull-off force. +// DEM verification test 04: oblique impact of a sphere on a wall (gross-sliding friction). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem04-*.yaml. diff --git a/unittest/granular/test_dem_05.cpp b/unittest/granular/test_dem_05.cpp index e40360600dc..c50128507e1 100644 --- a/unittest/granular/test_dem_05.cpp +++ b/unittest/granular/test_dem_05.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 05: two identical spinning spheres, head-on collision. +// DEM verification test 05: sphere sliding then rolling without slipping on a rough wall (slip cessation). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem05-*.yaml. diff --git a/unittest/granular/test_dem_06.cpp b/unittest/granular/test_dem_06.cpp index e3df7783b25..a1633bcb13a 100644 --- a/unittest/granular/test_dem_06.cpp +++ b/unittest/granular/test_dem_06.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 06: an unequal-size spinning sphere impacting a heavy/rigid partner. +// DEM verification test 06: spinning sphere impacting a heavy partner / wall (rebound + friction). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem06-*.yaml. diff --git a/unittest/granular/test_dem_07.cpp b/unittest/granular/test_dem_07.cpp index 077ee167731..7ffe5531fd7 100644 --- a/unittest/granular/test_dem_07.cpp +++ b/unittest/granular/test_dem_07.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 07: elastic Hertzian normal impact of a sphere on a wall. +// DEM verification test 07: spinning sphere damped to rest by rolling resistance (rolling sds). // All test logic is shared via test_dem_common; the reference systems // live in tests/dem07-*.yaml. diff --git a/unittest/granular/test_dem_08.cpp b/unittest/granular/test_dem_08.cpp index 24c5f926bf2..805368d3070 100644 --- a/unittest/granular/test_dem_08.cpp +++ b/unittest/granular/test_dem_08.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -// DEM verification test 08: elastic Hertzian normal impact of two spheres. +// DEM verification test 08: cohesive/adhesive contact -- the DMT pull-off force. // All test logic is shared via test_dem_common; the reference systems // live in tests/dem08-*.yaml. diff --git a/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml b/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml new file mode 100644 index 00000000000..cd053a35d4a --- /dev/null +++ b/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml @@ -0,0 +1,83 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:49 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.2 0.2 -0.1 0.1 -0.1 0.1 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + set group left omega 0.0 0.0 ${omega0} + set group right omega 0.0 0.0 -${omega0} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam 0.005 + dens 2700.0 + emod 7.0e10 + poisson 0.33 + en 0.5 + xmu 0.4 + vin 2.0 + omega0 22.0 + radius 0.0025 + dt 1.0e-8 + sep 0.002550 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 0.5 ${xmu} +run_segments: |- + 2600 1500 1000 +analytic_enable: yes +analytic_model: collision_restitution +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: |2 + 0 1 -2.4980771696568298e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 2.4980771696568298e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -2.5034876076619247e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 2.5034876076619247e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 -2.5134864441910699e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 2.5134864441910699e-03 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 1.8176180382750824e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 -1.8176180382750824e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -9.9988365289612324e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 9.9988365289612324e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 -9.9988365289612324e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 9.9988365289612324e-01 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 2.2000000000000000e+01 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 -2.2000000000000000e+01 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.2000000000000000e+01 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 -2.2000000000000000e+01 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.2000000000000000e+01 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 -2.2000000000000000e+01 +... diff --git a/unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml b/unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml deleted file mode 100644 index 732630e1474..00000000000 --- a/unittest/granular/tests/dem01-hertzmindlin-cof-3d-si.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: sphere_sliding_rolling.in (user script). A sphere launched along -# +x with no spin, on a rough z-plane wall, decelerates by friction and -# spins up until it reaches rolling-without-slipping. Axes already match -# the slip_cessation convention (velocity along x, spin about y, wall -# normal z), so no remapping was needed. -pre_commands: ! | - units si - dimension 3 - boundary p p f - atom_style sphere - region box block -0.05 0.5 -0.05 0.05 -0.01 0.05 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${u0} 0.0 0.0 - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix grav all gravity 1.0 vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 1.0 ${xmu} damping coeff_restitution zplane 0.0 1.0 -input_file: -natoms: 1 -variables: ! | - diam 0.005 - dens 2700.0 - emod 1.0e4 - poisson 0.33 - en 1.0 - xmu 0.4 - grav 1.0 - u0 1.0 - radius 0.0025 - dt 1.0e-6 - z0 0.0025 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 1.0 ${xmu} -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. -# As in the source script, gravity magnitude is 1.0 m/s^2 (not standard g); -# the source script also let the sphere settle onto the wall for 10000 -# steps at timestep 0.001 before switching to the fine timestep and giving -# it its sliding velocity -- that settling phase is folded into pre_commands -# here via placing it directly at contact (z0 = radius) rather than -# reproducing the settle run, so the reference trajectory will differ -# slightly in its transient; re-verify analytic_segment placement with -s. -run_segments: ! |- - 2000 1000 1500 -analytic_enable: yes -analytic_model: slip_cessation -analytic_tol: 0.01 -analytic_segment: 2 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem01-hooke-2d-lj.yaml b/unittest/granular/tests/dem01-hooke-2d-lj.yaml new file mode 100644 index 00000000000..57dff280938 --- /dev/null +++ b/unittest/granular/tests/dem01-hooke-2d-lj.yaml @@ -0,0 +1,72 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:50 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units lj + dimension 2 + boundary f f p + atom_style sphere + region box block -8.0 8.0 -2.0 2.0 -0.1 0.1 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + comm_modify vel yes + neighbor 0.05 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere disc + fix twod all enforce2d +input_file: +natoms: 2 +variables: | + diam 1 + dens 1 + knorm 10000 + en 0.5 + xmu 0.0 + vin 1 + radius 0.5 + dt 0.0001 + sep 0.55 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution +run_segments: |- + 947 500 +analytic_enable: yes +analytic_model: collision_restitution +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: |2 + 0 1 -5.1414816868621493e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 5.1414816868621493e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -5.3916945975278863e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 5.3916945975278863e-01 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 -5.0042582133180780e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 5.0042582133180780e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -5.0042582133180780e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 5.0042582133180780e-01 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml b/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml new file mode 100644 index 00000000000..f18ae58ec33 --- /dev/null +++ b/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml @@ -0,0 +1,71 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:50 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.03 0.03 -0.03 0.03 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam 0.005 + dens 2700 + knorm 1e+06 + en 0.5 + xmu 0.0 + vin 2 + radius 0.0025 + dt 3e-08 + sep 0.00255 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution +run_segments: |- + 2068 727 +analytic_enable: yes +analytic_model: collision_restitution +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: |2 + 0 1 -2.5068045944333988e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 2.5068045944333988e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -2.5285999681953571e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 2.5285999681953571e-03 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 -9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml b/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml new file mode 100644 index 00000000000..d83120342b3 --- /dev/null +++ b/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml @@ -0,0 +1,72 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:50 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.03 0.03 -0.03 0.03 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam 0.005 + dens 2700 + knorm 1e+06 + en 0.5 + kt 2.8e5 + xmu 0.0 + vin 2 + radius 0.0025 + dt 3e-08 + sep 0.00255 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution +run_segments: |- + 2068 727 +analytic_enable: yes +analytic_model: collision_restitution +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: |2 + 0 1 -2.5068045944333988e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 2.5068045944333988e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -2.5285999681953571e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 2.5285999681953571e-03 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 -9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 9.9932937926762544e-01 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml b/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml new file mode 100644 index 00000000000..8a4a4804f19 --- /dev/null +++ b/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml @@ -0,0 +1,80 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:51 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.03 0.03 -0.03 0.03 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam 0.02 + dens 2800.0 + kn 3.33333e+10 + xmu 0.35 + vin 10.0 + vrela 20.0 + mred_factor 0.5 + radius 0.01 + dt 2.0e-8 + sep 0.0101 +pair_style: granular +pair_coeff: | + * * hertz ${kn} 0.0 tangential linear_nohistory 0.0 0.0 +run_segments: |- + 500 1008 1000 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 -9.9999999999997261e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 9.9999999999997261e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -9.8629436218504573e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 9.8629436218504573e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 -9.9982053375566714e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 9.9982053375566714e-03 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 1.0000000000000000e+01 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 -1.0000000000000000e+01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 8.8771553283535053e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 -8.8771553283535053e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 -9.9999015425187849e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 9.9999015425187849e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml b/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml new file mode 100644 index 00000000000..b044c236c5c --- /dev/null +++ b/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml @@ -0,0 +1,81 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:51 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.03 0.03 -0.03 0.03 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + group left id 1 + group right id 2 + velocity left set ${vin} 0.0 0.0 + velocity right set -${vin} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam 0.02 + dens 2800.0 + emod 4.8e10 + poisson 0.20 + xmu 0.35 + vin 10.0 + vrela 20.0 + mred_factor 0.5 + radius 0.01 + dt 2.0e-8 + sep 0.0101 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} 0.0 ${poisson} tangential mindlin NULL 0.0 ${xmu} +run_segments: |- + 500 1008 1000 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 -9.9999999999997261e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 9.9999999999997261e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 -9.8629436766014371e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 9.8629436766014371e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 -9.9982054989131309e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 9.9982054989131309e-03 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 1.0000000000000000e+01 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 -1.0000000000000000e+01 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 8.8698006865996614e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 -8.8698006865996614e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 -9.9999015644864890e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 9.9999015644864890e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem02-oblique-cof-3d-si.yaml b/unittest/granular/tests/dem02-oblique-cof-3d-si.yaml deleted file mode 100644 index c7e3d9aa075..00000000000 --- a/unittest/granular/tests/dem02-oblique-cof-3d-si.yaml +++ /dev/null @@ -1,69 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: oblique_impact.in (user script). Single sphere striking a rigid -# wall at 25 degrees off the wall normal. Re-expressed with the wall normal -# along +z and the in-plane (tangential) direction along x (the convention -# assumed by test_analytic_models.cpp's oblique_impact model), instead of -# the source script's xplane wall with velocity components in x/y. All -# material and kinematic magnitudes are otherwise unchanged. -pre_commands: ! | - units si - dimension 3 - boundary p p f - atom_style sphere - region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set ${vx_in} 0.0 -${vz_in} - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 0.005 - dens 2700.0 - emod 7.0e10 - poisson 0.33 - en 0.98 - xmu 0.092 - radius 0.0025 - # theta = 25 deg measured from the wall normal, vin = 3.9 m/s: - # normal component vin*cos(theta) -> vz_in, tangential vin*sin(theta) -> vx_in - vx_in 1.6483 - vz_in 3.5347 - dt 1.0e-8 - z0 0.002550 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow; -# analytic_segment must land on a free-flight window after rebound (not -# mid-contact) for oblique_impact's gross-sliding formula to apply. -run_segments: ! |- - 1300 900 -analytic_enable: yes -analytic_model: oblique_impact -analytic_tol: 0.01 -analytic_segment: 1 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml b/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml new file mode 100644 index 00000000000..194a32f6a62 --- /dev/null +++ b/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml @@ -0,0 +1,66 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:51 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set 0.0 0.0 -${vin} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 7000.0 + kn 7.11111e+10 + en 1.0 + vin 3.9 + vrela 3.9 + mred_factor 1.0 + floor 0.0 + radius 0.0025 + dt 1.0e-8 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution +run_segments: |- + 1300 838 900 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4993000166951690e-03 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4773193520144258e-03 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.5017266321382694e-03 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -3.8996733777045449e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 9.2769893463961334e-04 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 3.9000000198694948e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml b/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml new file mode 100644 index 00000000000..240818e03fd --- /dev/null +++ b/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml @@ -0,0 +1,67 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:52 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set 0.0 0.0 -${vin} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 7000.0 + emod 1.0e11 + poisson 0.25 + en 1.0 + vin 3.9 + vrela 3.9 + mred_factor 1.0 + floor 0.0 + radius 0.0025 + dt 1.0e-8 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} tangential linear_nohistory 0.0 0.0 damping coeff_restitution +run_segments: |- + 1300 838 900 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4993000166951712e-03 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4773193534324612e-03 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.5017266363104966e-03 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -3.8996733776535106e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 9.2814738217408040e-04 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 3.9000000198738074e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem03-rolling-cof-3d-si.yaml b/unittest/granular/tests/dem03-rolling-cof-3d-si.yaml deleted file mode 100644 index 06f917e2986..00000000000 --- a/unittest/granular/tests/dem03-rolling-cof-3d-si.yaml +++ /dev/null @@ -1,71 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: sphere_pure_rolling.in (user script). A sphere resting on a -# z-plane wall is given a pure spin (no translation) about y and damped -# to rest by rolling resistance (rolling sds). Axes already match the -# rolling_decay convention in test_analytic_models.cpp, so no remapping -# was needed -- material/kinematic values are transcribed as-is. -pre_commands: ! | - units si - dimension 3 - boundary p p f - atom_style sphere - region box block -0.05 0.05 -0.05 0.05 -0.01 0.05 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - set group all omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix grav all gravity 1.0 vector 0.0 0.0 -1.0 - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 0.005 - dens 2700.0 - emod 1.0e4 - poisson 0.33 - en 1.0 - mur 0.05 - kr 1.0e4 - grav 1.0 - omega0 1.0 - radius 0.0025 - dt 1.0e-6 - z0 0.0025 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. -# gravity uses vector magnitude 1.0 (matching the source script's -# "fix grav all gravity 1 vector 0 0 -1"), i.e. grav = 1.0 m/s^2 -- this is -# what the source script actually specified, not standard g; keep as-is -# unless the user intended standard gravity (9.81), in which case update -# both the fix and the "grav" variable together. -run_segments: ! |- - 400 400 400 -analytic_enable: yes -analytic_model: rolling_decay -analytic_tol: 0.01 -analytic_segment: 1 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml b/unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml deleted file mode 100644 index d0c87c6c171..00000000000 --- a/unittest/granular/tests/dem04-dmt-twosphere-cof-3d-si.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: in.cohesive_dmt (user script). Two identical spheres start just -# barely touching and are pulled apart; the DMT pull-off force at contact -# is F = 4*pi*gamma*R_eff with R_eff = R/2 for two equal spheres. Axis and -# force-magnitude check are orientation-agnostic, so no remapping was -# needed; values transcribed as-is. -pre_commands: ! | - units si - dimension 3 - boundary p p p - atom_style sphere - region box block -0.05 0.05 -0.05 0.05 -0.05 0.05 units box - create_box 1 box - create_atoms 1 single -${sep} 0.0 0.0 units box - create_atoms 1 single ${sep} 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep 1.0e-10 -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 0.02 - dens 2800.0 - emod 4.8e10 - poisson 0.20 - ndamp 0.0 - coh 0.1 - xmu 0.35 - reff 0.005 - radius 0.01 - sep 0.00999999999999999 -pair_style: granular -pair_coeff: ! | - * * dmt ${emod} ${ndamp} ${poisson} ${coh} tangential mindlin NULL 0.0 ${xmu} -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. -# "run 0" (segment length 0) is enough since the spheres start already at -# (near) zero overlap, matching the pulloff_dmt check. -run_segments: ! |- - 0 -analytic_enable: yes -analytic_model: pulloff_dmt -analytic_tol: 0.001 -analytic_segment: 0 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml b/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml new file mode 100644 index 00000000000..29d4195dcde --- /dev/null +++ b/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml @@ -0,0 +1,66 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:52 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${vx_in} 0.0 -${vz_in} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz ${kn} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700 + kn 5.23697e+10 + kt 1.5e10 + en 0.98 + xmu 0.092 + radius 0.0025 + vx_in 2.5069 + vz_in 2.9876 + dt 1e-08 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hertz ${kn} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution +run_segments: |- + 1724 1593 900 +analytic_enable: yes +analytic_model: oblique_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 4.3218834621597697e-05 0.0000000000000000e+00 2.4984950953306625e-03 + 1 1 7.7972106138949184e-05 0.0000000000000000e+00 2.5072236212123943e-03 + 2 1 9.5635813315736917e-05 0.0000000000000000e+00 2.5335742020348153e-03 +run_vel: |2 + 0 1 2.5061771941302529e+00 0.0000000000000000e+00 -2.9797434144592430e+00 + 1 1 1.9626341307546062e+00 0.0000000000000000e+00 2.9278423135870786e+00 + 2 1 1.9626341307546062e+00 0.0000000000000000e+00 2.9278423135870786e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 1.3466415071223508e-03 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 7.2280586974967476e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 5.4426586924539083e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 5.4426586924539083e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml b/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml new file mode 100644 index 00000000000..23693ab9894 --- /dev/null +++ b/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml @@ -0,0 +1,66 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:52 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${vx_in} 0.0 -${vz_in} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700 + knorm 2.0e7 + kt 5.7e6 + en 0.98 + xmu 0.092 + radius 0.0025 + vx_in 2.5069 + vz_in 2.9876 + dt 1e-08 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution +run_segments: |- + 1724 1133 900 +analytic_enable: yes +analytic_model: oblique_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 4.3218144443063926e-05 0.0000000000000000e+00 2.4985026256484134e-03 + 1 1 6.7697125864983813e-05 0.0000000000000000e+00 2.5073069827388330e-03 + 2 1 8.5360942777429607e-05 0.0000000000000000e+00 2.5336574338724162e-03 +run_vel: |2 + 0 1 2.5023666425415572e+00 0.0000000000000000e+00 -2.9382675941730652e+00 + 1 1 1.9626463236052916e+00 0.0000000000000000e+00 2.9278279037320356e+00 + 2 1 1.9626463236052916e+00 0.0000000000000000e+00 2.9278279037320356e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 7.4047972399628442e-03 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 4.5333574584411203e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 5.4425367639471085e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 5.4425367639471085e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml b/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml new file mode 100644 index 00000000000..985e0d65ff6 --- /dev/null +++ b/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml @@ -0,0 +1,66 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:52 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${vx_in} 0.0 -${vz_in} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + emod 7.0e10 + poisson 0.33 + en 0.98 + xmu 0.092 + radius 0.0025 + vx_in 2.5069 + vz_in 2.9876 + dt 1.0e-8 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution +run_segments: |- + 1700 1600 900 +analytic_enable: yes +analytic_model: oblique_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 4.2617283835628844e-05 0.0000000000000000e+00 2.4992110055265266e-03 + 1 1 7.7638651345996810e-05 0.0000000000000000e+00 2.5067258974728027e-03 + 2 1 9.5302466035586915e-05 0.0000000000000000e+00 2.5330764782679018e-03 +run_vel: |2 + 0 1 2.5067149412230361e+00 0.0000000000000000e+00 -2.9854586441519237e+00 + 1 1 1.9626460766213021e+00 0.0000000000000000e+00 2.9278423105668629e+00 + 2 1 1.9626460766213021e+00 0.0000000000000000e+00 2.9278423105668629e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 6.2225216712037982e-04 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 1.8505877696403941e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 5.4425392337870403e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 5.4425392337870403e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml b/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml new file mode 100644 index 00000000000..de21e551f90 --- /dev/null +++ b/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml @@ -0,0 +1,66 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:53 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${vx_in} 0.0 -${vz_in} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin_rescale NULL 0.5 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700 + emod 7e+10 + poisson 0.33 + en 0.98 + xmu 0.092 + radius 0.0025 + vx_in 2.5069 + vz_in 2.9876 + dt 1e-08 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} tangential mindlin_rescale NULL 0.5 ${xmu} damping coeff_restitution +run_segments: |- + 1724 1593 900 +analytic_enable: yes +analytic_model: oblique_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 4.3218840232622755e-05 0.0000000000000000e+00 2.4984950953312736e-03 + 1 1 7.7972301179679522e-05 0.0000000000000000e+00 2.5072236306699839e-03 + 2 1 9.5636115869086668e-05 0.0000000000000000e+00 2.5335742114736700e-03 +run_vel: |2 + 0 1 2.5061891397356071e+00 0.0000000000000000e+00 -2.9797434105929264e+00 + 1 1 1.9626460766007514e+00 0.0000000000000000e+00 2.9278423115198366e+00 + 2 1 1.9626460766007514e+00 0.0000000000000000e+00 2.9278423115198366e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 1.3466422172390918e-03 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 7.1086026439197081e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 5.4425392339924827e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 5.4425392339924827e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml b/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml new file mode 100644 index 00000000000..b91c8d5b0c5 --- /dev/null +++ b/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml @@ -0,0 +1,66 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:53 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.2 0.2 -0.05 0.05 -0.05 0.1 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${vx_in} 0.0 -${vz_in} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700 + emod 7e+10 + poisson 0.33 + en 0.98 + xmu 0.092 + radius 0.0025 + vx_in 3.1947 + vz_in 2.2369 + dt 1e-08 + z0 0.002550 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution +run_segments: |- + 2285 1677 900 +analytic_enable: yes +analytic_model: oblique_impact +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 7.2998820115520601e-05 0.0000000000000000e+00 2.4988876801169779e-03 + 1 1 1.2252260050554098e-04 0.0000000000000000e+00 2.5054113469810710e-03 + 2 1 1.4760738870002189e-04 0.0000000000000000e+00 2.5251407972463834e-03 +run_vel: |2 + 0 1 3.1942406308257176e+00 0.0000000000000000e+00 -2.2318400261448739e+00 + 1 1 2.7871986882754021e+00 0.0000000000000000e+00 2.1921611405773640e+00 + 2 1 2.7871986882754021e+00 0.0000000000000000e+00 2.1921611405773640e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 8.6958423865611415e-04 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 4.5936917428274754e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 4.0750131172460095e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 4.0750131172460095e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml b/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml new file mode 100644 index 00000000000..0a8773a10d2 --- /dev/null +++ b/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml @@ -0,0 +1,67 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:53 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.5 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${u0} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution zplane 0.0 1.0 +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + knorm 10000 + kt 2.8e3 + en 1.0 + xmu 0.4 + grav 1.0 + u0 1.0 + radius 0.0025 + dt 1e-05 + z0 0.002499982 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution +run_segments: |- + 25000 25000 25000 +analytic_enable: yes +analytic_model: slip_cessation +analytic_tol: 0.01 +analytic_segment: 2 +run_pos: |2 + 0 1 2.3750050906720896e-01 0.0000000000000000e+00 2.4999825715246804e-03 + 1 1 4.5000101847256818e-01 0.0000000000000000e+00 2.4999822976702916e-03 + 2 1 8.7756546272827377e-02 0.0000000000000000e+00 2.4999821312213190e-03 +run_vel: |2 + 0 1 9.0000137227135268e-01 0.0000000000000000e+00 1.6622797951378513e-06 + 1 1 8.0000302069740337e-01 0.0000000000000000e+00 -2.4587853520681649e-06 + 2 1 7.1424033326038117e-01 0.0000000000000000e+00 1.9746681804860687e-06 +run_torque: |2 + 0 1 0.0000000000000000e+00 1.7428475319620357e-07 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.7702329708439016e-07 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 -8.8091649323608411e-08 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 9.9998627728646241e+01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.9999697930258714e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 2.8575966673961568e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml b/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml new file mode 100644 index 00000000000..9adb519e396 --- /dev/null +++ b/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml @@ -0,0 +1,67 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:54 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.5 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${u0} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 1.0 ${xmu} damping coeff_restitution zplane 0.0 1.0 +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + emod 1.0e4 + poisson 0.33 + en 1.0 + xmu 0.4 + grav 1.0 + u0 1.0 + radius 0.0025 + dt 1.0e-5 + z0 0.0024393 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 1.0 ${xmu} +run_segments: |- + 25000 25000 25000 +analytic_enable: yes +analytic_model: slip_cessation +analytic_tol: 0.01 +analytic_segment: 2 +run_pos: |2 + 0 1 2.3750099591375901e-01 0.0000000000000000e+00 2.4393450200047872e-03 + 1 1 4.5000199343264757e-01 0.0000000000000000e+00 2.4393860793755951e-03 + 2 1 8.7746482949875096e-02 0.0000000000000000e+00 2.4393374564208076e-03 +run_vel: |2 + 0 1 9.0000134588013636e-01 0.0000000000000000e+00 6.7747260632175400e-06 + 1 1 8.0000429385394667e-01 0.0000000000000000e+00 -5.9520847938169145e-07 + 2 1 7.1426001642140247e-01 0.0000000000000000e+00 -6.7225606190598820e-06 +run_torque: |2 + 0 1 0.0000000000000000e+00 1.7670628532812425e-07 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.7652688816506083e-07 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 -1.7655407487740076e-07 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 9.9998654119854535e+01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.9999570614603323e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 2.8573998357857914e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml b/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml new file mode 100644 index 00000000000..0fbee36f8e3 --- /dev/null +++ b/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml @@ -0,0 +1,67 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:54 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.5 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set ${u0} 0.0 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 1.0 ${xmu} damping coeff_restitution zplane 0.0 1.0 +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + emod 1.0e4 + poisson 0.33 + en 1.0 + xmu 0.2 + grav 1.0 + u0 1.0 + radius 0.0025 + dt 1e-05 + z0 0.0024393 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 1.0 ${xmu} +run_segments: |- + 50000 50000 50000 +analytic_enable: yes +analytic_model: slip_cessation +analytic_tol: 0.01 +analytic_segment: 2 +run_pos: |2 + 0 1 4.7500049189900018e-01 0.0000000000000000e+00 2.4393860793755951e-03 + 1 1 3.5000101809699813e-01 0.0000000000000000e+00 2.4393006646650163e-03 + 2 1 1.7551164940352082e-01 0.0000000000000000e+00 2.4393847554867532e-03 +run_vel: |2 + 0 1 9.0000113727180076e-01 0.0000000000000000e+00 -5.9520847938169145e-07 + 1 1 8.0000078101014194e-01 0.0000000000000000e+00 1.1860999086160702e-06 + 2 1 7.1430752414524312e-01 0.0000000000000000e+00 -1.7672858038705098e-06 +run_torque: |2 + 0 1 0.0000000000000000e+00 8.8263444082530414e-08 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 8.8450075760771054e-08 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 8.8256382010735907e-08 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 9.9998862728211961e+01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.9999921898988876e+02 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 2.8569247585478314e+02 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml b/unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml deleted file mode 100644 index 6634a3640a6..00000000000 --- a/unittest/granular/tests/dem05-spin-headon-cof-3d-si.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: angular_sphere_impact.in (user script). Two identical spheres -# collide head-on along x (equal & opposite velocity and spin). Collision -# axis is already x, matching collision_restitution's hardcoded momentum/ -# restitution check along the atom-array x-component, so no remapping was -# needed. The model checks momentum conservation + coefficient of -# restitution along the collision axis; it does not assert on the spin -# components, which the source script sets equal & opposite for coverage -# of the tangential/rolling sub-models but are not asserted here. -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.2 0.2 -0.1 0.1 -0.1 0.1 units box - create_box 1 box - create_atoms 1 single -${sep} 0.0 0.0 units box - create_atoms 1 single ${sep} 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - group left id 1 - group right id 2 - velocity left set ${vin} 0.0 0.0 - velocity right set -${vin} 0.0 0.0 - set group left omega 0.0 0.0 ${omega0} - set group right omega 0.0 0.0 -${omega0} - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 0.005 - dens 2700.0 - emod 7.0e10 - poisson 0.33 - en 0.5 - xmu 0.4 - vin 2.0 - omega0 22.0 - radius 0.0025 - dt 1.0e-8 - sep 0.002550 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 0.5 ${xmu} -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. -run_segments: ! |- - 1300 900 -analytic_enable: yes -analytic_model: collision_restitution -analytic_tol: 0.02 -analytic_segment: 1 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml b/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml new file mode 100644 index 00000000000..9132fddf7e5 --- /dev/null +++ b/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml @@ -0,0 +1,83 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:55 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.5 0.5 -0.5 0.5 -0.3 0.8 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + create_atoms 1 single 0.0 0.0 0.0 units box + set atom 1 diameter ${diam_small} density ${dens_small} + set atom 2 diameter ${diam_large} density ${dens_large} + group small id 1 + velocity small set 0.0 0.0 -${vin} + set group small omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam_small 0.2 + dens_small 2700.0 + diam_large 1.0 + dens_large 2.7e6 + knorm 1.2e+08 + kt 3.4e7 + en 0.5 + xmu 0.40 + vin 0.2 + omega0 22.860 + radius 0.1 + dt 1.0e-6 + z0 0.60001 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_history ${kt} 0.0 ${xmu} damping coeff_restitution +run_segments: |- + 600 700 500 +analytic_enable: yes +analytic_model: spin_impact +analytic_tol: 0.07 +analytic_segment: 1 +run_pos: |2 + 0 2 -2.1345653460170543e-10 0.0000000000000000e+00 -5.4398023995067662e-10 + 0 1 2.6682066825213155e-05 0.0000000000000000e+00 5.9995799752999324e-01 + 1 2 -8.9445779450216934e-10 0.0000000000000000e+00 -2.2098208175518701e-09 + 1 1 1.1180722431277068e-04 0.0000000000000000e+00 6.0002622760219382e-01 + 2 2 -1.4027353497892222e-09 0.0000000000000000e+00 -3.4092834467245913e-09 + 2 1 1.7534191872364536e-04 0.0000000000000000e+00 6.0007616043084344e-01 +run_vel: |2 + 0 2 -8.0430750822786784e-07 0.0000000000000000e+00 -2.0296893792335748e-06 + 0 1 1.0053843852848338e-01 0.0000000000000000e+00 5.3711172404196837e-02 + 1 2 -1.0165551105740206e-06 0.0000000000000000e+00 -2.3989252583452997e-06 + 1 1 1.2706938882175314e-01 0.0000000000000000e+00 9.9865657293162532e-02 + 2 2 -1.0165551105740206e-06 0.0000000000000000e+00 -2.3989252583452997e-06 + 2 1 1.2706938882175314e-01 0.0000000000000000e+00 9.9865657293162532e-02 +run_torque: |2 + 0 2 0.0000000000000000e+00 -8.3803706738178062e+02 0.0000000000000000e+00 + 0 1 0.0000000000000000e+00 -1.6757925335464904e+02 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 2 0.0000000000000000e+00 -4.0212541014183523e-06 0.0000000000000000e+00 + 0 1 0.0000000000000000e+00 2.0347067284486268e+01 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 -5.0823681327759345e-06 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.9683950332657247e+01 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 -5.0823681327759345e-06 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 1.9683950332657247e+01 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml b/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml new file mode 100644 index 00000000000..786551c3fa7 --- /dev/null +++ b/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml @@ -0,0 +1,83 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:55 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.5 0.5 -0.5 0.5 -0.3 0.8 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + create_atoms 1 single 0.0 0.0 0.0 units box + set atom 1 diameter ${diam_small} density ${dens_small} + set atom 2 diameter ${diam_large} density ${dens_large} + group small id 1 + velocity small set 0.0 0.0 -${vin} + set group small omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam_small 0.2 + dens_small 2700.0 + diam_large 1.0 + dens_large 2.7e6 + emod 7.0e10 + poisson 0.33 + en 0.5 + xmu 0.40 + vin 0.2 + omega0 22.860 + radius 0.1 + dt 1.0e-6 + z0 0.60001 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 0.5 ${xmu} +run_segments: |- + 600 700 500 +analytic_enable: yes +analytic_model: spin_impact +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: |2 + 0 2 -1.5885705308571179e-10 0.0000000000000000e+00 -4.7147731004024763e-10 + 0 1 1.9857131635713953e-05 0.0000000000000000e+00 5.9994893466375554e-01 + 1 2 -7.9871282405435688e-10 0.0000000000000000e+00 -2.1315611657730344e-09 + 1 1 9.9839103006795345e-05 0.0000000000000000e+00 6.0001644514572128e-01 + 2 2 -1.2822874932073249e-09 0.0000000000000000e+00 -3.3314791827185765e-09 + 2 1 1.6028593665091926e-04 0.0000000000000000e+00 6.0006643489783684e-01 +run_vel: |2 + 0 2 -7.2193501311427468e-07 0.0000000000000000e+00 -1.9478778908996579e-06 + 0 1 9.0241876639284166e-02 0.0000000000000000e+00 4.3484736362457206e-02 + 1 2 -9.6714933830595133e-07 0.0000000000000000e+00 -2.3998360338912761e-06 + 1 1 1.2089366728824319e-01 0.0000000000000000e+00 9.9979504236410416e-02 + 2 2 -9.6714933830595133e-07 0.0000000000000000e+00 -2.3998360338912761e-06 + 2 1 1.2089366728824319e-01 0.0000000000000000e+00 9.9979504236410416e-02 +run_torque: |2 + 0 2 0.0000000000000000e+00 -9.5750523521425168e+02 0.0000000000000000e+00 + 0 1 0.0000000000000000e+00 -1.9146192939677110e+02 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 2 0.0000000000000000e+00 -3.6094175732518426e-06 0.0000000000000000e+00 + 0 1 0.0000000000000000e+00 2.0604516348029431e+01 0.0000000000000000e+00 + 1 2 0.0000000000000000e+00 -4.8353529322051940e-06 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.9838426252892553e+01 0.0000000000000000e+00 + 2 2 0.0000000000000000e+00 -4.8353529322051940e-06 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 1.9838426252892553e+01 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml b/unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml deleted file mode 100644 index 576e603d8ec..00000000000 --- a/unittest/granular/tests/dem06-spin-unequal-cof-3d-si.yaml +++ /dev/null @@ -1,75 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: in.angular_bidisperse (user script). A small, light, spinning -# sphere impacts a much larger and much denser (effectively rigid/immobile) -# stationary sphere. Re-expressed with the approach direction along -z and -# the spin about y (the convention assumed by test_analytic_models.cpp's -# spin_impact model, which treats the heavy partner like a rigid wall), -# instead of the source script's x-axis approach with spin about z. -# Material values (moduli, densities, diameters, friction, restitution) -# are transcribed unchanged from the source script. -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.5 0.5 -0.5 0.5 -0.3 0.6 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - create_atoms 1 single 0.0 0.0 0.0 units box - set atom 1 diameter ${diam_small} density ${dens_small} - set atom 2 diameter ${diam_large} density ${dens_large} - group small id 1 - velocity small set 0.0 0.0 -${vin} - set group small omega 0.0 ${omega0} 0.0 - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam_small 0.2 - dens_small 2700.0 - diam_large 1.0 - dens_large 2.7e6 - emod 7.0e10 - poisson 0.33 - en 0.5 - xmu 0.40 - vin 0.2 - omega0 22.860 - radius 0.1 - dt 1.0e-6 - z0 0.60001 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential mindlin NULL 0.5 ${xmu} -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow. -# analytic_segment must fall in free flight after rebound, with omega0 -# large enough relative to vin that contact stays in gross sliding -# (matches the source script's parameters, but re-verify with -s). -run_segments: ! |- - 300 300 -analytic_enable: yes -analytic_model: spin_impact -analytic_tol: 0.02 -analytic_segment: 1 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem06-spin-wall-3d-si.yaml b/unittest/granular/tests/dem06-spin-wall-3d-si.yaml new file mode 100644 index 00000000000..2ae6df091d9 --- /dev/null +++ b/unittest/granular/tests/dem06-spin-wall-3d-si.yaml @@ -0,0 +1,67 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:55 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary f f f + atom_style sphere + region box block -0.5 0.5 -0.5 0.5 -0.01 0.5 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + velocity all set 0.0 0.0 -${vin} + set group all omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.2 + dens 2700.0 + emod 7e+10 + poisson 0.33 + en 0.5 + xmu 0.40 + vin 0.2 + omega0 22.860 + radius 0.1 + dt 1.0e-6 + z0 0.10001 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} tangential mindlin NULL 0.5 ${xmu} damping coeff_restitution +run_segments: |- + 300 958 400 +analytic_enable: yes +analytic_model: spin_impact +analytic_tol: 0.02 +analytic_segment: 1 +run_pos: |2 + 0 1 2.1008288624971314e-06 0.0000000000000000e+00 9.9959197317964654e-02 + 1 1 9.6597688668275587e-05 0.0000000000000000e+00 1.0001613952907509e-01 + 2 1 1.4495446506513951e-04 0.0000000000000000e+00 1.0005613631040647e-01 +run_vel: |2 + 0 1 2.9322567733461518e-02 0.0000000000000000e+00 -1.0881015968111697e-01 + 1 1 1.2089194099215592e-01 0.0000000000000000e+00 9.9991953332364936e-02 + 2 1 1.2089194099215592e-01 0.0000000000000000e+00 9.9991953332364936e-02 +run_torque: |2 + 0 1 0.0000000000000000e+00 -2.4536169425110313e+02 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 2.2126935806663486e+01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 1.9837701475196010e+01 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 1.9837701475196010e+01 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml b/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml new file mode 100644 index 00000000000..924e530a0ce --- /dev/null +++ b/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml @@ -0,0 +1,68 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:56 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + set group all omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + emod 1.0e4 + poisson 0.33 + en 1.0 + mur 0.05 + kr 1.0e4 + grav 1.0 + omega0 1.0 + radius 0.0025 + dt 1.0e-6 + z0 0.0024393 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution +run_segments: |- + 3000 4000 3000 +analytic_enable: yes +analytic_model: rolling_decay +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4393047109726824e-03 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4393235948414883e-03 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4393432012658920e-03 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 3.0821618401636272e-06 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 6.0463003134993147e-06 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 6.7812991755638290e-06 +run_torque: |2 + 0 1 0.0000000000000000e+00 -2.2110307897107791e-08 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 -2.2099990069744646e-08 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 -2.2089279148959932e-08 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 8.4987091857109898e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 6.4972271164742845e-01 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 4.9968596170431628e-01 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml b/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml new file mode 100644 index 00000000000..93f6febb825 --- /dev/null +++ b/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml @@ -0,0 +1,67 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:56 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + set group all omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + knorm 10000 + en 1.0 + mur 0.05 + kr 1.0e4 + grav 1.0 + omega0 1.0 + radius 0.0025 + dt 1.0e-6 + z0 0.002499982 +pair_style: granular +pair_coeff: | + * * hooke ${knorm} ${en} tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution +run_segments: |- + 3000 4000 3000 +analytic_enable: yes +analytic_model: rolling_decay +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4999826039845000e-03 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4999825690977923e-03 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4999820048911287e-03 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 -1.3471417605498602e-06 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 1.6832868579600465e-06 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 -4.2486660149128432e-07 +run_torque: |2 + 0 1 0.0000000000000000e+00 -2.1745019375082365e-08 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 -2.1788627759672385e-08 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 -2.2493886089164878e-08 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 8.5009282187891866e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 6.4994130044799026e-01 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 5.0004670812095975e-01 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml b/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml new file mode 100644 index 00000000000..7c7f3095c02 --- /dev/null +++ b/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml @@ -0,0 +1,68 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:56 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + set group all omega 0.0 ${omega0} 0.0 + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} +post_commands: | + fix grav all gravity 1.0 vector 0.0 0.0 -1.0 + fix integr all nve/sphere + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.005 + dens 2700.0 + emod 1.0e4 + poisson 0.33 + en 1.0 + mur 0.2 + kr 1.0e4 + grav 1.0 + omega0 1.0 + radius 0.0025 + dt 1.0e-6 + z0 0.0024393 +pair_style: granular +pair_coeff: | + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution +run_segments: |- + 1000 1500 1500 +analytic_enable: yes +analytic_model: rolling_decay +analytic_tol: 0.01 +analytic_segment: 1 +run_pos: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4393005321636787e-03 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4393032901667698e-03 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 2.4393082544577767e-03 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 1.0621323433430524e-06 + 1 1 0.0000000000000000e+00 0.0000000000000000e+00 2.5981325983383736e-06 + 2 1 0.0000000000000000e+00 0.0000000000000000e+00 3.9901932532700743e-06 +run_torque: |2 + 0 1 0.0000000000000000e+00 -8.8450365379092588e-08 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 -8.8444337065696669e-08 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 -8.8433486697103137e-08 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 7.9994642242805813e-01 0.0000000000000000e+00 + 1 1 0.0000000000000000e+00 4.9963922237705533e-01 0.0000000000000000e+00 + 2 1 0.0000000000000000e+00 1.9936081024606936e-01 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml b/unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml deleted file mode 100644 index f2a96651a94..00000000000 --- a/unittest/granular/tests/dem07-wall-normal-cof-3d-si.yaml +++ /dev/null @@ -1,73 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: normal_contact_cof.in (user script). -# Single sphere normal-impacting a rigid wall, fully elastic (e = 1), -# frictionless tangential response. Re-expressed with the wall normal along -# +z (test_analytic_models.cpp's hertz_normal_impact model assumes a -# z-plane wall) instead of the original script's xplane; all material -# and kinematic values are otherwise unchanged from the source script. -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box - create_box 1 box - create_atoms 1 single 0.0 0.0 ${z0} units box - set group all diameter ${diam} density ${dens} - velocity all set 0.0 0.0 -${vin} - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL -input_file: -natoms: 1 -variables: ! | - diam 0.005 - dens 7000.0 - emod 1.0e11 - poisson 0.25 - en 1.0 - vin 3.9 - vrela 3.9 - mred_factor 1.0 - floor 0.0 - radius 0.0025 - dt 1.0e-8 - z0 0.002550 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} ${en} ${poisson} tangential linear_nohistory 0.0 0.0 damping coeff_restitution -# NOTE: run_segments and the run_pos/run_vel/run_torque/run_omega reference -# blocks below are NOT yet generated -- they must be produced by actually -# running the compiled test program against a built LAMMPS+GRANULAR, e.g.: -# test_dem_11 tests/dem11-wall-normal-cof-3d-si.yaml -g new.yaml -# then inspecting/renaming new.yaml, or updating in place with -u. -# The starting gap (z0) is small so contact happens quickly; the first -# analytic_segment should land at (or very near) peak compression -- -# check with -s to see per-quantity error stats and retune if needed. -run_segments: ! |- - 1300 900 -analytic_enable: yes -analytic_model: hertz_normal_impact -analytic_tol: 0.01 -analytic_segment: 0 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... diff --git a/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml b/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml new file mode 100644 index 00000000000..06cd297ce81 --- /dev/null +++ b/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml @@ -0,0 +1,60 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:57 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p p + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.05 0.05 units box + create_box 1 box + create_atoms 1 single -${sep} 0.0 0.0 units box + create_atoms 1 single ${sep} 0.0 0.0 units box + set group all diameter ${diam} density ${dens} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep 1.0e-10 +post_commands: | + fix integr all nve/sphere +input_file: +natoms: 2 +variables: | + diam 0.02 + dens 2800.0 + emod 4.8e10 + poisson 0.20 + ndamp 0.0 + coh 0.1 + xmu 0.35 + reff 0.005 + radius 0.01 + sep 0.00999999999999999 +pair_style: granular +pair_coeff: | + * * dmt ${emod} ${ndamp} ${poisson} ${coh} tangential mindlin NULL 0.0 ${xmu} +run_segments: |- + 0 +analytic_enable: yes +analytic_model: pulloff_dmt +analytic_tol: 0.001 +analytic_segment: 0 +run_pos: |2 + 0 1 -9.9999999999999898e-03 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 9.9999999999999898e-03 0.0000000000000000e+00 0.0000000000000000e+00 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 0 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml b/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml new file mode 100644 index 00000000000..4d2d1eb968b --- /dev/null +++ b/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml @@ -0,0 +1,56 @@ +--- +lammps_version: 4 Jul 2026 +tags: granular,, generated +date_generated: Tue Jul 21 21:40:57 2026 +epsilon: 1e-10 +skip_tests: +prerequisites: | + atom sphere + pair granular +pre_commands: | + units si + dimension 3 + boundary p p f + atom_style sphere + region box block -0.05 0.05 -0.05 0.05 -0.01 0.05 units box + create_box 1 box + create_atoms 1 single 0.0 0.0 ${z0} units box + set group all diameter ${diam} density ${dens} + comm_modify vel yes + neighbor 0.001 bin + neigh_modify delay 0 + timestep 1.0e-10 +post_commands: | + fix integr all nve/sphere + fix zwall all wall/gran granular dmt ${emod} ${ndamp} ${poisson} ${coh} tangential mindlin NULL 0.0 ${xmu} zplane 0.0 NULL +input_file: +natoms: 1 +variables: | + diam 0.02 + dens 2800.0 + emod 4.8e10 + poisson 0.20 + ndamp 0.0 + coh 0.1 + xmu 0.35 + reff 0.01 + radius 0.01 + z0 0.00999999999999999 +pair_style: granular +pair_coeff: | + * * dmt ${emod} ${ndamp} ${poisson} ${coh} tangential mindlin NULL 0.0 ${xmu} +run_segments: |- + 0 +analytic_enable: yes +analytic_model: pulloff_dmt +analytic_tol: 0.001 +analytic_segment: 0 +run_pos: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 9.9999999999999898e-03 +run_vel: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_torque: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_omega: |2 + 0 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +... diff --git a/unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml b/unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml deleted file mode 100644 index 3b26fa73eef..00000000000 --- a/unittest/granular/tests/dem08-twosphere-normal-3d-si.yaml +++ /dev/null @@ -1,70 +0,0 @@ ---- -lammps_version: REGENERATE -tags: granular, generated -date_generated: REGENERATE -epsilon: 1e-10 -skip_tests: -prerequisites: ! | - atom sphere - pair granular -# Source: in.normal_simple (user script). Two identical spheres, head-on -# elastic normal impact along x (native axis of the source script; no -# remapping needed since hertz_normal_impact's two-sphere branch is -# axis-agnostic). Friction is present in the original pair_coeff (mindlin, -# mu = 0.35) but is irrelevant to a purely normal, non-rotating impact, so -# it is kept for coverage. -pre_commands: ! | - units si - dimension 3 - boundary f f f - atom_style sphere - region box block -0.05 0.05 -0.03 0.03 -0.03 0.03 units box - create_box 1 box - create_atoms 1 single -${sep} 0.0 0.0 units box - create_atoms 1 single ${sep} 0.0 0.0 units box - set group all diameter ${diam} density ${dens} - group left id 1 - group right id 2 - velocity left set ${vin} 0.0 0.0 - velocity right set -${vin} 0.0 0.0 - comm_modify vel yes - neighbor 0.001 bin - neigh_modify delay 0 - timestep ${dt} -post_commands: ! | - fix integr all nve/sphere -input_file: -natoms: 2 -variables: ! | - diam 0.02 - dens 2800.0 - emod 4.8e10 - poisson 0.20 - xmu 0.35 - vin 10.0 - vrela 20.0 - mred_factor 0.5 - radius 0.01 - dt 1.0e-10 - sep 0.0101 -pair_style: granular -pair_coeff: ! | - * * hertz/material ${emod} 0.0 ${poisson} tangential mindlin NULL 0.0 ${xmu} -# NOTE: see dem11-wall-normal-cof-3d-si.yaml for the regeneration workflow; -# run_segments/reference blocks below are placeholders pending an actual -# LAMMPS run with -u / -g. -run_segments: ! |- - 600 400 -analytic_enable: yes -analytic_model: hertz_normal_impact -analytic_tol: 0.01 -analytic_segment: 0 -run_pos: ! |2 - # TODO: regenerate -- see NOTE above -run_vel: ! |2 - # TODO: regenerate -- see NOTE above -run_torque: ! |2 - # TODO: regenerate -- see NOTE above -run_omega: ! |2 - # TODO: regenerate -- see NOTE above -... From beae114abceafd3f51419a4cebe4b11b61248f54 Mon Sep 17 00:00:00 2001 From: zawh4159 Date: Tue, 21 Jul 2026 22:18:06 -0600 Subject: [PATCH 05/12] add audit script for dem unittests --- unittest/granular/dem_audit.py | 185 +++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 unittest/granular/dem_audit.py diff --git a/unittest/granular/dem_audit.py b/unittest/granular/dem_audit.py new file mode 100644 index 00000000000..671cba269e1 --- /dev/null +++ b/unittest/granular/dem_audit.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +# Analytic audit for unittest/granular. Per checked quantity, prints: the closed-form +# equation, the value it gives from the YAML variables (computed here, independent of +# the harness), the harness's own expected, the simulated value, and relative errors. +# Forces the harness to print by running a temp copy with a tiny tolerance. Leaves +# nothing behind. Run from the build dir: python3 dem_audit.py [tests_dir] +import sys, os, re, math, glob, subprocess, tempfile +PI = math.pi +HERE = os.path.dirname(os.path.abspath(__file__)) +# tests dir: 1st arg, else ./tests next to this script, else the cwd's tests +TESTS = os.path.expanduser(sys.argv[1]) if len(sys.argv) > 1 else ( + os.path.join(HERE, "tests") if os.path.isdir(os.path.join(HERE, "tests")) + else os.path.join(os.getcwd(), "tests")) + +def find_build(): + # 2nd arg wins; else search likely locations for the test_dem_01 binary + if len(sys.argv) > 2: + return os.path.expanduser(sys.argv[2]) + if os.getenv("DEM_BUILD"): + return os.path.expanduser(os.getenv("DEM_BUILD")) + cands = [os.getcwd()] + # walk up from here looking for a sibling 'build' dir, then scan it + up = HERE + for _ in range(6): + up = os.path.dirname(up) + if not up or up == "/": + break + cands.append(os.path.join(up, "build")) + for base in cands: + if not base or not os.path.isdir(base): + continue + if os.path.exists(os.path.join(base, "test_dem_01")): + return base + hit = glob.glob(os.path.join(base, "**", "test_dem_01"), recursive=True) + if hit: + return os.path.dirname(hit[0]) + return os.getcwd() + +BUILD = find_build() + +def variables(txt): + m = re.search(r'^variables:.*?\n(.*?)\n[A-Za-z_]\w*:', txt, re.S | re.M) + if not m: return {} + d = {} + for ln in m.group(1).splitlines(): + mm = re.match(r'\s+([A-Za-z_]\w*)\s+(\S+)', ln) + if mm: + try: d[mm.group(1)] = float(mm.group(2)) + except ValueError: pass + return d + +def radius(v): return v.get('radius', v.get('diam', 0.0) / 2.0) +def dim_of(txt): + m = re.search(r'\n\s+dimension\s+(\d)', txt) + return int(m.group(1)) if m else 3 +def massof(v, txt): + d, dm = v.get('dens', 0.0), v.get('diam', 0.0) + return dens_disc(d, dm) if dim_of(txt) == 2 else d * (PI / 6.0) * dm ** 3 +def dens_disc(d, dm): return d * (PI / 4.0) * dm ** 2 + +def seg_time(txt): + try: + segs = [int(x) for x in re.search(r'^run_segments:.*?\n\s+([\d ]+)', txt, re.S | re.M).group(1).split()] + aseg = int(re.search(r'^analytic_segment:\s*(-?\d+)', txt, re.M).group(1)) + dt = float(re.search(r'\n\s+dt\s+(\S+)', txt).group(1)) + if aseg < 0: aseg = len(segs) - 1 + return sum(segs[:aseg + 1]) * dt + except Exception: + return None + + +def derived(model, v, txt): + r = radius(v); m = massof(v, txt); out = [] + out.append(("radius r", r)) + out.append(("mass m = dens*(pi/4)*diam^2 [2D disc]" if dim_of(txt)==2 else "mass m = dens*(pi/6)*diam^3", m)) + if model in ('collision_restitution',): + out.append(("m_red = m/2 (two equal spheres)", m/2)) + if model == 'hertz_normal_impact': + out.append(("m_red = mred_factor*m", v.get('mred_factor',1.0)*m)) + out.append(("(1/2)*m_red*vrela^2", 0.5*v.get('mred_factor',1.0)*m*v.get('vrela',0.0)**2)) + if model == 'rolling_decay': + t = seg_time(txt) + if t is not None: out.append(("t = sum(run_segments[:aseg+1])*dt", t)) + if model == 'pulloff_dmt': + out.append(("R_eff = reff", v.get('reff'))) + return out + +def formulas(model, v, txt): + r = radius(v); f = {} + try: + if model == 'collision_restitution': + f['collision_restitution e'] = ("e = -(v1x - v2x)/(2*vin)", v['en']) + elif model == 'oblique_impact': + e, mu, vz, vx = v['en'], v['xmu'], v['vz_in'], v['vx_in'] + f['oblique_impact vz_out'] = ("vz_out = e*vz_in", e * vz) + f['oblique_impact vx_out'] = ("vx_out = vx_in - mu*(1+e)*vz_in", vx - mu * (1 + e) * vz) + f['oblique_impact omega_y'] = ("omega_y = (5/2)*mu*(1+e)*vz_in/r", 2.5 * mu * (1 + e) * vz / r) + elif model == 'slip_cessation': + u0 = v['u0'] + f['slip_cessation vx'] = ("vx = 5*u0/7", 5 * u0 / 7) + f['slip_cessation omega_y'] = ("omega_y = (5*u0/7)/r", (5 * u0 / 7) / r) + elif model == 'spin_impact': + e, mu, vin, w0 = v['en'], v['xmu'], v['vin'], v['omega0'] + f['spin_impact vz_out'] = ("vz_out = e*vin", e * vin) + f['spin_impact vx_out'] = ("vx_out = mu*(1+e)*vin", mu * (1 + e) * vin) + f['spin_impact omega_y'] = ("omega_y = omega0 - (5/2)*mu*(1+e)*vin/r", w0 - 2.5 * mu * (1 + e) * vin / r) + elif model == 'rolling_decay': + t = seg_time(txt) + if t is not None: + f['rolling_decay omega_y'] = (f"omega_y(t) = omega0 - (5*mur*g)/(2r)*t [t={t:.4g}s]", + v['omega0'] - (5 * v['mur'] * v['grav']) / (2 * r) * t) + else: + f['rolling_decay omega_y'] = ("omega_y(t) = omega0 - (5*mur*g)/(2r)*t", None) + elif model == 'pulloff_dmt': + f['pulloff_dmt force'] = ("F = 4*pi*coh*reff", 4 * PI * v['coh'] * v['reff']) + elif model == 'hertz_normal_impact': + f['hertz_normal_impact peak energy balance'] = ( + "(1/2)*m_red*vrela^2 = (2/5)*Pmax*alpha [LHS here; RHS from sim force]", + 0.5 * v['mred_factor'] * massof(v, txt) * v['vrela'] ** 2) + except KeyError: + pass + return f + +def harness_numbers(yaml_path, driver): + txt = open(yaml_path).read() + t = tempfile.NamedTemporaryFile('w', suffix='.yaml', dir='/tmp', delete=False) + t.write(re.sub(r'analytic_tol:\s*\S+', 'analytic_tol: 1e-14', txt)); t.close() + try: + r = subprocess.run([driver, t.name, '-v'], capture_output=True, text=True, cwd=BUILD, timeout=300) + out = r.stdout + r.stderr + except Exception: + out = "" + finally: + os.unlink(t.name) + seen = {} + for what, E, G in re.findall(r'([A-Za-z_][\w ]*?): expected (\S+) got (\S+)', out): + try: seen[what.strip()] = (float(E), float(G)) + except ValueError: pass + return seen + +def rel(a, b): + return abs(a - b) / max(abs(b), 1e-300) + +def main(): + print(f"tests: {TESTS}\nbuild: {BUILD}") + files = sorted(glob.glob(os.path.join(TESTS, "dem*.yaml"))) + skipped = [] + for y in files: + txt = open(y).read() + mm = re.search(r'^analytic_model:\s*(\S+)', txt, re.M) + nn = re.search(r'dem(\d\d)', os.path.basename(y)) + if not mm or not nn: + skipped.append(os.path.basename(y)); continue + model = mm.group(1) + driver = os.path.join(BUILD, f"test_dem_{nn.group(1)}") + v = variables(txt) + fx = formulas(model, v, txt) + hv = harness_numbers(y, driver) if os.path.exists(driver) else {} + print(f"\n### {os.path.basename(y)} [{model}]") + if v: + print(" variables: " + ", ".join(f"{k}={val:g}" for k, val in v.items())) + dv = derived(model, v, txt) + if dv: + print(" derived: " + ", ".join(f"{name} = {val:.6g}" for name, val in dv)) + if not fx and not hv: + print(" (no variables/quantities parsed)"); continue + for k in (fx or hv): + eq, mine = fx.get(k, ("(see test_analytic_models.cpp)", None)) + E, G = hv.get(k, (None, None)) + label = k.split(None, 1)[-1] if ' ' in k else k + print(f" {label:<26} {eq}") + if E is not None: + line = f" harness expected = {E:.6g} simulated got = {G:.6g} relerr = {rel(G, E):.2e}" + if mine is not None: + line += (" (formula = harness expected OK)" if rel(mine, E) <= 1e-4 + else f" [!! formula here = {mine:.6g} DISAGREES with harness]") + print(line) + elif mine is not None: + print(f" formula value = {mine:.6g} (harness value needs the driver)") + if skipped: + print("\nskipped (no analytic_model / not a demNN file):", ", ".join(skipped)) + print() + +if __name__ == "__main__": + main() \ No newline at end of file From 98e3acee2aa34254b7cd336ac87024855e71f678 Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Mon, 27 Jul 2026 13:41:52 -0600 Subject: [PATCH 06/12] Update doc_readme for granular tests --- unittest/granular/doc_readme | 248 +++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 unittest/granular/doc_readme diff --git a/unittest/granular/doc_readme b/unittest/granular/doc_readme new file mode 100644 index 00000000000..9e34492de49 --- /dev/null +++ b/unittest/granular/doc_readme @@ -0,0 +1,248 @@ +Tests for granular (DEM) models +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 4Jul2026 + +The unittest/granular folder contains a YAML-driven test suite for +discrete element method (DEM) / granular contact models, built in the same +spirit as the force-style tests above but specialized for time-resolved +trajectories of small, analytically tractable granular systems. These tests +are only enabled if the :ref:GRANULAR package is enabled. + +There are 8 test programs, test_dem_01 through test_dem_08, covering +particle-impact-level benchmarks: two-sphere and sphere-wall collisions, +oblique and spinning-sphere impacts, rolling and slipping contact, and +cohesive pull-off. These follow the software-agnostic DEM benchmark of +:ref:Mohajeri et al. (rolling resistance and cohesion) +and the particle-impact benchmark of :ref:Chung and Ooi +(normal, oblique, and spinning-sphere collisions). The test programs are: + +.. list-table:: +:header-rows: 1 + +Program +Scenario +Analytic model +test_dem_01 +two-sphere head-on normal collision +collision_restitution +test_dem_02 +two-sphere elastic Hertzian normal impact (peak force) +hertz_normal_impact +test_dem_03 +sphere-wall elastic Hertzian normal impact (peak force) +hertz_normal_impact +test_dem_04 +oblique impact on a wall (gross-sliding friction) +oblique_impact +test_dem_05 +sphere sliding then rolling without slipping +slip_cessation +test_dem_06 +spinning sphere impact (rebound with friction) +spin_impact +test_dem_07 +rolling-resistance decay +rolling_decay +test_dem_08 +cohesive DMT pull-off force +pulloff_dmt + +Every test program shares the same driver logic, implemented in +unittest/granular/test_dem_common.cpp and compiled into the +granular_tests support library; each test_dem_0N.cpp only contains +the two GoogleTest fixtures (newton_on and newton_off). As with the +force-style tests, the reference systems are defined by YAML files in the +unittest/granular/tests folder and registered as CTest cases by their +file name (dem0N-*.yaml becomes test DEM0N:*); adding or removing a +YAML file requires re-running CMake. A given driver may cover several +variants of one scenario -- across contact models +(hooke, hooke/history, hertz, hertz/material, mindlin, +mindlin/rescale), dimensionality, or unit systems -- since it simply +runs every dem0N-*.yaml file that matches its number. + +Unlike the force-style tests, the entire system is built from the YAML +file rather than from a fixed input template. A YAML file provides an +optional variables block (emitted as :doc:index variables +so they can be substituted as ${name} anywhere in the command strings), +pre_commands that create the geometry, pair_style / pair_coeff +that select the contact model, and post_commands that add the +integrator and any walls. The trajectory is then advanced in a sequence of +run_segments and, after each segment, the per-atom positions, +velocities, torques, and angular velocities are compared against the +recorded reference. A minimal example (dem03-hertz-wall-3d-si.yaml) +looks like: + +.. code-block:: yaml + +lammps_version: 4 Jul 2026 +tags: granular, generated +date_generated: Tue Jul 21 21:40:51 2026 +epsilon: 1e-10 +prerequisites: | +atom sphere +pair granular +pre_commands: | +units si +dimension 3 +boundary f f f +atom_style sphere +region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box +create_box 1 box +create_atoms 1 single 0.0 0.0 ${z0} units box +set group all diameter ${diam} density ${dens} +velocity all set 0.0 0.0 -${vin} +comm_modify vel yes +neighbor 0.001 bin +neigh_modify delay 0 +timestep ${dt} +post_commands: | +fix integr all nve/sphere +fix zwall all wall/gran granular hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL +natoms: 1 +variables: | +diam 0.005 +dens 7000.0 +kn 7.11111e+10 +en 1.0 +vin 3.9 +vrela 3.9 +mred_factor 1.0 +radius 0.0025 +dt 1.0e-8 +z0 0.002550 +pair_style: granular +pair_coeff: | +* * hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution +run_segments: |- +1300 838 900 +analytic_enable: yes +analytic_model: hertz_normal_impact +analytic_tol: 0.01 +analytic_segment: 1 + +run_pos / run_vel / run_torque / run_omega blocks follow + +The following table describes the available keys: + +.. list-table:: +:header-rows: 1 + +Key: +Description: +epsilon +relative precision required for the recorded (regression) reference data +prerequisites +list of style kind / style name pairs required to run the test +variables +name/value pairs exposed as ${name} index variables for substitution +pre_commands +commands that build the geometry (units, box, atoms, set, timestep) +pair_style / pair_coeff +the particle-particle (or particle-wall) contact model +post_commands +fixes added after the geometry (integrator, walls) +run_segments +whitespace-separated list of run lengths; state is captured after each +run_pos, run_vel +reference positions and velocities, as segment tag x y z rows +run_torque, run_omega +reference torque and angular velocity (when applicable) +analytic_enable +yes to also assert a closed-form (analytic) model +analytic_model +which analytic model to evaluate (see below) +analytic_tol +relative tolerance for the analytic assertion (looser than epsilon) +analytic_segment +run segment at which the analytic model is checked (-1 means the last) + +The per-atom reference blocks use a segment tag x y z row format, so a +single block holds the data for all run segments and the row order does not +matter. Because granular/atomic systems do not build an atom map by +default, the reference generator iterates over local atoms by tag rather +than calling Atom::map(). + +Each test runs as a pure regression check (the recorded data is reproduced +to within epsilon) under both the newton on and newton off +fixtures, which are expected to give identical results. In addition, every +test opts in to an analytic check that compares a derived quantity against +a closed-form solution implemented in +unittest/granular/test_analytic_models.cpp. The analytic tolerance is +deliberately loose, because the soft-sphere DEM result only approaches the +idealized (hard-sphere or instantaneous-contact) solution. The models +currently implemented are: + +.. list-table:: +:header-rows: 1 + +Model: +Checks: +collision_restitution +two-sphere momentum conservation and restitution :math:e = -(v_1'-v_2')/(v_1-v_2) +hertz_normal_impact +Hertzian peak energy balance :math:\tfrac{1}{2}\mu_{red} V_{rela}^2 = \tfrac{2}{5} P_{max}\alpha_{max} +oblique_impact +gross-sliding rebound :math:v_x' = v_x - \mu(1+e)v_z, :math:\omega_y = \tfrac{5}{2}\mu(1+e)v_z/r +slip_cessation +rolling-without-slipping limit :math:u = 5 u_0/7, :math:\omega = u/r +spin_impact +gross-sliding rebound of a spinning sphere: :math:v_x' = \mu(1+e)v_n, :math:\omega_y' = \omega_0 - \tfrac{5}{2}\mu(1+e)v_n/r +rolling_decay +linear spin-down under rolling resistance: :math:\omega = \omega_0 - \tfrac{5 \mu_r g}{2 r} t +pulloff_dmt +DMT pull-off force at contact :math:|F| = 4 \pi \gamma R_{\mathrm{eff}} + +Adding a new reference (YAML) file +"""""""""""""""""""""""""""""""""" + +Copy an existing dem0N-*.yaml +for a similar scenario, adjust the variables, pre_commands, +pair_style/pair_coeff and post_commands for the new model, and +give it a new name matching the dem0N-*.yaml pattern of the test program +it belongs to. Leave out the reference data blocks initially, then +(re)generate them in place with: + +.. code-block:: bash + +TEST_ARGS=-u ctest -R DEM0N:myvariant + +or by running the driver directly (test_dem_0N dem0N-myvariant.yaml -u). +Do not write the generated file to a sibling dem0N-*.yaml name (for +example with the -g newfile.yaml option pointing into the tests +folder), because the CONFIGURE_DEPENDS glob would then register it as an +extra, stale test. After adding the file, re-run CMake so the new test is +registered, then verify it with ctest -V -R DEM0N:myvariant (the -s +option of the driver reports per-quantity error statistics, which helps when +choosing epsilon and the analytic tolerance). + +Adding a new test program +""""""""""""""""""""""""" + +Create test_dem_0N.cpp as a thin copy of an existing one (only the +GoogleTest suite name changes), add an +add_executable/register_dem_tests pair to +unittest/granular/CMakeLists.txt, and add the corresponding +dem0N-*.yaml reference files. If the new scenario needs a +closed-form check, add a named model to test_analytic_models.cpp +that reads its parameters from the variables block (and reads +masses, radii, etc. from the live LAMMPS instance to avoid depending on +derived quantities) and assert it with EXPECT_LE on the relative +error. + +References +"""""""""" + +.. _dem_Mohajeri2024: + +(Mohajeri et al., 2024) M. J. Mohajeri, C. Coetzee, and D. L. Schott, +A software-agnostic benchmark for DEM simulation of cohesive and +non-cohesive materials, Powder Technology, 447, 120136 (2024), +https://doi.org/10.1016/j.powtec.2024.120136 + +.. _dem_Chung2011: + +(Chung and Ooi, 2011) Y. C. Chung and J. Y. Ooi, Benchmark tests for +verifying discrete element modelling codes at particle impact level, +Granular Matter, 13, 643-656 (2011), +https://doi.org/10.1007/s10035-011-0277-0 From c49ab63df6e2d42d679ada31d66a1134df55101e Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Mon, 27 Jul 2026 13:42:21 -0600 Subject: [PATCH 07/12] Rename doc_readme to doc_readme.md --- unittest/granular/{doc_readme => doc_readme.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename unittest/granular/{doc_readme => doc_readme.md} (100%) diff --git a/unittest/granular/doc_readme b/unittest/granular/doc_readme.md similarity index 100% rename from unittest/granular/doc_readme rename to unittest/granular/doc_readme.md From b8651ee48c56f94b0f2203e52d24a5fb6d25f1fc Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Mon, 27 Jul 2026 13:44:46 -0600 Subject: [PATCH 08/12] Delete unittest/granular/doc_readme.md --- unittest/granular/doc_readme.md | 248 -------------------------------- 1 file changed, 248 deletions(-) delete mode 100644 unittest/granular/doc_readme.md diff --git a/unittest/granular/doc_readme.md b/unittest/granular/doc_readme.md deleted file mode 100644 index 9e34492de49..00000000000 --- a/unittest/granular/doc_readme.md +++ /dev/null @@ -1,248 +0,0 @@ -Tests for granular (DEM) models -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. versionadded:: 4Jul2026 - -The unittest/granular folder contains a YAML-driven test suite for -discrete element method (DEM) / granular contact models, built in the same -spirit as the force-style tests above but specialized for time-resolved -trajectories of small, analytically tractable granular systems. These tests -are only enabled if the :ref:GRANULAR package is enabled. - -There are 8 test programs, test_dem_01 through test_dem_08, covering -particle-impact-level benchmarks: two-sphere and sphere-wall collisions, -oblique and spinning-sphere impacts, rolling and slipping contact, and -cohesive pull-off. These follow the software-agnostic DEM benchmark of -:ref:Mohajeri et al. (rolling resistance and cohesion) -and the particle-impact benchmark of :ref:Chung and Ooi -(normal, oblique, and spinning-sphere collisions). The test programs are: - -.. list-table:: -:header-rows: 1 - -Program -Scenario -Analytic model -test_dem_01 -two-sphere head-on normal collision -collision_restitution -test_dem_02 -two-sphere elastic Hertzian normal impact (peak force) -hertz_normal_impact -test_dem_03 -sphere-wall elastic Hertzian normal impact (peak force) -hertz_normal_impact -test_dem_04 -oblique impact on a wall (gross-sliding friction) -oblique_impact -test_dem_05 -sphere sliding then rolling without slipping -slip_cessation -test_dem_06 -spinning sphere impact (rebound with friction) -spin_impact -test_dem_07 -rolling-resistance decay -rolling_decay -test_dem_08 -cohesive DMT pull-off force -pulloff_dmt - -Every test program shares the same driver logic, implemented in -unittest/granular/test_dem_common.cpp and compiled into the -granular_tests support library; each test_dem_0N.cpp only contains -the two GoogleTest fixtures (newton_on and newton_off). As with the -force-style tests, the reference systems are defined by YAML files in the -unittest/granular/tests folder and registered as CTest cases by their -file name (dem0N-*.yaml becomes test DEM0N:*); adding or removing a -YAML file requires re-running CMake. A given driver may cover several -variants of one scenario -- across contact models -(hooke, hooke/history, hertz, hertz/material, mindlin, -mindlin/rescale), dimensionality, or unit systems -- since it simply -runs every dem0N-*.yaml file that matches its number. - -Unlike the force-style tests, the entire system is built from the YAML -file rather than from a fixed input template. A YAML file provides an -optional variables block (emitted as :doc:index variables -so they can be substituted as ${name} anywhere in the command strings), -pre_commands that create the geometry, pair_style / pair_coeff -that select the contact model, and post_commands that add the -integrator and any walls. The trajectory is then advanced in a sequence of -run_segments and, after each segment, the per-atom positions, -velocities, torques, and angular velocities are compared against the -recorded reference. A minimal example (dem03-hertz-wall-3d-si.yaml) -looks like: - -.. code-block:: yaml - -lammps_version: 4 Jul 2026 -tags: granular, generated -date_generated: Tue Jul 21 21:40:51 2026 -epsilon: 1e-10 -prerequisites: | -atom sphere -pair granular -pre_commands: | -units si -dimension 3 -boundary f f f -atom_style sphere -region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box -create_box 1 box -create_atoms 1 single 0.0 0.0 ${z0} units box -set group all diameter ${diam} density ${dens} -velocity all set 0.0 0.0 -${vin} -comm_modify vel yes -neighbor 0.001 bin -neigh_modify delay 0 -timestep ${dt} -post_commands: | -fix integr all nve/sphere -fix zwall all wall/gran granular hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL -natoms: 1 -variables: | -diam 0.005 -dens 7000.0 -kn 7.11111e+10 -en 1.0 -vin 3.9 -vrela 3.9 -mred_factor 1.0 -radius 0.0025 -dt 1.0e-8 -z0 0.002550 -pair_style: granular -pair_coeff: | -* * hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution -run_segments: |- -1300 838 900 -analytic_enable: yes -analytic_model: hertz_normal_impact -analytic_tol: 0.01 -analytic_segment: 1 - -run_pos / run_vel / run_torque / run_omega blocks follow - -The following table describes the available keys: - -.. list-table:: -:header-rows: 1 - -Key: -Description: -epsilon -relative precision required for the recorded (regression) reference data -prerequisites -list of style kind / style name pairs required to run the test -variables -name/value pairs exposed as ${name} index variables for substitution -pre_commands -commands that build the geometry (units, box, atoms, set, timestep) -pair_style / pair_coeff -the particle-particle (or particle-wall) contact model -post_commands -fixes added after the geometry (integrator, walls) -run_segments -whitespace-separated list of run lengths; state is captured after each -run_pos, run_vel -reference positions and velocities, as segment tag x y z rows -run_torque, run_omega -reference torque and angular velocity (when applicable) -analytic_enable -yes to also assert a closed-form (analytic) model -analytic_model -which analytic model to evaluate (see below) -analytic_tol -relative tolerance for the analytic assertion (looser than epsilon) -analytic_segment -run segment at which the analytic model is checked (-1 means the last) - -The per-atom reference blocks use a segment tag x y z row format, so a -single block holds the data for all run segments and the row order does not -matter. Because granular/atomic systems do not build an atom map by -default, the reference generator iterates over local atoms by tag rather -than calling Atom::map(). - -Each test runs as a pure regression check (the recorded data is reproduced -to within epsilon) under both the newton on and newton off -fixtures, which are expected to give identical results. In addition, every -test opts in to an analytic check that compares a derived quantity against -a closed-form solution implemented in -unittest/granular/test_analytic_models.cpp. The analytic tolerance is -deliberately loose, because the soft-sphere DEM result only approaches the -idealized (hard-sphere or instantaneous-contact) solution. The models -currently implemented are: - -.. list-table:: -:header-rows: 1 - -Model: -Checks: -collision_restitution -two-sphere momentum conservation and restitution :math:e = -(v_1'-v_2')/(v_1-v_2) -hertz_normal_impact -Hertzian peak energy balance :math:\tfrac{1}{2}\mu_{red} V_{rela}^2 = \tfrac{2}{5} P_{max}\alpha_{max} -oblique_impact -gross-sliding rebound :math:v_x' = v_x - \mu(1+e)v_z, :math:\omega_y = \tfrac{5}{2}\mu(1+e)v_z/r -slip_cessation -rolling-without-slipping limit :math:u = 5 u_0/7, :math:\omega = u/r -spin_impact -gross-sliding rebound of a spinning sphere: :math:v_x' = \mu(1+e)v_n, :math:\omega_y' = \omega_0 - \tfrac{5}{2}\mu(1+e)v_n/r -rolling_decay -linear spin-down under rolling resistance: :math:\omega = \omega_0 - \tfrac{5 \mu_r g}{2 r} t -pulloff_dmt -DMT pull-off force at contact :math:|F| = 4 \pi \gamma R_{\mathrm{eff}} - -Adding a new reference (YAML) file -"""""""""""""""""""""""""""""""""" - -Copy an existing dem0N-*.yaml -for a similar scenario, adjust the variables, pre_commands, -pair_style/pair_coeff and post_commands for the new model, and -give it a new name matching the dem0N-*.yaml pattern of the test program -it belongs to. Leave out the reference data blocks initially, then -(re)generate them in place with: - -.. code-block:: bash - -TEST_ARGS=-u ctest -R DEM0N:myvariant - -or by running the driver directly (test_dem_0N dem0N-myvariant.yaml -u). -Do not write the generated file to a sibling dem0N-*.yaml name (for -example with the -g newfile.yaml option pointing into the tests -folder), because the CONFIGURE_DEPENDS glob would then register it as an -extra, stale test. After adding the file, re-run CMake so the new test is -registered, then verify it with ctest -V -R DEM0N:myvariant (the -s -option of the driver reports per-quantity error statistics, which helps when -choosing epsilon and the analytic tolerance). - -Adding a new test program -""""""""""""""""""""""""" - -Create test_dem_0N.cpp as a thin copy of an existing one (only the -GoogleTest suite name changes), add an -add_executable/register_dem_tests pair to -unittest/granular/CMakeLists.txt, and add the corresponding -dem0N-*.yaml reference files. If the new scenario needs a -closed-form check, add a named model to test_analytic_models.cpp -that reads its parameters from the variables block (and reads -masses, radii, etc. from the live LAMMPS instance to avoid depending on -derived quantities) and assert it with EXPECT_LE on the relative -error. - -References -"""""""""" - -.. _dem_Mohajeri2024: - -(Mohajeri et al., 2024) M. J. Mohajeri, C. Coetzee, and D. L. Schott, -A software-agnostic benchmark for DEM simulation of cohesive and -non-cohesive materials, Powder Technology, 447, 120136 (2024), -https://doi.org/10.1016/j.powtec.2024.120136 - -.. _dem_Chung2011: - -(Chung and Ooi, 2011) Y. C. Chung and J. Y. Ooi, Benchmark tests for -verifying discrete element modelling codes at particle impact level, -Granular Matter, 13, 643-656 (2011), -https://doi.org/10.1007/s10035-011-0277-0 From df2ddb079d936018c3e3ceccec4db8dd6f1f515b Mon Sep 17 00:00:00 2001 From: zwhite <33009111+zawh4159@users.noreply.github.com> Date: Mon, 27 Jul 2026 13:55:20 -0600 Subject: [PATCH 09/12] Revise granular model unit test documentation Updated the documentation for granular model unit tests, including changes to test descriptions and YAML file examples. --- doc/src/Developer_unittest.rst | 270 ++++++++++++++------------------- 1 file changed, 111 insertions(+), 159 deletions(-) diff --git a/doc/src/Developer_unittest.rst b/doc/src/Developer_unittest.rst index a8e10b5b220..7d507813b34 100644 --- a/doc/src/Developer_unittest.rst +++ b/doc/src/Developer_unittest.rst @@ -1004,61 +1004,54 @@ testers. Tests for granular (DEM) models ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - + .. versionadded:: 4Jul2026 - + The ``unittest/granular`` folder contains a YAML-driven test suite for -discrete element method (DEM) / granular models, built in the same +discrete element method (DEM) / granular contact models, built in the same spirit as the force-style tests above but specialized for time-resolved -trajectories of small granular systems. These tests are only enabled if -the :ref:`GRANULAR package` is enabled. - -Currently, there are 11 test programs. This set of unit tests is still a -work-in-progress and the tests have not yet been thoroughly vetted. Tests -may be added, updated, or removed. The first six test programs, -``test_dem_01`` through ``test_dem_06``, reproduce the test surface of the -MFiX-DEM verification studies of :ref:`Garg et al. ` (the -individual cases are also described in the `MFiX-DEM manual -`_). -``test_dem_07`` through ``test_dem_11`` add coverage of benchmark cases -from the granular literature: rolling resistance, cohesion, and -two-particle collisions follow the software-agnostic DEM benchmark of -:ref:`Mohajeri et al. `, and the bulk angle of repose -and multi-sphere clump cases follow the round-robin study of -:ref:`Saomoto et al. `. The particle-impact-level cases --- oblique wall impact (``test_dem_05``), two-sphere and spinning-sphere -collisions (``test_dem_09``) and the elastic Hertzian normal impact -(``test_dem_11``) -- follow the benchmark of :ref:`Chung and Ooi -`. The test programs are: - +trajectories of small, analytically tractable granular systems. These tests +are only enabled if the :ref:`GRANULAR package` is enabled. + +There are 8 test programs, ``test_dem_01`` through ``test_dem_08``, covering +particle-impact-level benchmarks: two-sphere and sphere-wall collisions, +oblique and spinning-sphere impacts, rolling and slipping contact, and +cohesive pull-off. These follow the software-agnostic DEM benchmark of +:ref:`Mohajeri et al. ` (rolling resistance and cohesion) +and the particle-impact benchmark of :ref:`Chung and Ooi ` +(normal, oblique, and spinning-sphere collisions). The test programs are: + .. list-table:: :header-rows: 1 * - Program - Scenario + - Analytic model * - ``test_dem_01`` - - a freely falling particle bouncing off a wall + - two-sphere head-on normal collision + - ``collision_restitution`` * - ``test_dem_02`` - - a particle bouncing repeatedly (convergence to the hard-sphere limit) + - two-sphere elastic Hertzian normal impact (peak force) + - ``hertz_normal_impact`` * - ``test_dem_03`` - - two stacked particles in continuous compression between two walls + - sphere-wall elastic Hertzian normal impact (peak force) + - ``hertz_normal_impact`` * - ``test_dem_04`` - - a sphere sliding then rolling without slipping on a rough surface + - oblique impact on a wall (gross-sliding friction) + - ``oblique_impact`` * - ``test_dem_05`` - - an oblique collision of a sphere (and a superellipsoid) with a wall + - sphere sliding then rolling without slipping + - ``slip_cessation`` * - ``test_dem_06`` - - a single particle settling to its terminal velocity under fluid drag + - spinning sphere impact (rebound with friction) + - ``spin_impact`` * - ``test_dem_07`` - - a spinning sphere damped to rest by rolling resistance (``rolling sds``) + - rolling-resistance decay + - ``rolling_decay`` * - ``test_dem_08`` - - cohesive/adhesive contact: the DMT and JKR pull-off force - * - ``test_dem_09`` - - two-sphere head-on, oblique (shear), and spinning-sphere collisions - * - ``test_dem_10`` - - bulk behavior: a settling pile, the angle of repose, and a rigid clump - * - ``test_dem_11`` - - elastic Hertzian normal impact (peak contact mechanics) - + - cohesive DMT pull-off force + - ``pulloff_dmt`` + Every test program shares the same driver logic, implemented in ``unittest/granular/test_dem_common.cpp`` and compiled into the ``granular_tests`` support library; each ``test_dem_0N.cpp`` only contains @@ -1066,64 +1059,76 @@ the two GoogleTest fixtures (``newton_on`` and ``newton_off``). As with the force-style tests, the reference systems are defined by YAML files in the ``unittest/granular/tests`` folder and registered as CTest cases by their file name (``dem0N-*.yaml`` becomes test ``DEM0N:*``); adding or removing a -YAML file requires re-running CMake. - +YAML file requires re-running CMake. A given driver may cover several +variants of one scenario -- across contact models +(``hooke``, ``hooke/history``, ``hertz``, ``hertz/material``, ``mindlin``, +``mindlin/rescale``), dimensionality, or unit systems -- since it simply +runs every ``dem0N-*.yaml`` file that matches its number. + Unlike the force-style tests, the entire system is built *from the YAML file* rather than from a fixed input template. A YAML file provides an optional ``variables`` block (emitted as :doc:`index variables ` so they can be substituted as ``${name}`` anywhere in the command strings), ``pre_commands`` that create the geometry, ``pair_style`` / ``pair_coeff`` that select the contact model, and ``post_commands`` that add the -integrator, gravity, walls and drag. The trajectory is then advanced in a -sequence of ``run_segments`` and, after each segment, the per-atom -positions, velocities, torques, angular velocities (spheres) and angular -momenta (ellipsoids/superellipsoids) are compared against the recorded -reference. A minimal example (``dem01-hooke-3d-si.yaml``) looks like: - +integrator and any walls. The trajectory is then advanced in a sequence of +``run_segments`` and, after each segment, the per-atom positions, +velocities, torques, and angular velocities are compared against the +recorded reference. A minimal example (``dem03-hertz-wall-3d-si.yaml``) +looks like: + .. code-block:: yaml - + --- - lammps_version: 30 Mar 2026 - tags: granular + lammps_version: 4 Jul 2026 + tags: granular, generated + date_generated: Tue Jul 21 21:40:51 2026 epsilon: 1e-10 - prerequisites: ! | + prerequisites: | atom sphere - pair gran/hooke - variables: ! | - knorm 1.0e4 - gnorm 10.0 - diam 0.2 - dens 2600.0 - grav 9.81 - z0 0.5 - pre_commands: ! | + pair granular + pre_commands: | units si dimension 3 boundary f f f atom_style sphere - region box block -0.5 0.5 -0.5 0.5 0.0 1.0 units box + region box block -0.05 0.05 -0.05 0.05 -0.05 0.1 units box create_box 1 box create_atoms 1 single 0.0 0.0 ${z0} units box set group all diameter ${diam} density ${dens} + velocity all set 0.0 0.0 -${vin} comm_modify vel yes - timestep 0.001 - pair_style: gran/hooke ${knorm} NULL ${gnorm} NULL 0.0 0 - pair_coeff: ! | - * * - post_commands: ! | - fix grav all gravity ${grav} vector 0.0 0.0 -1.0 + neighbor 0.001 bin + neigh_modify delay 0 + timestep ${dt} + post_commands: | fix integr all nve/sphere - fix zwall all wall/gran hooke ${knorm} NULL ${gnorm} NULL 0.0 0 zplane 0.0 NULL - run_segments: ! | - 250 150 300 + fix zwall all wall/gran granular hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution zplane 0.0 NULL + natoms: 1 + variables: | + diam 0.005 + dens 7000.0 + kn 7.11111e+10 + en 1.0 + vin 3.9 + vrela 3.9 + mred_factor 1.0 + radius 0.0025 + dt 1.0e-8 + z0 0.002550 + pair_style: granular + pair_coeff: | + * * hertz ${kn} ${en} tangential linear_nohistory 0.0 0.0 damping coeff_restitution + run_segments: |- + 1300 838 900 analytic_enable: yes - analytic_model: freefall - analytic_tol: 1.0e-9 - analytic_segment: 0 - # run_pos / run_vel / run_torque / run_omega / run_angmom blocks follow - + analytic_model: hertz_normal_impact + analytic_tol: 0.01 + analytic_segment: 1 + # run_pos / run_vel / run_torque / run_omega blocks follow + The following table describes the available keys: - + .. list-table:: :header-rows: 1 @@ -1138,15 +1143,15 @@ The following table describes the available keys: * - pre_commands - commands that build the geometry (units, box, atoms, ``set``, timestep) * - pair_style / pair_coeff - - the particle-particle contact model + - the particle-particle (or particle-wall) contact model * - post_commands - - fixes added after the geometry (integrator, gravity, walls, drag) + - fixes added after the geometry (integrator, walls) * - run_segments - whitespace-separated list of run lengths; state is captured after each * - run_pos, run_vel - reference positions and velocities, as ``segment tag x y z`` rows - * - run_torque, run_omega, run_angmom - - reference torque / angular velocity / angular momentum (when applicable) + * - run_torque, run_omega + - reference torque / angular velocity (when applicable) * - analytic_enable - ``yes`` to also assert a closed-form (analytic) model * - analytic_model @@ -1155,96 +1160,57 @@ The following table describes the available keys: - relative tolerance for the analytic assertion (looser than ``epsilon``) * - analytic_segment - run segment at which the analytic model is checked (``-1`` means the last) - * - analytic_only - - ``yes`` to record/check *only* the analytic model and skip the per-atom - regression (for chaotic bulk tests; see below) - + The per-atom reference blocks use a ``segment tag x y z`` row format, so a single block holds the data for all run segments and the row order does not matter. Because granular/atomic systems do not build an atom map by default, the reference generator iterates over local atoms by tag rather than calling ``Atom::map()``. - + Each test runs as a pure regression check (the recorded data is reproduced to within ``epsilon``) under both the ``newton on`` and ``newton off`` -fixtures, which are expected to give identical results. In addition, a -test may opt in to an *analytic* check that compares a derived quantity -against a closed-form solution implemented in +fixtures, which are expected to give identical results. In addition, every +test opts in to an *analytic* check that compares a derived quantity against +a closed-form solution implemented in ``unittest/granular/test_analytic_models.cpp``. The analytic tolerance is deliberately loose, because the soft-sphere DEM result only approaches the idealized (hard-sphere or instantaneous-contact) solution. The models currently implemented are: - + .. list-table:: :header-rows: 1 * - Model: - Checks: - * - freefall - - ballistic motion before contact: :math:`z = z_0 - g t^2/2`, :math:`v_z = -g t` - * - bounce_height - - hard-sphere apex after the k-th bounce :math:`h_k = r + e^{2k}(h_0 - r)` - * - stack_energy - - conservation of total mechanical energy for an elastic two-particle stack - * - slip_cessation - - rolling-without-slipping limit :math:`u = 5 u_0/7`, :math:`\omega = u/r` - * - oblique_impact - - gross-sliding rebound :math:`v_x' = v_x - \mu(1+e)v_z`, :math:`\omega_y = \tfrac{5}{2}\mu(1+e)v_z/r` - * - terminal_velocity_linear - - Stokes drag terminal velocity :math:`v_{term} = m g/\gamma` - * - terminal_velocity_schiller_naumann - - Schiller-Naumann terminal velocity from :math:`m g = \tfrac{1}{2} C_d \rho_g \pi r^2 v^2` - * - rolling_decay - - linear spin-down under rolling resistance: :math:`\omega = \omega_0 - \tfrac{5 \mu_r g}{2 r} t` - * - pulloff_dmt - - DMT pull-off force at contact :math:`|F| = 4 \pi \gamma R_{\mathrm{eff}}` * - collision_restitution - two-sphere momentum conservation and restitution :math:`e = -(v_1'-v_2')/(v_1-v_2)` - * - angle\_of\_repose - - measured heap slope :math:`\arctan(z_{\max}/r_{\max})` lies within a ``[lo, hi]`` band * - hertz\_normal\_impact - Hertzian peak energy balance :math:`\tfrac{1}{2}\mu_{red} V_{rela}^2 = \tfrac{2}{5} P_{max}\alpha_{max}` + * - oblique_impact + - gross-sliding rebound :math:`v_x' = v_x - \mu(1+e)v_z`, :math:`\omega_y = \tfrac{5}{2}\mu(1+e)v_z/r` + * - slip_cessation + - rolling-without-slipping limit :math:`u = 5 u_0/7`, :math:`\omega = u/r` * - spin\_impact - gross-sliding rebound of a spinning sphere: :math:`v_x' = \mu(1+e)v_n`, :math:`\omega_y' = \omega_0 - \tfrac{5}{2}\mu(1+e)v_n/r` - * - spin\_no\_friction - - counter-spinning spheres with zero contact slip keep their spin and gain no tangential velocity - -``test_dem_06`` exercises both :doc:`fix viscous ` (linear -Stokes drag) and the :doc:`fix viscous/nonlinear ` -style that was added together with these tests for the Schiller-Naumann -drag correlation. - -Analytic-only (chaotic bulk) -"""""""""""""""""""""""""""" - -Most tests are bit-for-bit -regressions that reproduce identically under ``newton on`` and ``newton -off``. A few bulk scenarios -- notably the angle-of-repose pile in -``test_dem_10`` -- are *chaotic*: a long pour-and-settle trajectory amplifies -the round-off differences between summation orders, so the per-atom state is -not reproducible across ``newton`` settings or platforms even though the bulk -observable (the heap angle) is robust. Such a YAML sets ``analytic_only: -yes``. The generator then records no per-atom reference blocks, and the -driver checks only the analytic model. ``test_dem_10`` pairs this with a -short, deterministic ``dem10-settle-*`` regression (a small lattice block -relaxing into contact) and a deterministic ``dem10-clump-*`` case (a -:doc:`fix rigid/small ` tetrahedral clump bouncing on a granular -wall) so the bit-for-bit code path is still covered. - + * - rolling_decay + - linear spin-down under rolling resistance: :math:`\omega = \omega_0 - \tfrac{5 \mu_r g}{2 r} t` + * - pulloff_dmt + - DMT pull-off force at contact :math:`|F| = 4 \pi \gamma R_{\mathrm{eff}}` + Adding a new reference (YAML) file """""""""""""""""""""""""""""""""" - + Copy an existing ``dem0N-*.yaml`` for a similar scenario, adjust the ``variables``, ``pre_commands``, ``pair_style``/``pair_coeff`` and ``post_commands`` for the new model, and give it a new name matching the ``dem0N-*.yaml`` pattern of the test program it belongs to. Leave out the reference data blocks initially, then (re)generate them in place with: - + .. code-block:: bash - + TEST_ARGS=-u ctest -R DEM0N:myvariant - + or by running the driver directly (``test_dem_0N dem0N-myvariant.yaml -u``). Do **not** write the generated file to a sibling ``dem0N-*.yaml`` name (for example with the ``-g newfile.yaml`` option pointing into the ``tests`` @@ -1253,10 +1219,10 @@ extra, stale test. After adding the file, re-run CMake so the new test is registered, then verify it with ``ctest -V -R DEM0N:myvariant`` (the ``-s`` option of the driver reports per-quantity error statistics, which helps when choosing ``epsilon`` and the analytic tolerance). - + Adding a new test program """"""""""""""""""""""""" - + Create ``test_dem_0N.cpp`` as a thin copy of an existing one (only the GoogleTest suite name changes), add an ``add_executable``/``register_dem_tests`` pair to @@ -1267,33 +1233,19 @@ that reads its parameters from the ``variables`` block (and reads masses, radii, etc. from the live LAMMPS instance to avoid depending on derived quantities) and assert it with ``EXPECT_LE`` on the relative error. - + References """""""""" - -.. _dem_Garg2012: - -**(Garg et al., 2012)** R. Garg, J. Galvin, T. Li, and S. Pannala, -Open-source MFIX-DEM software for gas-solids flows: Part I -- Verification -studies, Powder Technology, 220, 122-137 (2012), -https://doi.org/10.1016/j.powtec.2011.09.019 - + .. _dem_Mohajeri2024: - + **(Mohajeri et al., 2024)** M. J. Mohajeri, C. Coetzee, and D. L. Schott, A software-agnostic benchmark for DEM simulation of cohesive and non-cohesive materials, Powder Technology, 447, 120136 (2024), https://doi.org/10.1016/j.powtec.2024.120136 - -.. _dem_Saomoto2023: - -**(Saomoto et al., 2023)** H. Saomoto, N. Kikkawa, S. Moriguchi, Y. Nakata, -et al., Round robin test on angle of repose: DEM simulation results -collected from 16 groups around the world, Soils and Foundations, 63, -101272 (2023), https://doi.org/10.1016/j.sandf.2023.101272 - + .. _dem_Chung2011: - + **(Chung and Ooi, 2011)** Y. C. Chung and J. Y. Ooi, Benchmark tests for verifying discrete element modelling codes at particle impact level, Granular Matter, 13, 643-656 (2011), From f9720ce2d176d615495d1d6c31349b1f71be1c73 Mon Sep 17 00:00:00 2001 From: jtclemm Date: Tue, 28 Jul 2026 10:55:24 -0600 Subject: [PATCH 10/12] Fixing test tags/coeff, clarifying python audit script, removing outdated references to tests --- unittest/granular/README.md | 5 +- unittest/granular/dem_audit.py | 25 ++- unittest/granular/test_analytic_models.cpp | 173 +----------------- unittest/granular/test_dem_common.cpp | 2 +- .../tests/dem01-hertz-twosphere-3d-si.yaml | 2 +- .../granular/tests/dem01-hooke-2d-lj.yaml | 2 +- .../tests/dem01-hooke-twosphere-3d-si.yaml | 2 +- .../dem01-hookehistory-twosphere-3d-si.yaml | 2 +- .../tests/dem02-hertz-twosphere-3d-si.yaml | 2 +- .../dem02-hertzmaterial-twosphere-3d-si.yaml | 2 +- .../tests/dem03-hertz-wall-3d-si.yaml | 2 +- .../tests/dem03-hertzmaterial-wall-3d-si.yaml | 2 +- .../tests/dem04-hertz-oblique-3d-si.yaml | 2 +- .../dem04-hookehistory-oblique-3d-si.yaml | 2 +- .../tests/dem04-mindlin-oblique-3d-si.yaml | 2 +- .../dem04-mindlinrescale-oblique-3d-si.yaml | 2 +- .../tests/dem04-oblique-grazing-3d-si.yaml | 2 +- .../tests/dem05-hookehistory-slip-3d-si.yaml | 2 +- .../tests/dem05-mindlin-slip-3d-si.yaml | 2 +- .../granular/tests/dem05-slip-mu02-3d-si.yaml | 2 +- .../tests/dem06-hookehistory-spin-3d-si.yaml | 2 +- .../tests/dem06-mindlin-spin-heavy-3d-si.yaml | 2 +- .../granular/tests/dem06-spin-wall-3d-si.yaml | 2 +- .../tests/dem07-hertz-rolling-3d-si.yaml | 6 +- .../tests/dem07-hooke-rolling-3d-si.yaml | 2 +- .../tests/dem07-rolling-mu02-3d-si.yaml | 2 +- .../tests/dem08-dmt-twosphere-3d-si.yaml | 2 +- .../granular/tests/dem08-dmt-wall-3d-si.yaml | 2 +- 28 files changed, 51 insertions(+), 206 deletions(-) diff --git a/unittest/granular/README.md b/unittest/granular/README.md index 911f79f520c..765dde70db2 100644 --- a/unittest/granular/README.md +++ b/unittest/granular/README.md @@ -18,6 +18,9 @@ stored per-atom reference trajectory. - `test_config_reader.{cpp,h}`, `test_main.{cpp,h}`, `test_config.h` — YAML parsing and the test-runner entry point. - `tests/` — the YAML test definitions, `demNN---.yaml`. +- `dem_audit.py` — separate diagonistic script that compares results from all + test drivers to analytic expectations. Intended for authoring/debugging + new/existing tests. Not connected to CMake or CTest. ## Tests @@ -57,7 +60,7 @@ Run a single test file: Or run the whole suite through ctest from the build directory: - ctest -R Dem --output-on-failure + ctest -R DEM --output-on-failure Options: diff --git a/unittest/granular/dem_audit.py b/unittest/granular/dem_audit.py index 671cba269e1..1d0c1c0d5eb 100644 --- a/unittest/granular/dem_audit.py +++ b/unittest/granular/dem_audit.py @@ -4,6 +4,7 @@ # the harness), the harness's own expected, the simulated value, and relative errors. # Forces the harness to print by running a temp copy with a tiny tolerance. Leaves # nothing behind. Run from the build dir: python3 dem_audit.py [tests_dir] + import sys, os, re, math, glob, subprocess, tempfile PI = math.pi HERE = os.path.dirname(os.path.abspath(__file__)) @@ -55,8 +56,10 @@ def dim_of(txt): return int(m.group(1)) if m else 3 def massof(v, txt): d, dm = v.get('dens', 0.0), v.get('diam', 0.0) - return dens_disc(d, dm) if dim_of(txt) == 2 else d * (PI / 6.0) * dm ** 3 -def dens_disc(d, dm): return d * (PI / 4.0) * dm ** 2 + if (dim_of(txt) == 2): + return d * (PI / 4.0) * dm ** 2 + else: + return d * (PI / 6.0) * dm ** 3 def seg_time(txt): try: @@ -124,7 +127,9 @@ def formulas(model, v, txt): def harness_numbers(yaml_path, driver): txt = open(yaml_path).read() t = tempfile.NamedTemporaryFile('w', suffix='.yaml', dir='/tmp', delete=False) - t.write(re.sub(r'analytic_tol:\s*\S+', 'analytic_tol: 1e-14', txt)); t.close() + + # use negative tolerance such that it is never satisfied to force comparison output + t.write(re.sub(r'analytic_tol:\s*\S+', 'analytic_tol: -1', txt)); t.close() try: r = subprocess.run([driver, t.name, '-v'], capture_output=True, text=True, cwd=BUILD, timeout=300) out = r.stdout + r.stderr @@ -145,6 +150,8 @@ def main(): print(f"tests: {TESTS}\nbuild: {BUILD}") files = sorted(glob.glob(os.path.join(TESTS, "dem*.yaml"))) skipped = [] + ntest = 0 + nfail = 0 for y in files: txt = open(y).read() mm = re.search(r'^analytic_model:\s*(\S+)', txt, re.M) @@ -170,15 +177,21 @@ def main(): label = k.split(None, 1)[-1] if ' ' in k else k print(f" {label:<26} {eq}") if E is not None: - line = f" harness expected = {E:.6g} simulated got = {G:.6g} relerr = {rel(G, E):.2e}" + line = f" harness expected = {E:.6g} simulation = {G:.6g} relerr = {rel(G, E):.2e}" if mine is not None: - line += (" (formula = harness expected OK)" if rel(mine, E) <= 1e-4 - else f" [!! formula here = {mine:.6g} DISAGREES with harness]") + ntest += 1 + if rel(mine, E) <= 1e-4: + line += " (formula = harness, OK)" + else: + line += f" (formula = {mine:.6g} != harness), fail!!" + nfail += 1 print(line) elif mine is not None: print(f" formula value = {mine:.6g} (harness value needs the driver)") if skipped: print("\nskipped (no analytic_model / not a demNN file):", ", ".join(skipped)) + + print(f"Failed {nfail} out of {ntest} tests\n") print() if __name__ == "__main__": diff --git a/unittest/granular/test_analytic_models.cpp b/unittest/granular/test_analytic_models.cpp index 7f4fba5bb3e..42bcbbb9063 100644 --- a/unittest/granular/test_analytic_models.cpp +++ b/unittest/granular/test_analytic_models.cpp @@ -79,72 +79,7 @@ void check_analytic_model(const TestConfig &cfg, LAMMPS *lmp, int segment) const auto vars = as_doubles(cfg); const double t = (double) lmp->update->ntimestep * lmp->update->dt; - if (cfg.analytic_model == "freefall") { - // ballistic motion of atom 1 before any contact: z = z0 - g t^2/2, vz = -g t. - // velocity-Verlet integrates constant acceleration exactly, so this is tight. - const double g = var_or(vars, "grav", 0.0); - const double z0 = var_or(vars, "z0", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "freefall: atom with tag 1 not found"; - expect_rel(z0 - 0.5 * g * t * t, lmp->atom->x[i][2], cfg.analytic_tol, "freefall z"); - expect_rel(-g * t, lmp->atom->v[i][2], cfg.analytic_tol, "freefall vz"); - } else if (cfg.analytic_model == "bounce_height") { - // hard-sphere limit: the apex (center) height after the k-th bounce is - // h_k = r + e^(2k) (h0 - r). - // Evaluated at a free-flight segment via energy conservation, - // apex = z + vz^2/(2g), so the segment need not end exactly at the apex. - // The match is approximate (soft-sphere, finite stiffness) -> loose tol. - const double g = var_or(vars, "grav", 0.0); - const double e = var_or(vars, "restitution", var_or(vars, "en", 1.0)); - const double r = var_or(vars, "radius", 0.0); - const double h0 = var_or(vars, "h0", 0.0); - const double k = var_or(vars, "bounce_k", 1.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "bounce_height: atom with tag 1 not found"; - const double z = lmp->atom->x[i][2]; - const double vz = lmp->atom->v[i][2]; - const double apex = z + vz * vz / (2.0 * g); - expect_rel(r + std::pow(e, 2.0 * k) * (h0 - r), apex, cfg.analytic_tol, "bounce_height apex"); - } else if (cfg.analytic_model == "stack_energy") { - // Two particles (tags 1 lower, 2 upper) stacked between a floor (ylo) - // and ceiling (yhi). For the elastic (e=1) linear-spring case the total - // mechanical energy KE + gravitational PE + contact spring PE is - // conserved; compare it to the initial value (particles start at rest). - // Masses and radii are read from the live simulation so the comparison - // does not depend on reproducing LAMMPS' mass formula. - const double g = var_or(vars, "grav", 0.0); - const double kn = var_or(vars, "knorm", 0.0); - const double ylo = var_or(vars, "ylo", 0.0); - const double yhi = var_or(vars, "yhi", 0.0); - const double y1_0 = var_or(vars, "y1", 0.0); - const double y2_0 = var_or(vars, "y2", 0.0); - const int i1 = find_local(lmp, 1); - const int i2 = find_local(lmp, 2); - ASSERT_GE(i1, 0) << "stack_energy: atom with tag 1 not found"; - ASSERT_GE(i2, 0) << "stack_energy: atom with tag 2 not found"; - const double m1 = lmp->atom->rmass[i1]; - const double m2 = lmp->atom->rmass[i2]; - const double r1 = lmp->atom->radius[i1]; - const double r2 = lmp->atom->radius[i2]; - - // linear-spring contact PE from the three possible overlaps: - // lower particle vs floor, the pair, upper particle vs ceiling - auto spring_pe = [&](double ya, double yb) { - const double df = std::max(0.0, r1 - (ya - ylo)); - const double dc = std::max(0.0, (yb + r2) - yhi); - const double dpp = std::max(0.0, (r1 + r2) - (yb - ya)); - return 0.5 * kn * (df * df + dc * dc + dpp * dpp); - }; - - const double e0 = (m1 * g * y1_0 + m2 * g * y2_0) + spring_pe(y1_0, y2_0); - const double ya = lmp->atom->x[i1][1]; - const double yb = lmp->atom->x[i2][1]; - const double va = lmp->atom->v[i1][1]; - const double vb = lmp->atom->v[i2][1]; - const double ec = 0.5 * m1 * va * va + 0.5 * m2 * vb * vb + (m1 * g * ya + m2 * g * yb) + - spring_pe(ya, yb); - expect_rel(e0, ec, cfg.analytic_tol, "stack_energy total energy"); - } else if (cfg.analytic_model == "slip_cessation") { + if (cfg.analytic_model == "slip_cessation") { // sphere (tag 1) launched along +x with no spin on a rough floor (normal +z): // kinetic friction decelerates u and spins it up about +y until the no-slip // condition u = omega_y r is reached. Thereafter u = 5 u0/7 and omega_y = u/r. @@ -174,69 +109,6 @@ void check_analytic_model(const TestConfig &cfg, LAMMPS *lmp, int segment) expect_rel(en * vz_in, lmp->atom->v[i][2], cfg.analytic_tol, "oblique_impact vz_out"); expect_rel(vx_in - dvt, lmp->atom->v[i][0], cfg.analytic_tol, "oblique_impact vx_out"); expect_rel(2.5 * dvt / r, lmp->atom->omega[i][1], cfg.analytic_tol, "oblique_impact omega_y"); - } else if (cfg.analytic_model == "terminal_velocity_linear") { - // particle (tag 1) falling under gravity g with linear (Stokes) drag - // F = -gamma v reaches terminal speed v_term = m g / gamma. - const double g = var_or(vars, "grav", 0.0); - const double gamma = var_or(vars, "gamma", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "terminal_velocity_linear: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - expect_rel(m * g / gamma, -lmp->atom->v[i][2], cfg.analytic_tol, - "terminal_velocity_linear"); - } else if (cfg.analytic_model == "terminal_velocity_schiller_naumann") { - // particle (tag 1) falling under gravity g with Schiller-Naumann drag - // (quiescent gas): terminal speed solves m g = 1/2 Cd rho_g pi r^2 v^2. - const double g = var_or(vars, "grav", 0.0); - const double rho = var_or(vars, "rho_gas", 0.0); - const double mu = var_or(vars, "mu_gas", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "terminal_velocity_schiller_naumann: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - const double r = lmp->atom->radius[i]; - const double area = MathConst::MY_PI * r * r; - const double mg = m * g; - auto drag = [&](double v) { - if (v <= 0.0) return 0.0; - const double re = rho * v * (2.0 * r) / mu; - const double cd = (24.0 / re) * (1.0 + 0.15 * std::pow(re, 0.687)); - return 0.5 * cd * rho * area * v * v; - }; - // bracket then bisect for the terminal speed (drag is monotone in v) - double vlo = 0.0, vhi = 1.0; - int guard = 0; - while ((drag(vhi) < mg) && (guard++ < 200)) vhi *= 2.0; - for (int it = 0; it < 100; ++it) { - const double vm = 0.5 * (vlo + vhi); - if (drag(vm) < mg) - vlo = vm; - else - vhi = vm; - } - expect_rel(0.5 * (vlo + vhi), -lmp->atom->v[i][2], cfg.analytic_tol, - "terminal_velocity_schiller_naumann"); - } else if (cfg.analytic_model == "energy_dissipation") { - // For a frictional collision with no external forces (no gravity) the - // total mechanical (translational + rotational) kinetic energy of the - // sphere (tag 1) must not increase. This guards against the - // grazing-impact energy-injection bug of the classic tangential model. - // Initial state: velocity (vx_in, 0, -vz_in) with no spin; sphere moment - // of inertia I = (2/5) m r^2. analytic_tol is the (small) fractional - // excess over the initial energy that is tolerated. - const double vx_in = var_or(vars, "vx_in", 0.0); - const double vz_in = var_or(vars, "vz_in", 0.0); - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "energy_dissipation: atom with tag 1 not found"; - const double m = lmp->atom->rmass[i]; - const double r = lmp->atom->radius[i]; - const double *v = lmp->atom->v[i]; - const double *w = lmp->atom->omega[i]; - const double e_init = 0.5 * m * (vx_in * vx_in + vz_in * vz_in); - const double ke_tr = 0.5 * m * (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); - const double ke_rot = 0.5 * (0.4 * m * r * r) * (w[0] * w[0] + w[1] * w[1] + w[2] * w[2]); - const double e_final = ke_tr + ke_rot; - EXPECT_LE(e_final, e_init * (1.0 + cfg.analytic_tol)) - << "energy_dissipation: final energy " << e_final << " exceeds initial " << e_init; } else if (cfg.analytic_model == "rolling_decay") { // sphere (tag 1) spinning about +y on a flat wall, damped only by the // rolling-resistance torque M = mu_r R N (N = m g). In the gross-rolling @@ -281,35 +153,6 @@ void check_analytic_model(const TestConfig &cfg, LAMMPS *lmp, int segment) EXPECT_LE(std::fabs(m1 * v1 + m2 * v2), cfg.analytic_tol * (m1 + m2) * vin) << "collision_restitution: total x-momentum not conserved"; expect_rel(en, -(v1 - v2) / (2.0 * vin), cfg.analytic_tol, "collision_restitution e"); - } else if (cfg.analytic_model == "angle_of_repose") { - // coarse, statistical estimate of a settled heap's angle of repose: - // atan(H / R), where H is the peak height above the floor and R is the - // largest horizontal distance from the (horizontal) centroid. Asserted - // to lie within a band [aor_lo, aor_hi] degrees (variables). - const double floor = var_or(vars, "floor", 0.0); - const double lo = var_or(vars, "aor_lo", 0.0); - const double hi = var_or(vars, "aor_hi", 90.0); - double **x = lmp->atom->x; - const int nlocal = lmp->atom->nlocal; - ASSERT_GT(nlocal, 0) << "angle_of_repose: no atoms"; - double xc = 0.0, yc = 0.0, zmax = -1.0e300; - for (int k = 0; k < nlocal; ++k) { - xc += x[k][0]; - yc += x[k][1]; - if (x[k][2] > zmax) zmax = x[k][2]; - } - xc /= nlocal; - yc /= nlocal; - double rmax = 0.0; - for (int k = 0; k < nlocal; ++k) { - const double dx = x[k][0] - xc, dy = x[k][1] - yc; - const double rr = std::sqrt(dx * dx + dy * dy); - if (rr > rmax) rmax = rr; - } - const double angle = - (rmax > 0.0) ? std::atan((zmax - floor) / rmax) * 180.0 / MathConst::MY_PI : 90.0; - EXPECT_GE(angle, lo) << "angle_of_repose " << angle << " deg is below the band"; - EXPECT_LE(angle, hi) << "angle_of_repose " << angle << " deg is above the band"; } else if (cfg.analytic_model == "hertz_normal_impact") { // Elastic Hertzian normal impact at peak compression (Chung & Ooi 2011, // Tests 1 & 2). This segment must be timed to land at peak compression, @@ -375,20 +218,6 @@ void check_analytic_model(const TestConfig &cfg, LAMMPS *lmp, int segment) expect_rel(dvt, lmp->atom->v[i][0], cfg.analytic_tol, "spin_impact vx_out"); expect_rel(w0 - 2.5 * dvt / r, lmp->atom->omega[i][1], cfg.analytic_tol, "spin_impact omega_y"); - } else if (cfg.analytic_model == "spin_no_friction") { - // Two identical spheres (tags 1,2) collide head-on along z while spinning - // about y with equal and opposite omega0, arranged so the relative - // tangential velocity at the contact point is zero (Chung & Ooi 2011, - // Test 7). No tangential force should be generated: each sphere's spin - // is preserved and it gains no tangential (x,y) velocity. This guards - // against a model spuriously creating friction from spin alone. - const double w0 = var_or(vars, "omega0", 0.0); - const double tol = cfg.analytic_tol; - const int i = find_local(lmp, 1); - ASSERT_GE(i, 0) << "spin_no_friction: atom with tag 1 not found"; - expect_rel(w0, lmp->atom->omega[i][1], tol, "spin_no_friction omega_y preserved"); - EXPECT_LE(std::fabs(lmp->atom->v[i][0]), tol) << "spin_no_friction: spurious vx"; - EXPECT_LE(std::fabs(lmp->atom->v[i][1]), tol) << "spin_no_friction: spurious vy"; } else { ADD_FAILURE() << "unknown analytic_model: '" << cfg.analytic_model << "'"; } diff --git a/unittest/granular/test_dem_common.cpp b/unittest/granular/test_dem_common.cpp index 000d8a3ca14..db954a77c07 100644 --- a/unittest/granular/test_dem_common.cpp +++ b/unittest/granular/test_dem_common.cpp @@ -12,7 +12,7 @@ ------------------------------------------------------------------------- */ // Shared implementation for the DEM verification test drivers -// (test_dem_01 ... test_dem_11). Every driver builds its system entirely +// (test_dem_01, test_dem_02, ...). Every driver builds its system entirely // from the YAML file: a 'variables' block provides ${var} substitution, // 'pre_commands' create the geometry, 'pair_style'/'pair_coeff' set the // contact model, and 'post_commands' add the integrator, gravity and walls. diff --git a/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml b/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml index cd053a35d4a..9029229be2a 100644 --- a/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml +++ b/unittest/granular/tests/dem01-hertz-twosphere-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:49 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem01-hooke-2d-lj.yaml b/unittest/granular/tests/dem01-hooke-2d-lj.yaml index 57dff280938..9bc3f60cd4c 100644 --- a/unittest/granular/tests/dem01-hooke-2d-lj.yaml +++ b/unittest/granular/tests/dem01-hooke-2d-lj.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:50 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml b/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml index f18ae58ec33..57c2041792b 100644 --- a/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml +++ b/unittest/granular/tests/dem01-hooke-twosphere-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:50 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml b/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml index d83120342b3..6900a6efd5c 100644 --- a/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml +++ b/unittest/granular/tests/dem01-hookehistory-twosphere-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:50 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml b/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml index 8a4a4804f19..b584c91ba91 100644 --- a/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml +++ b/unittest/granular/tests/dem02-hertz-twosphere-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:51 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml b/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml index b044c236c5c..7a5d55b4492 100644 --- a/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml +++ b/unittest/granular/tests/dem02-hertzmaterial-twosphere-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:51 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml b/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml index 194a32f6a62..8ab4e654a5c 100644 --- a/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml +++ b/unittest/granular/tests/dem03-hertz-wall-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:51 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml b/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml index 240818e03fd..2b1e846a637 100644 --- a/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml +++ b/unittest/granular/tests/dem03-hertzmaterial-wall-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:52 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml b/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml index 29d4195dcde..5b07ff13041 100644 --- a/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml +++ b/unittest/granular/tests/dem04-hertz-oblique-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:52 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml b/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml index 23693ab9894..6ab54dcfe7f 100644 --- a/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml +++ b/unittest/granular/tests/dem04-hookehistory-oblique-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:52 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml b/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml index 985e0d65ff6..631bb0828b9 100644 --- a/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml +++ b/unittest/granular/tests/dem04-mindlin-oblique-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:52 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml b/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml index de21e551f90..a7e1c006996 100644 --- a/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml +++ b/unittest/granular/tests/dem04-mindlinrescale-oblique-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:53 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml b/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml index b91c8d5b0c5..b818942ecd2 100644 --- a/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml +++ b/unittest/granular/tests/dem04-oblique-grazing-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:53 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml b/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml index 0a8773a10d2..9d4f2bbc7cf 100644 --- a/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml +++ b/unittest/granular/tests/dem05-hookehistory-slip-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:53 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml b/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml index 9adb519e396..864e4de3731 100644 --- a/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml +++ b/unittest/granular/tests/dem05-mindlin-slip-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:54 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml b/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml index 0fbee36f8e3..ccecc980cfb 100644 --- a/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml +++ b/unittest/granular/tests/dem05-slip-mu02-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:54 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml b/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml index 9132fddf7e5..d1cc7b040de 100644 --- a/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml +++ b/unittest/granular/tests/dem06-hookehistory-spin-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:55 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml b/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml index 786551c3fa7..1db58e84583 100644 --- a/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml +++ b/unittest/granular/tests/dem06-mindlin-spin-heavy-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:55 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem06-spin-wall-3d-si.yaml b/unittest/granular/tests/dem06-spin-wall-3d-si.yaml index 2ae6df091d9..336074ed3cc 100644 --- a/unittest/granular/tests/dem06-spin-wall-3d-si.yaml +++ b/unittest/granular/tests/dem06-spin-wall-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:55 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml b/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml index 924e530a0ce..923a1ee9060 100644 --- a/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml +++ b/unittest/granular/tests/dem07-hertz-rolling-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:56 2026 epsilon: 1e-10 skip_tests: @@ -24,7 +24,7 @@ pre_commands: | post_commands: | fix grav all gravity 1.0 vector 0.0 0.0 -1.0 fix integr all nve/sphere - fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution zplane 0.0 NULL + fix zwall all wall/gran granular hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} zplane 0.0 NULL input_file: natoms: 1 variables: | @@ -42,7 +42,7 @@ variables: | z0 0.0024393 pair_style: granular pair_coeff: | - * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} damping coeff_restitution + * * hertz/material ${emod} ${en} ${poisson} damping coeff_restitution tangential linear_nohistory 0.0 0.0 rolling sds ${kr} 0.0 ${mur} run_segments: |- 3000 4000 3000 analytic_enable: yes diff --git a/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml b/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml index 93f6febb825..70c8d8237ed 100644 --- a/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml +++ b/unittest/granular/tests/dem07-hooke-rolling-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:56 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml b/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml index 7c7f3095c02..6ffca422067 100644 --- a/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml +++ b/unittest/granular/tests/dem07-rolling-mu02-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:56 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml b/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml index 06cd297ce81..37ba4e4ff44 100644 --- a/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml +++ b/unittest/granular/tests/dem08-dmt-twosphere-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:57 2026 epsilon: 1e-10 skip_tests: diff --git a/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml b/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml index 4d2d1eb968b..45fbbc63841 100644 --- a/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml +++ b/unittest/granular/tests/dem08-dmt-wall-3d-si.yaml @@ -1,6 +1,6 @@ --- lammps_version: 4 Jul 2026 -tags: granular,, generated +tags: granular date_generated: Tue Jul 21 21:40:57 2026 epsilon: 1e-10 skip_tests: From ecdf0b44c55f9a5f4106d9d437a2fd21eb3ce545 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 28 Jul 2026 14:54:31 -0400 Subject: [PATCH 11/12] whitespace and formatting fixes --- doc/src/Developer_unittest.rst | 161 +++++++++++++++++---------------- unittest/granular/README.md | 2 +- unittest/granular/dem_audit.py | 2 +- 3 files changed, 83 insertions(+), 82 deletions(-) mode change 100644 => 100755 unittest/granular/dem_audit.py diff --git a/doc/src/Developer_unittest.rst b/doc/src/Developer_unittest.rst index 7d507813b34..18c8c1fbcb7 100644 --- a/doc/src/Developer_unittest.rst +++ b/doc/src/Developer_unittest.rst @@ -36,13 +36,12 @@ The following sections describe how the tests are implemented and executed in those categories with increasing complexity of tests and implementation. - Tests for utility functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^ These tests are driven by programs in the ``unittest/utils`` folder -and most closely resemble conventional unit tests. There is one test -program for each namespace or group of classes or file. The naming +and most closely resemble conventional unit tests. There is one test +program for each namespace or group of classes or file. The naming convention for the sources and executables is that they start with with ``test_``. The following sources and groups of tests are currently available: @@ -80,7 +79,6 @@ available: - FFT3DKokkos - Tests for KOKKOS FFT3d wrapper (CPU and GPU back ends) - To add tests either an existing source file needs to be modified or a new source file needs to be added to the distribution and enabled for testing. To add a new file suitable CMake script code needs to be added @@ -99,10 +97,10 @@ GoogleMock library of GoogleTest. The third line registers the executable as a test program to be run from ``ctest`` under the name ``Tokenizer``. The test executable itself will execute multiple individual tests -through the GoogleTest framework. In this case each test consists of +through the GoogleTest framework. In this case each test consists of creating a tokenizer class instance with a given string and explicit or default separator choice, and then executing member functions of the -class and comparing their results with expected values. A few examples: +class and comparing their results with expected values. A few examples: .. code-block:: c++ @@ -127,7 +125,7 @@ class and comparing their results with expected values. A few examples: } Each of these TEST functions will become an individual -test run by the test program. When using the ``ctest`` +test run by the test program. When using the ``ctest`` command as a front end to run the tests, their output will be suppressed and only a summary printed, but adding the '-V' option will then produce output from the tests @@ -164,7 +162,7 @@ etc.). **Building and Running FFT Tests:** The FFT tests are automatically enabled when ``ENABLE_TESTING=ON`` and -``PKG_KSPACE=ON`` are set during CMake configuration. For KOKKOS FFT tests, +``PKG_KSPACE=ON`` are set during CMake configuration. For KOKKOS FFT tests, ``PKG_KOKKOS=ON`` is also required. Run only FFT tests using the ``ctest`` command of the CMake software: @@ -273,7 +271,7 @@ understand why tests fail unexpectedly. The specifics of so-called "death tests", i.e. conditions where LAMMPS should fail and throw an exception, are implemented in the -``TEST_FAILURE()`` macro. These tests operate by capturing the screen +``TEST_FAILURE()`` macro. These tests operate by capturing the screen output when executing the failing command and then comparing that with a provided regular expression string pattern. Example: @@ -396,7 +394,7 @@ angle styles, kspace styles and certain fix styles. Those are tests driven by some test executables build from sources in the ``unittest/force-styles`` folder and use LAMMPS input template and data files as well as input files in YAML format from the -``unittest/force-styles/tests`` folder. The YAML file names have to +``unittest/force-styles/tests`` folder. The YAML file names have to follow some naming conventions so they get associated with the test programs and categorized and listed with canonical names in the list of tests as displayed by ``ctest -N``. If you add a new YAML file, @@ -650,12 +648,12 @@ documentation for how to install ``check-jsonschema``. The test program will read all this data from the YAML file and then create a LAMMPS instance, apply the settings/commands from the YAML file as needed and then issue a "run 0" command, write out a restart file, a -data file and a coeff file. The actual test will then compare computed +data file and a coeff file. The actual test will then compare computed energies, stresses, and forces with the reference data, issue a "run 4" command and compare to the second set of reference data. This will be run with both the newton_pair setting enabled and disabled and is expected to generate the same results (allowing for some numerical -noise). Then it will restart from the previously generated restart and +noise). Then it will restart from the previously generated restart and compare with the reference and also start from the data file. A final check will use multi-cutoff r-RESPA (if supported by the pair style) at a 1:1 split and compare to the Verlet results. These sets of tests are @@ -839,7 +837,7 @@ The ``test_pair_style`` tester is used with 4 categories of test inputs: correspondingly labeled with "ManybodyPairStyle:\*" - kspace styles. The YAML files match the pattern "kspace-\*.yaml" and the tests are - correspondingly labeled with "KSpaceStyle:\*". In these cases a compatible + correspondingly labeled with "KSpaceStyle:\*". In these cases a compatible pair style is defined, but the computation of the pair style contributions is disabled. @@ -888,7 +886,7 @@ files then should be compared manually, if they agree well enough within the lim of those two approximations. The ``test_pair_style`` and equivalent programs have special command-line options -to update the YAML files. Running a command like +to update the YAML files. Running a command like .. code-block:: bash @@ -923,10 +921,10 @@ of the potentials and differences in compilers. These kinds of tests can be very sensitive to compiler optimization and thus the expectation is that they pass with compiler optimization turned - off. When compiler optimization is enabled, there may be some failures, but + off. When compiler optimization is enabled, there may be some failures, but one has to carefully check whether those are acceptable due to the enhanced numerical noise from reordering floating-point math operations or due to - the compiler mis-compiling the code. That is not always obvious. + the compiler mis-compiling the code. That is not always obvious. Tests for minimizer styles """""""""""""""""""""""""" @@ -1001,26 +999,27 @@ supported by this driver. Reference files are created and updated with the same ``-g`` and ``-u`` command-line options as for the other testers. - Tests for granular (DEM) models ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. versionadded:: 4Jul2026 - + +.. versionadded:: TBD + The ``unittest/granular`` folder contains a YAML-driven test suite for -discrete element method (DEM) / granular contact models, built in the same -spirit as the force-style tests above but specialized for time-resolved -trajectories of small, analytically tractable granular systems. These tests -are only enabled if the :ref:`GRANULAR package` is enabled. - -There are 8 test programs, ``test_dem_01`` through ``test_dem_08``, covering -particle-impact-level benchmarks: two-sphere and sphere-wall collisions, -oblique and spinning-sphere impacts, rolling and slipping contact, and -cohesive pull-off. These follow the software-agnostic DEM benchmark of -:ref:`Mohajeri et al. ` (rolling resistance and cohesion) -and the particle-impact benchmark of :ref:`Chung and Ooi ` -(normal, oblique, and spinning-sphere collisions). The test programs are: - +discrete element method (DEM) / granular contact models, built in the +same spirit as the force-style tests above but specialized for +time-resolved trajectories of small, analytically tractable granular +systems. These tests are only enabled if the :ref:`GRANULAR +package` is enabled. + +There are 8 test programs, ``test_dem_01`` through ``test_dem_08``, +covering particle-impact-level benchmarks: two-sphere and sphere-wall +collisions, oblique and spinning-sphere impacts, rolling and slipping +contact, and cohesive pull-off. These follow the software-agnostic DEM +benchmark of :ref:`Mohajeri et al. ` (rolling +resistance and cohesion) and the particle-impact benchmark of +:ref:`Chung and Ooi ` (normal, oblique, and +spinning-sphere collisions). The test programs are: + .. list-table:: :header-rows: 1 @@ -1051,20 +1050,21 @@ and the particle-impact benchmark of :ref:`Chung and Ooi ` * - ``test_dem_08`` - cohesive DMT pull-off force - ``pulloff_dmt`` - + Every test program shares the same driver logic, implemented in ``unittest/granular/test_dem_common.cpp`` and compiled into the -``granular_tests`` support library; each ``test_dem_0N.cpp`` only contains -the two GoogleTest fixtures (``newton_on`` and ``newton_off``). As with the -force-style tests, the reference systems are defined by YAML files in the -``unittest/granular/tests`` folder and registered as CTest cases by their -file name (``dem0N-*.yaml`` becomes test ``DEM0N:*``); adding or removing a -YAML file requires re-running CMake. A given driver may cover several -variants of one scenario -- across contact models -(``hooke``, ``hooke/history``, ``hertz``, ``hertz/material``, ``mindlin``, -``mindlin/rescale``), dimensionality, or unit systems -- since it simply -runs every ``dem0N-*.yaml`` file that matches its number. - +``granular_tests`` support library; each ``test_dem_0N.cpp`` only +contains the two GoogleTest fixtures (``newton_on`` and ``newton_off``). +As with the force-style tests, the reference systems are defined by YAML +files in the ``unittest/granular/tests`` folder and registered as CTest +cases by their file name (``dem0N-\*.yaml`` becomes test ``DEM0N:\*``); +adding or removing a YAML file requires re-running CMake. A given +driver may cover several variants of one scenario -- across contact +models (``hooke``, ``hooke/history``, ``hertz``, ``hertz/material``, +``mindlin``, ``mindlin/rescale``), dimensionality, or unit systems -- +since it simply runs every ``dem0N-\*.yaml`` file that matches its +number. + Unlike the force-style tests, the entire system is built *from the YAML file* rather than from a fixed input template. A YAML file provides an optional ``variables`` block (emitted as :doc:`index variables ` @@ -1076,12 +1076,12 @@ integrator and any walls. The trajectory is then advanced in a sequence of velocities, torques, and angular velocities are compared against the recorded reference. A minimal example (``dem03-hertz-wall-3d-si.yaml``) looks like: - + .. code-block:: yaml - + --- lammps_version: 4 Jul 2026 - tags: granular, generated + tags: granular date_generated: Tue Jul 21 21:40:51 2026 epsilon: 1e-10 prerequisites: | @@ -1126,9 +1126,9 @@ looks like: analytic_tol: 0.01 analytic_segment: 1 # run_pos / run_vel / run_torque / run_omega blocks follow - + The following table describes the available keys: - + .. list-table:: :header-rows: 1 @@ -1160,13 +1160,13 @@ The following table describes the available keys: - relative tolerance for the analytic assertion (looser than ``epsilon``) * - analytic_segment - run segment at which the analytic model is checked (``-1`` means the last) - + The per-atom reference blocks use a ``segment tag x y z`` row format, so a single block holds the data for all run segments and the row order does not matter. Because granular/atomic systems do not build an atom map by default, the reference generator iterates over local atoms by tag rather than calling ``Atom::map()``. - + Each test runs as a pure regression check (the recorded data is reproduced to within ``epsilon``) under both the ``newton on`` and ``newton off`` fixtures, which are expected to give identical results. In addition, every @@ -1176,7 +1176,7 @@ a closed-form solution implemented in deliberately loose, because the soft-sphere DEM result only approaches the idealized (hard-sphere or instantaneous-contact) solution. The models currently implemented are: - + .. list-table:: :header-rows: 1 @@ -1196,56 +1196,57 @@ currently implemented are: - linear spin-down under rolling resistance: :math:`\omega = \omega_0 - \tfrac{5 \mu_r g}{2 r} t` * - pulloff_dmt - DMT pull-off force at contact :math:`|F| = 4 \pi \gamma R_{\mathrm{eff}}` - + Adding a new reference (YAML) file """""""""""""""""""""""""""""""""" - -Copy an existing ``dem0N-*.yaml`` -for a similar scenario, adjust the ``variables``, ``pre_commands``, -``pair_style``/``pair_coeff`` and ``post_commands`` for the new model, and -give it a new name matching the ``dem0N-*.yaml`` pattern of the test program -it belongs to. Leave out the reference data blocks initially, then -(re)generate them in place with: - + +Copy an existing ``dem0N-\*.yaml`` for a similar scenario, adjust the +``variables``, ``pre_commands``, ``pair_style``/``pair_coeff`` and +``post_commands`` for the new model, and give it a new name matching the +``dem0N-\*.yaml`` pattern of the test program it belongs to. Leave out +the reference data blocks initially, then (re)generate them in place +with: + .. code-block:: bash - + TEST_ARGS=-u ctest -R DEM0N:myvariant - -or by running the driver directly (``test_dem_0N dem0N-myvariant.yaml -u``). -Do **not** write the generated file to a sibling ``dem0N-*.yaml`` name (for -example with the ``-g newfile.yaml`` option pointing into the ``tests`` -folder), because the ``CONFIGURE_DEPENDS`` glob would then register it as an -extra, stale test. After adding the file, re-run CMake so the new test is -registered, then verify it with ``ctest -V -R DEM0N:myvariant`` (the ``-s`` -option of the driver reports per-quantity error statistics, which helps when -choosing ``epsilon`` and the analytic tolerance). - + +or by running the driver directly (``test_dem_0N dem0N-myvariant.yaml +-u``). Do **not** write the generated file to a sibling +``dem0N-\*.yaml`` name (for example with the ``-g newfile.yaml`` option +pointing into the ``tests`` folder), because the ``CONFIGURE_DEPENDS`` +glob would then register it as an extra, stale test. After adding the +file, re-run CMake so the new test is registered, then verify it with +``ctest -V -R DEM0N:myvariant`` (the ``-s`` option of the driver reports +per-quantity error statistics, which helps when choosing ``epsilon`` and +the analytic tolerance). + Adding a new test program """"""""""""""""""""""""" - + Create ``test_dem_0N.cpp`` as a thin copy of an existing one (only the GoogleTest suite name changes), add an ``add_executable``/``register_dem_tests`` pair to ``unittest/granular/CMakeLists.txt``, and add the corresponding -``dem0N-*.yaml`` reference files. If the new scenario needs a +``dem0N-\*.yaml`` reference files. If the new scenario needs a closed-form check, add a named model to ``test_analytic_models.cpp`` that reads its parameters from the ``variables`` block (and reads masses, radii, etc. from the live LAMMPS instance to avoid depending on derived quantities) and assert it with ``EXPECT_LE`` on the relative error. - + References """""""""" - + .. _dem_Mohajeri2024: - + **(Mohajeri et al., 2024)** M. J. Mohajeri, C. Coetzee, and D. L. Schott, A software-agnostic benchmark for DEM simulation of cohesive and non-cohesive materials, Powder Technology, 447, 120136 (2024), https://doi.org/10.1016/j.powtec.2024.120136 - + .. _dem_Chung2011: - + **(Chung and Ooi, 2011)** Y. C. Chung and J. Y. Ooi, Benchmark tests for verifying discrete element modelling codes at particle impact level, Granular Matter, 13, 643-656 (2011), diff --git a/unittest/granular/README.md b/unittest/granular/README.md index 765dde70db2..eda885f3dd9 100644 --- a/unittest/granular/README.md +++ b/unittest/granular/README.md @@ -92,4 +92,4 @@ After editing a test, regenerate its reference trajectory and confirm it passes: ./test_dem_0N tests/.yaml -s The reference is recorded with `newton on`; tests are checked under both -`newton on` and `newton off`. \ No newline at end of file +`newton on` and `newton off`. diff --git a/unittest/granular/dem_audit.py b/unittest/granular/dem_audit.py old mode 100644 new mode 100755 index 1d0c1c0d5eb..62d6078e2dc --- a/unittest/granular/dem_audit.py +++ b/unittest/granular/dem_audit.py @@ -195,4 +195,4 @@ def main(): print() if __name__ == "__main__": - main() \ No newline at end of file + main() From d2f9bea93205b1f2e41a4163814aa956f1b3d11a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 28 Jul 2026 14:55:18 -0400 Subject: [PATCH 12/12] don't override the tempfile dir for portability --- unittest/granular/dem_audit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/granular/dem_audit.py b/unittest/granular/dem_audit.py index 62d6078e2dc..41fa1d1f39e 100755 --- a/unittest/granular/dem_audit.py +++ b/unittest/granular/dem_audit.py @@ -126,7 +126,7 @@ def formulas(model, v, txt): def harness_numbers(yaml_path, driver): txt = open(yaml_path).read() - t = tempfile.NamedTemporaryFile('w', suffix='.yaml', dir='/tmp', delete=False) + t = tempfile.NamedTemporaryFile('w', suffix='.yaml', delete=False) # use negative tolerance such that it is never satisfied to force comparison output t.write(re.sub(r'analytic_tol:\s*\S+', 'analytic_tol: -1', txt)); t.close()