diff --git a/examples/PACKAGES/metatomic/in.kokkos.pair_metatomic b/examples/PACKAGES/metatomic/in.kokkos.pair_metatomic index 3b4be5bd662..c779bfabd9e 100644 --- a/examples/PACKAGES/metatomic/in.kokkos.pair_metatomic +++ b/examples/PACKAGES/metatomic/in.kokkos.pair_metatomic @@ -20,6 +20,10 @@ velocity all create 123 42 pair_style metatomic/kk nickel-lj.pt pair_coeff * * 28 +# For dense systems with large cutoffs (e.g. PET-MAD, ~5.5 A interaction range), +# pair_style metatomic will auto-adjust binsize, one, and page. To override: +# neigh_modify one 100000 page 1000000 binsize 5.5 + # pair_style hybrid/overlay/kk metatomic_1/kk nickel-lj.pt metatomic_2/kk nickel-lj.pt # pair_coeff * * metatomic_1/kk 28 # pair_coeff * * metatomic_2/kk 28 diff --git a/src/KOKKOS/nbin_kokkos.cpp b/src/KOKKOS/nbin_kokkos.cpp index 29ed21ca5bc..ebc29a6df22 100644 --- a/src/KOKKOS/nbin_kokkos.cpp +++ b/src/KOKKOS/nbin_kokkos.cpp @@ -17,6 +17,7 @@ #include "atom_kokkos.h" #include "atom_masks.h" #include "comm.h" +#include "error.h" #include "kokkos.h" #include "memory_kokkos.h" #include "update.h" @@ -63,6 +64,11 @@ NBinKokkos::NBinKokkos(LAMMPS *lmp) : NBinStandard(lmp) { template void NBinKokkos::bin_atoms_setup(int nall) { + if (mbins <= 0) + error->one(FLERR, "Kokkos neighbor list produced zero bins; " + "add 'neigh_modify binsize ' with a value smaller than " + "the shortest box dimension (e.g. half the pair cutoff)"); + if (mbins > (int)k_bins.view_device().extent(0)) { MemoryKokkos::realloc_kokkos(k_bins,"Neighbor::d_bins",mbins,atoms_per_bin); bins = k_bins.view(); diff --git a/src/KOKKOS/npair_kokkos.cpp b/src/KOKKOS/npair_kokkos.cpp index dd7d18a9652..53659ebe11e 100644 --- a/src/KOKKOS/npair_kokkos.cpp +++ b/src/KOKKOS/npair_kokkos.cpp @@ -16,6 +16,7 @@ #include "atom_kokkos.h" #include "atom_masks.h" #include "domain_kokkos.h" +#include "error.h" #include "update.h" #include "neighbor_kokkos.h" #include "nbin_kokkos.h" @@ -234,6 +235,10 @@ void NPairKokkos::build(NeighList *list_) data.special_flag[2] = special_flag[2]; data.special_flag[3] = special_flag[3]; + if (atoms_per_bin <= 0) + error->one(FLERR, "Kokkos neighbor list bin size produced zero atoms_per_bin; " + "try increasing neigh_modify binsize"); + data.h_resize()=1; while (data.h_resize()) { data.h_new_maxneighs() = list->maxneighs; diff --git a/src/ML-METATOMIC/fix_metatomic.cpp b/src/ML-METATOMIC/fix_metatomic.cpp index 2f302fc153f..554889bf8ba 100644 --- a/src/ML-METATOMIC/fix_metatomic.cpp +++ b/src/ML-METATOMIC/fix_metatomic.cpp @@ -39,9 +39,11 @@ #include "neigh_list.h" #include "neigh_request.h" #include "comm.h" +#include "domain.h" #include #include +#include #include #include @@ -337,16 +339,34 @@ void FixMetatomic::init() { this->system_adaptor->add_nl_request(cutoff, options); } - // HACK: Explicitly set the binsize for the neighbor list if there is no - // pair_style that would set it instead. - // - // Otherwise, the default binsize of box[0] is used, which crashes kokkos - // for large-ish boxes (~40A), and slow down the simulation for non-kokkos. - if (strcmp(force->pair_style, "none") == 0) { + // Check that neighbor list parameters are sufficient for this cutoff. + // Dense systems with large cutoffs can overflow the default one/page + // and crash the Kokkos NL builder with SIGFPE. + if (!neighbor->binsizeflag) { + // Keep the existing binsize hack for fix metatomic neighbor->binsize_user = 0.5 * mta_data->max_cutoff; neighbor->binsizeflag = 1; } - // END HACK + + double volume = domain->xprd * domain->yprd * domain->zprd; + double density = (volume > 0) ? static_cast(atom->natoms) / volume : 0.0; + double cutoff_with_skin = mta_data->max_cutoff + neighbor->skin; + int est_neighbors = static_cast( + (4.0/3.0) * M_PI * pow(cutoff_with_skin, 3) * density * 2.0 + ); + if (est_neighbors > neighbor->oneatom) { + // Auto-adjust one/page to avoid SIGFPE in Kokkos NL builder + if (comm->me == 0) { + error->message(FLERR, + "Metatomic model cutoff ({:.4f}) with current density requires " + "~{} neighbors per atom; auto-adjusting neigh_modify one/page. " + "To set manually, use at least: neigh_modify one {} page {}", + mta_data->max_cutoff, est_neighbors, + est_neighbors, est_neighbors * 10); + } + neighbor->oneatom = est_neighbors; + neighbor->pgsize = est_neighbors * 10; + } } void FixMetatomic::pick_device(c10::Device& device, const char* requested) { diff --git a/src/ML-METATOMIC/pair_metatomic.cpp b/src/ML-METATOMIC/pair_metatomic.cpp index bd067026e86..83f99303090 100644 --- a/src/ML-METATOMIC/pair_metatomic.cpp +++ b/src/ML-METATOMIC/pair_metatomic.cpp @@ -38,6 +38,7 @@ #endif #include +#include #include #include @@ -559,6 +560,29 @@ void PairMetatomic::init_style() { auto request = neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST); request->set_cutoff(mta_data->max_cutoff); + // Check that neighbor list parameters are sufficient for this cutoff. + // Dense systems with large cutoffs can overflow the default one/page + // and crash the Kokkos NL builder with SIGFPE. + double volume = compute_volume(domain); + double density = (volume > 0) ? static_cast(atom->natoms) / volume : 0.0; + double cutoff_with_skin = mta_data->max_cutoff + neighbor->skin; + int est_neighbors = static_cast( + (4.0/3.0) * M_PI * pow(cutoff_with_skin, 3) * density * 2.0 + ); + if (est_neighbors > neighbor->oneatom) { + // Auto-adjust one/page to avoid SIGFPE in Kokkos NL builder + if (comm->me == 0) { + error->message(FLERR, + "Metatomic model cutoff ({:.4f}) with current density requires " + "~{} neighbors per atom; auto-adjusting neigh_modify one/page. " + "To set manually, use at least: neigh_modify one {} page {}", + mta_data->max_cutoff, est_neighbors, + est_neighbors, est_neighbors * 10); + } + neighbor->oneatom = est_neighbors; + neighbor->pgsize = est_neighbors * 10; + } + // Translate from the metatomic neighbor lists requests to LAMMPS neighbor // lists requests. auto requested_nl = mta_data->model->run_method("requested_neighbor_lists");