diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index c6cb09f325..fbe56e99a1 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -306,6 +306,7 @@ set(STANDARD_PACKAGES REACTION REAXFF REPLICA + RHEO RIGID SCAFACOS SHOCK @@ -410,6 +411,7 @@ pkg_depends(CG-DNA ASPHERE) pkg_depends(ELECTRODE KSPACE) pkg_depends(EXTRA-MOLECULE MOLECULE) pkg_depends(MESONT MOLECULE) +pkg_depends(RHEO BPM) # detect if we may enable OpenMP support by default set(BUILD_OMP_DEFAULT OFF) @@ -550,7 +552,7 @@ else() endif() foreach(PKG_WITH_INCL KSPACE PYTHON ML-IAP VORONOI COLVARS ML-HDNNP MDI MOLFILE NETCDF - PLUMED QMMM ML-QUIP SCAFACOS MACHDYN VTK KIM COMPRESS ML-PACE LEPTON) + PLUMED QMMM ML-QUIP SCAFACOS MACHDYN VTK KIM COMPRESS ML-PACE LEPTON RHEO) if(PKG_${PKG_WITH_INCL}) include(Packages/${PKG_WITH_INCL}) endif() diff --git a/cmake/Modules/Packages/RHEO.cmake b/cmake/Modules/Packages/RHEO.cmake new file mode 100644 index 0000000000..be8c22877b --- /dev/null +++ b/cmake/Modules/Packages/RHEO.cmake @@ -0,0 +1,2 @@ +find_package(GSL 2.7 REQUIRED) +target_link_libraries(lammps PRIVATE GSL::gsl) diff --git a/cmake/presets/all_off.cmake b/cmake/presets/all_off.cmake index 1ed5c0acd7..f2f5782480 100644 --- a/cmake/presets/all_off.cmake +++ b/cmake/presets/all_off.cmake @@ -82,6 +82,7 @@ set(ALL_PACKAGES REACTION REAXFF REPLICA + RHEO RIGID SCAFACOS SHOCK diff --git a/cmake/presets/all_on.cmake b/cmake/presets/all_on.cmake index c4345470e5..8dc4632138 100644 --- a/cmake/presets/all_on.cmake +++ b/cmake/presets/all_on.cmake @@ -84,6 +84,7 @@ set(ALL_PACKAGES REACTION REAXFF REPLICA + RHEO RIGID SCAFACOS SHOCK diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index f66238c3c9..4802c67420 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -59,6 +59,7 @@ This is the list of packages that may require additional steps. * :ref:`POEMS ` * :ref:`PYTHON ` * :ref:`QMMM ` + * :ref:`RHEO ` * :ref:`SCAFACOS ` * :ref:`VORONOI ` * :ref:`VTK ` @@ -1566,10 +1567,11 @@ LAMMPS build. .. tab:: CMake build When the ``-D PKG_PLUMED=yes`` flag is included in the cmake - command you must ensure that GSL is installed in locations that - are specified in your environment. There are then two additional - variables that control the manner in which PLUMED is obtained and - linked into LAMMPS. + command you must ensure that `the GNU Scientific Library (GSL) + ` is installed in locations + that are accessible in your environment. There are then two + additional variables that control the manner in which PLUMED is + obtained and linked into LAMMPS. .. code-block:: bash @@ -2040,6 +2042,36 @@ verified to work in February 2020 with Quantum Espresso versions 6.3 to ---------- +.. _rheo: + +RHEO package +------------ + +To build with this package you must have the `GNU Scientific Library +(GSL) ` installed in locations that +are accessible in your environment. The GSL library should be at least +version 2.7. + +.. tabs:: + + .. tab:: CMake build + + If CMake cannot find the GSL library or include files, you can set: + + .. code-block:: bash + + -D GSL_ROOT_DIR=path # path to root of GSL installation + + .. tab:: Traditional make + + LAMMPS will try to auto-detect the GSL compiler and linker flags + from the corresponding ``pkg-config`` file (``gsl.pc``), otherwise + you can edit the file ``lib/rheo/Makefile.lammps`` + to specify the paths and library names where indicated by comments. + This must be done **before** the package is installed. + +---------- + .. _scafacos: SCAFACOS package diff --git a/doc/src/Build_package.rst b/doc/src/Build_package.rst index 63ccac534d..b70a1ca4d1 100644 --- a/doc/src/Build_package.rst +++ b/doc/src/Build_package.rst @@ -62,6 +62,7 @@ packages: * :ref:`POEMS ` * :ref:`PYTHON ` * :ref:`QMMM ` + * :ref:`RHEO ` * :ref:`SCAFACOS ` * :ref:`VORONOI ` * :ref:`VTK ` diff --git a/doc/src/Commands_bond.rst b/doc/src/Commands_bond.rst index 73235cf3c6..eec6f7acf1 100644 --- a/doc/src/Commands_bond.rst +++ b/doc/src/Commands_bond.rst @@ -54,6 +54,7 @@ OPT. * :doc:`oxdna2/fene ` * :doc:`oxrna2/fene ` * :doc:`quartic (o) ` + * :doc:`rheo/shell ` * :doc:`special ` * :doc:`table (o) ` diff --git a/doc/src/Commands_compute.rst b/doc/src/Commands_compute.rst index 2e8f291c77..e5ec34fc22 100644 --- a/doc/src/Commands_compute.rst +++ b/doc/src/Commands_compute.rst @@ -126,6 +126,7 @@ KOKKOS, o = OPENMP, t = OPT. * :doc:`reduce ` * :doc:`reduce/chunk ` * :doc:`reduce/region ` + * :doc:`rheo/property/atom ` * :doc:`rigid/local ` * :doc:`saed ` * :doc:`slcsa/atom ` diff --git a/doc/src/Commands_fix.rst b/doc/src/Commands_fix.rst index a7648218fa..4350a98b31 100644 --- a/doc/src/Commands_fix.rst +++ b/doc/src/Commands_fix.rst @@ -28,6 +28,7 @@ OPT. * :doc:`adapt ` * :doc:`adapt/fep ` * :doc:`addforce ` + * :doc:`add/heat ` * :doc:`addtorque ` * :doc:`alchemy ` * :doc:`amoeba/bitorsion ` @@ -204,6 +205,11 @@ OPT. * :doc:`reaxff/species (k) ` * :doc:`recenter ` * :doc:`restrain ` + * :doc:`rheo ` + * :doc:`rheo/oxidation ` + * :doc:`rheo/pressure ` + * :doc:`rheo/thermal ` + * :doc:`rheo/viscosity ` * :doc:`rhok ` * :doc:`rigid (o) ` * :doc:`rigid/meso ` diff --git a/doc/src/Commands_pair.rst b/doc/src/Commands_pair.rst index c0747b83d4..a1b2a78fdb 100644 --- a/doc/src/Commands_pair.rst +++ b/doc/src/Commands_pair.rst @@ -264,6 +264,8 @@ OPT. * :doc:`rebo (io) ` * :doc:`rebomos (o) ` * :doc:`resquared (go) ` + * :doc:`rheo ` + * :doc:`rheo/solid ` * :doc:`saip/metal (t) ` * :doc:`sdpd/taitwater/isothermal ` * :doc:`smatb ` diff --git a/doc/src/Examples.rst b/doc/src/Examples.rst index c5da4a498b..3d2103fd6f 100644 --- a/doc/src/Examples.rst +++ b/doc/src/Examples.rst @@ -134,6 +134,8 @@ Lowercase directories +-------------+------------------------------------------------------------------+ | rerun | use of rerun and read_dump commands | +-------------+------------------------------------------------------------------+ +| rheo | RHEO simulations of fluid flows and phase transitions | ++-------------+------------------------------------------------------------------+ | rigid | rigid bodies modeled as independent or coupled | +-------------+------------------------------------------------------------------+ | shear | sideways shear applied to 2d solid, with and without a void | diff --git a/doc/src/Howto.rst b/doc/src/Howto.rst index 85c98bd6de..5a63e2b1c4 100644 --- a/doc/src/Howto.rst +++ b/doc/src/Howto.rst @@ -89,6 +89,7 @@ Packages howto Howto_drude2 Howto_peri Howto_manifold + Howto_rheo Howto_spins Tutorials howto diff --git a/doc/src/Howto_rheo.rst b/doc/src/Howto_rheo.rst new file mode 100644 index 0000000000..34c0f7b6a1 --- /dev/null +++ b/doc/src/Howto_rheo.rst @@ -0,0 +1,116 @@ +Reproducing hydrodynamics and elastic objects (RHEO) +==================================================== + +The RHEO package is a hybrid implementation of smoothed particle +hydrodynamics (SPH) for fluid flow, which can couple to the :doc:`BPM package +` to model solid elements. RHEO combines these methods to enable +mesh-free modeling of multi-phase material systems. Its SPH solver supports +many advanced options including reproducing kernels, particle shifting, free +surface identification, and solid surface reconstruction. To model fluid-solid +systems, the status of particles can dynamically change between a fluid and +solid state, e.g. during melting/solidification, which determines how they +interact and their physical behavior. The package is designed with modularity +in mind, so one can easily turn various features on/off, adjust physical +details of the system, or develop new capabilities. For instance, the numerics +associated with calculating gradients, reproducing kernels, etc. are separated +into distinctclasses to simplify the development of new integration schemes +which can call these calculations. Additional numerical details can be found in +:ref:`(Palermo) ` and +:ref:`(Clemmer) `. + +Note, if you simply want to run a traditional SPH simulation, the :ref:`SPH package +` package is likely better suited for your application. It has fewer advanced +features and therefore benefits from improved performance. The :ref:`MACHDYN +` package for solids may also be relevant for fluid-solid problems. + +---------- + +At the core of the package is :doc:`fix rheo ` which integrates +particle trajectories and controls many optional features (e.g. the use +of reproducing kernels). In conjunction to fix rheo, one must specify an +instance of :doc:`fix rheo/pressure ` and +:doc:`fix rheo/viscosity ` to define a pressure equation +of state and viscosity model, respectively. Optionally, one can model +a heat equation with :doc:`fix rheo/thermal `, which also +allows the user to specify equations for a particle's thermal conductivity, +specific heat, latent heat, and melting temperature. The ordering of these +fixes in an an input script matters. Fix rheo must be defined prior to all +other RHEO fixes. + +Typically, RHEO requires atom style rheo. In addition to typical atom +properties like positions and forces, particles store a local density, +viscosity, pressure, and status. If thermal evolution is modeled, one must +use atom style rheo/thermal which also includes a local energy, temperature, and +conductivity. Note that the temperature is always derived from the energy. +This implies the *temperature* attribute of :doc:`the set command ` does not +affect particles. Instead, one should use the *sph/e* attribute. + +The status variable uses bit-masking to track various properties of a particle +such as its current state of matter (fluid or solid) and its location relative +to a surface. Some of these properties (and others) can be accessed using +:doc:`compute rheo/property/atom `. The *status* +attribute in :doc:`the set command ` only allows control over the first bit +which sets the state of matter, 0 is fluid and 1 is solid. + +Fluid interactions, including pressure forces, viscous forces, and heat exchange, +are calculated using :doc:`pair rheo `. Unlike typical pair styles, +pair rheo ignores the :doc:`special bond ` settings. Instead, +it determines whether to calculate forces based on the status of particles: e.g., +hydrodynamic forces are only calculated if a fluid particle is involved. + +---------- + +To model elastic objects, there are currently two mechanisms in RHEO, one designed +for bulk solid bodies and the other for thin shells. Both mechanisms rely on +introducing bonded forces between particles and therefore require a hybrid of atom +style bond and rheo (or rheo/thermal). + +To create an elastic solid body, one has to (a) change the status of constituent +particles to solid (e.g. with the :doc:`set ` command), (b) create bpm +bonds between the particles (see the :doc:`bpm howto ` page for +more details), and (c) use :doc:`pair rheo/solid ` to +apply repulsive contact forces between distinct solid bodies. Akin to pair rheo, +pair rheo/solid considers a particles fluid/solid phase to determine whether to +apply forces. However, unlike pair rheo, pair rheo/solid does obey special bond +settings such that contact forces do not have to be calculated between two bonded +solid particles in the same elastic body. + +In systems with thermal evolution, fix rheo/thermal can optionally set a +melting/solidification temperature allowing particles to dynamically swap their +state between fluid and solid when the temperature exceeds or drops below the +critical temperature, respectively. Using the *react* option, one can specify a maximum +bond length and a bond type. Then, when solidifying, particles will search their +local neighbors and automatically create bonds with any neighboring solid particles +in range. For BPM bond styles, bonds will then use the immediate position of the two +particles to calculate a reference state. When melting, particles will delete any +bonds of the specified type when reverting to a fluid state. Special bonds are updated +as bonds are created/broken. + +The other option for elastic objects is an elastic shell that is nominally much +thinner than a particle diameter, e.g. a oxide skin which gradually forms over time +on the surface of a fluid. Currently, this is implemented using +:doc:`fix rheo/oxidation ` and bond style +:doc:`rheo/shell `. Essentially, fix rheo/oxidation creates candidate +bonds of a specified type between surface fluid particles within a specified distance. +a newly created rheo/shell bond will then start a timer. While the timer is counting +down, the bond will delete itself if particles move too far apart or move away from the +surface. However, if the timer reaches a user-defined threshold, then the bond will +activate and apply additional forces to the fluid particles. Bond style rheo/shell +then operates very similarly to a BPM bond style, storing a reference length and +breaking if stretched too far. Unlike the above method, this option does not remove +the underlying fluid interactions (although particle shifting is turned off) and does +not modify special bond settings of particles. + +While these two options are not expected to be appropriate for every system, +either framework can be modified to create more suitable models (e.g. by changing the +criteria for creating/deleting a bond or altering force calculations). + +---------- + +.. _howto_rheo_palermo: + +**(Palermo)** Palermo, Wolf, Clemmer, O'Connor, in preparation. + +.. _howto_rheo_clemmer: + +**(Clemmer)** Clemmer, Pierce, O'Connor, Nevins, Jones, Lechman, Tencer, Appl. Math. Model., 130, 310-326 (2024). diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index a62e7e41b3..b812ddd26a 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -8,12 +8,12 @@ info on how to download or build any extra library it requires. It also gives links to documentation, example scripts, and pictures/movies (if available) that illustrate use of the package. -The majority of packages can be included in a LAMMPS build with a -single setting (``-D PKG_=on`` for CMake) or command -(``make yes-`` for make). See the :doc:`Build package ` -page for more info. A few packages may require additional steps; -this is indicated in the descriptions below. The :doc:`Build extras ` -page gives those details. +The majority of packages can be included in a LAMMPS build with a single +setting (``-D PKG_=on`` for CMake) or command (``make yes-`` +for make). See the :doc:`Build package ` page for more +info. A few packages may require additional steps; this is indicated in +the descriptions below. The :doc:`Build extras ` page +gives those details. .. note:: @@ -103,6 +103,7 @@ page gives those details. * :ref:`QEQ ` * :ref:`QMMM ` * :ref:`QTB ` + * :ref:`RHEO ` * :ref:`REACTION ` * :ref:`REAXFF ` * :ref:`REPLICA ` @@ -2622,6 +2623,45 @@ another set. ---------- +.. _PKG-RHEO: + +RHEO package +------------ + +**Contents:** + +Pair styles, bond styles, fixes, and computes for reproducing +hydrodynamics and elastic objects. See the :doc:`Howto rheo +` page for an overview. + +**Install:** + +This package has :ref:`specific installation instructions ` on the :doc:`Build extras ` page. + +**Authors:** Joel T. Clemmer (Sandia National Labs), +Thomas C. O'Connor (Carnegie Mellon University) + +.. versionadded:: TBD + +**Supporting info:** + +* src/RHEO filenames -> commands +* :doc:`Howto_rheo ` +* :doc:`atom_style rheo ` +* :doc:`atom_style rheo/thermal ` +* :doc:`bond_style rheo/shell ` +* :doc:`compute rheo/property/atom ` +* :doc:`fix rheo ` +* :doc:`fix rheo/oxidation ` +* :doc:`fix rheo/pressure ` +* :doc:`fix rheo/thermal ` +* :doc:`fix rheo/viscosity ` +* :doc:`pair_style rheo ` +* :doc:`pair_style rheo/solid ` +* examples/rheo + +---------- + .. _PKG-RIGID: RIGID package diff --git a/doc/src/Packages_list.rst b/doc/src/Packages_list.rst index d1422c5f09..0b3cfc216e 100644 --- a/doc/src/Packages_list.rst +++ b/doc/src/Packages_list.rst @@ -413,6 +413,11 @@ whether an extra library is needed to build and use the package: - :doc:`fix qtb ` :doc:`fix qbmsst ` - qtb - no + * - :ref:`RHEO ` + - reproducing hydrodynamics and elastic objects + - :doc:`Howto rheo ` + - rheo + - no * - :ref:`REACTION ` - chemical reactions in classical MD - :doc:`fix bond/react ` diff --git a/doc/src/atom_style.rst b/doc/src/atom_style.rst index f11cdf54b9..2e6a6e1cbe 100644 --- a/doc/src/atom_style.rst +++ b/doc/src/atom_style.rst @@ -189,6 +189,14 @@ the Additional Information section below. - *atomic* + molecule, radius, rmass + "smd data" - :ref:`MACHDYN ` - Smooth Mach Dynamics models + * - *rheo* + - *atomic* + rho, status + - :ref:`RHEO ` + - solid and fluid RHEO particles + * - *rheo/thermal* + - *atomic* + rho, status, energy, temperature + - :ref:`RHEO ` + - RHEO particles with temperature * - *sph* - *atomic* + "sph data" - :ref:`SPH ` diff --git a/doc/src/bond_rheo_shell.rst b/doc/src/bond_rheo_shell.rst new file mode 100644 index 0000000000..f83219b9f3 --- /dev/null +++ b/doc/src/bond_rheo_shell.rst @@ -0,0 +1,188 @@ +.. index:: bond_style rheo/shell + +bond_style rheo/shell command +============================= + +Syntax +"""""" + +.. code-block:: LAMMPS + + bond_style rheo/shell keyword value attribute1 attribute2 ... + +* required keyword = *t/form* +* optional keyword = *store/local* + + .. parsed-literal:: + + *t/form* value = formation time for a bond (time units) + + *store/local* values = fix_ID N attributes ... + * fix_ID = ID of associated internal fix to store data + * N = prepare data for output every this many timesteps + * attributes = zero or more of the below attributes may be appended + + *id1, id2* = IDs of 2 atoms in the bond + *time* = the timestep the bond broke + *x, y, z* = the center of mass position of the 2 atoms when the bond broke (distance units) + *x/ref, y/ref, z/ref* = the initial center of mass position of the 2 atoms (distance units) + +Examples +"""""""" + +.. code-block:: LAMMPS + + bond_style rheo/shell t/form 10.0 + bond_coeff 1 1.0 0.05 0.1 + +Description +""""""""""" + +.. versionadded:: TBD + +The *rheo/shell* bond style is designed to work with +:doc:`fix rheo/oxidation ` which creates candidate +bonds between eligible surface or near-surface particles. When a bond +is first created, it computes no forces and starts a timer. Forces are +not computed until the timer reaches the specified bond formation time, +*t/form*, and the bond is enabled and applies forces. If the two particles +move outside of the maximum bond distance or move into the bulk before +the timer reaches *t/form*, the bond automatically deletes itself. This +deletion is not recorded as a broken bond in the optional *store/local* fix. + +Before bonds are enabled, they are still treated as regular bonds by +all other parts of LAMMPS. This means they are written to data files +and counted in computes such as :doc:`nbond/atom `. +To only count enabled bonds, use the *nbond/shell* attribute in +:doc:`compute rheo/property/atom `. + +When enabled, the bond then computes forces based on deviations from +the initial reference state of the two atoms much like a BPM style +bond (as further discussed in the :doc:`BPM howto page `). +The reference state is stored by each bond when it is first enabled. +Data is then preserved across run commands and is written to +:doc:`binary restart files ` such that restarting the system +will not reset the reference state of a bond or the timer. + +This bond style is based on a model described in +:ref:`(Clemmer) `. The force has a magnitude of + +.. math:: + + F = 2 k (r - r_0) + \frac{2 k}{r_0^2 \epsilon_c^2} (r - r_0)^3 + +where :math:`k` is a stiffness, :math:`r` is the current distance +and :math:`r_0` is the initial distance between the two particles, and +:math:`\epsilon_c` is maximum strain beyond which a bond breaks. This +is done by setting the bond type to 0 such that forces are no longer +computed. + +A damping force proportional to the difference in the normal velocity +of particles is also applied to bonded particles: + +.. math:: + + F_D = - \gamma w (\hat{r} \bullet \vec{v}) + +where :math:`\gamma` is the damping strength, :math:`\hat{r}` is the +displacement normal vector, and :math:`\vec{v}` is the velocity difference +between the two particles. + +The following coefficients must be defined for each bond type via the +:doc:`bond_coeff ` command as in the example above, or in +the data file or restart files read by the :doc:`read_data +` or :doc:`read_restart ` commands: + +* :math:`k` (force/distance units) +* :math:`\epsilon_c` (unit less) +* :math:`\gamma` (force/velocity units) + +Unlike other BPM-style bonds, this bond style does not update special +bond settings when bonds are created or deleted. This bond style also +does not enforce specific :doc:`special_bonds ` settings. +This behavior is purposeful such :doc:`RHEO pair ` forces +and heat flows are still calculated. + +If the *store/local* keyword is used, an internal fix will track bonds that +break during the simulation. Whenever a bond breaks, data is processed +and transferred to an internal fix labeled *fix_ID*. This allows the +local data to be accessed by other LAMMPS commands. Following this optional +keyword, a list of one or more attributes is specified. These include the +IDs of the two atoms in the bond. The other attributes for the two atoms +include the timestep during which the bond broke and the current/initial +center of mass position of the two atoms. + +Data is continuously accumulated over intervals of *N* +timesteps. At the end of each interval, all of the saved accumulated +data is deleted to make room for new data. Individual datum may +therefore persist anywhere between *1* to *N* timesteps depending on +when they are saved. This data can be accessed using the *fix_ID* and a +:doc:`dump local ` command. To ensure all data is output, +the dump frequency should correspond to the same interval of *N* +timesteps. A dump frequency of an integer multiple of *N* can be used +to regularly output a sample of the accumulated data. + +Note that when unbroken bonds are dumped to a file via the +:doc:`dump local ` command, bonds with type 0 (broken bonds) +are not included. +The :doc:`delete_bonds ` command can also be used to +query the status of broken bonds or permanently delete them, e.g.: + +.. code-block:: LAMMPS + + delete_bonds all stats + delete_bonds all bond 0 remove + +---------- + +Restart and other info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +This bond style writes the reference state of each bond to +:doc:`binary restart files `. Loading a restart +file will properly restore bonds. However, the reference state is NOT +written to data files. Therefore reading a data file will not +restore bonds and will cause their reference states to be redefined. + +If the *store/local* option is used, an internal fix will calculate +a local vector or local array depending on the number of input values. +The length of the vector or number of rows in the array is the number +of recorded, broken bonds. If a single input is specified, a local +vector is produced. If two or more inputs are specified, a local array +is produced where the number of columns = the number of inputs. The +vector or array can be accessed by any command that uses local values +from a compute as input. See the :doc:`Howto output ` page +for an overview of LAMMPS output options. + +The vector or array will be floating point values that correspond to +the specified attribute. + +The single() function of this bond style returns 0.0 for the energy +of a bonded interaction, since energy is not conserved in these +dissipative potentials. The single() function also calculates two +extra bond quantities, the initial distance :math:`r_0` and a time. +These extra quantities can be accessed by the +:doc:`compute bond/local ` command as *b1* and *b2*\ . + +Restrictions +"""""""""""" + +This bond style is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the :doc:`Build package +` page for more info. + +Related commands +"""""""""""""""" + +:doc:`bond_coeff `, :doc:`fix rheo/oxidation ` + +Default +""""""" + +NA + +---------- + +.. _rheo_clemmer: + +**(Clemmer)** Clemmer, Pierce, O'Connor, Nevins, Jones, Lechman, Tencer, Appl. Math. Model., 130, 310-326 (2024). diff --git a/doc/src/bond_style.rst b/doc/src/bond_style.rst index 95f463e695..da56fe7fbb 100644 --- a/doc/src/bond_style.rst +++ b/doc/src/bond_style.rst @@ -105,6 +105,7 @@ accelerated styles exist. * :doc:`oxdna2/fene ` - same as oxdna but used with different pair styles * :doc:`oxrna2/fene ` - modified FENE bond suitable for RNA modeling * :doc:`quartic ` - breakable quartic bond +* :doc:`rheo/shell ` - shell bond for oxidation modeling in RHEO * :doc:`special ` - enable special bond exclusions for 1-5 pairs and beyond * :doc:`table ` - tabulated by bond length diff --git a/doc/src/compute.rst b/doc/src/compute.rst index 05181b9e7e..0690ec57c3 100644 --- a/doc/src/compute.rst +++ b/doc/src/compute.rst @@ -290,6 +290,7 @@ The individual style names on the :doc:`Commands compute ` pag * :doc:`reduce ` - combine per-atom quantities into a single global value * :doc:`reduce/chunk ` - reduce per-atom quantities within each chunk * :doc:`reduce/region ` - same as compute reduce, within a region +* :doc:`rheo/property/atom ` - convert atom attributes in RHEO package to per-atom vectors/arrays * :doc:`rigid/local ` - extract rigid body attributes * :doc:`saed ` - electron diffraction intensity on a mesh of reciprocal lattice nodes * :doc:`slcsa/atom ` - perform Supervised Learning Crystal Structure Analysis (SL-CSA) diff --git a/doc/src/compute_nbond_atom.rst b/doc/src/compute_nbond_atom.rst index f438836534..274d958a10 100644 --- a/doc/src/compute_nbond_atom.rst +++ b/doc/src/compute_nbond_atom.rst @@ -8,10 +8,17 @@ Syntax .. code-block:: LAMMPS - compute ID group-ID nbond/atom + compute ID group-ID nbond/atom keyword value * ID, group-ID are documented in :doc:`compute ` command * nbond/atom = style name of this compute command +* zero or more keyword/value pairs may be appended +* keyword = *bond/type* + + .. parsed-literal:: + + *bond/type* value = *btype* + *btype* = bond type included in count Examples """""""" @@ -19,6 +26,7 @@ Examples .. code-block:: LAMMPS compute 1 all nbond/atom + compute 1 all nbond/atom bond/type 2 Description """"""""""" @@ -31,6 +39,9 @@ the :doc:`Howto broken bonds ` page for more information. The number of bonds will be zero for atoms not in the specified compute group. This compute does not depend on Newton bond settings. +If the keyword *bond/type* is specified, only bonds of *btype* are +counted. + Output info """"""""""" diff --git a/doc/src/compute_rheo_property_atom.rst b/doc/src/compute_rheo_property_atom.rst new file mode 100644 index 0000000000..f34b2225f5 --- /dev/null +++ b/doc/src/compute_rheo_property_atom.rst @@ -0,0 +1,143 @@ +.. index:: compute rheo/property/atom + +compute rheo/property/atom command +================================== + +Syntax +"""""" + +.. code-block:: LAMMPS + + compute ID group-ID rheo/property/atom input1 input2 ... + +* ID, group-ID are documented in :doc:`compute ` command +* rheo/property/atom = style name of this compute command +* input = one or more atom attributes + + .. parsed-literal:: + + possible attributes = phase, surface, surface/r, + surface/divr, surface/n/a, coordination, + shift/v/a, energy, temperature, heatflow, + conductivity, cv, viscosity, pressure, rho, + grad/v/ab, stress/v/ab, stress/t/ab, nbond/shell + + .. parsed-literal:: + + *phase* = atom phase state + *surface* = atom surface status + *surface/r* = atom distance from the surface + *surface/divr* = divergence of position at atom position + *surface/n/a* = a-component of surface normal vector + *coordination* = coordination number + *shift/v/a* = a-component of atom shifting velocity + *energy* = atom energy + *temperature* = atom temperature + *heatflow* = atom heat flow + *conductivity* = atom conductivity + *cv* = atom specific heat + *viscosity* = atom viscosity + *pressure* = atom pressure + *rho* = atom density + *grad/v/ab* = ab-component of atom velocity gradient tensor + *stress/v/ab* = ab-component of atom viscous stress tensor + *stress/t/ab* = ab-component of atom total stress tensor (pressure and viscous) + *nbond/shell* = number of oxide bonds + +Examples +"""""""" + +.. code-block:: LAMMPS + + compute 1 all rheo/property/atom phase surface/r surface/n/* pressure + compute 2 all rheo/property/atom shift/v/x grad/v/xx stress/v/* + +Description +""""""""""" + +.. versionadded:: TBD + +Define a computation that stores atom attributes specific to the RHEO +package for each atom in the group. This is useful so that the values +can be used by other :doc:`output commands ` that take +computes as inputs. See for example, the +:doc:`compute reduce `, +:doc:`fix ave/atom `, +:doc:`fix ave/histo `, +:doc:`fix ave/chunk `, and +:doc:`atom-style variable ` commands. + +For vector attributes, e.g. *shift/v/*:math:`\alpha`, one must specify +:math:`\alpha` as the *x*, *y*, or *z* component, e.g. *shift/v/x*. +Alternatively, a wild card \* will include all components, *x* and *y* in +2D or *x*, *y*, and *z* in 3D. + +For tensor attributes, e.g. *grad/v/*:math:`\alpha \beta`, one must specify +both :math:`\alpha` and :math:`\beta` as *x*, *y*, or *z*, e.g. *grad/v/xy*. +Alternatively, a wild card \* will include all components. In 2D, this +includes *xx*, *xy*, *yx*, and *yy*. In 3D, this includes *xx*, *xy*, *xz*, +*yx*, *yy*, *yz*, *zx*, *zy*, and *zz*. + +Many properties require their respective fixes, listed below in related +commands, be defined. For instance, the *viscosity* attribute is the +viscosity of a particle calculated by +:doc:`fix rheo/viscous `. The meaning of less obvious +properties is described below. + +The *phase* property indicates whether the particle is in a fluid state, +a value of 0, or a solid state, a value of 1. + +The *surface* property indicates the surface designation produced by +the *interface/reconstruct* option of :doc:`fix rheo `. Bulk +particles have a value of 0, surface particles have a value of 1, and +splash particles have a value of 2. The *surface/r* property is the +distance from the surface, up to the kernel cutoff length. Surface particles +have a value of 0. The *surface/n/*:math:`\alpha` properties are the +components of the surface normal vector. + +The *shift/v/*:math:`\alpha` properties are the components of the shifting +velocity produced by the *shift* option of :doc:`fix rheo `. + +The *nbond/shell* property is the number of shell bonds that have been +activated from :doc:`bond style rheo/shell `. + +The values are stored in a per-atom vector or array as discussed +below. Zeroes are stored for atoms not in the specified group or for +quantities that are not defined for a particular particle in the group + +Output info +""""""""""" + +This compute calculates a per-atom vector or per-atom array depending +on the number of input values. Generally, if a single input is specified, +a per-atom vector is produced. If two or more inputs are specified, a +per-atom array is produced where the number of columns = the number of +inputs. However, if a wild card \* is used for a vector or tensor, then +the number of inputs is considered to be incremented by the dimension or +the dimension squared, respectively. The vector or array can be accessed +by any command that uses per-atom values from a compute as input. See the +:doc:`Howto output ` page for an overview of LAMMPS output +options. + +The vector or array values will be in whatever :doc:`units ` the +corresponding attribute is in (e.g., density units for *rho*). + +Restrictions +"""""""""""" + none + +Related commands +"""""""""""""""" + +:doc:`dump custom `, :doc:`compute reduce `, +:doc:`fix ave/atom `, :doc:`fix ave/chunk `, +:doc:`fix rheo/viscosity `, +:doc:`fix rheo/pressure `, +:doc:`fix rheo/thermal `, +:doc:`fix rheo/oxdiation `, +:doc:`fix rheo ` + +Default +""""""" + +none diff --git a/doc/src/fix.rst b/doc/src/fix.rst index 4cd21353c7..4919c226fd 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -193,6 +193,7 @@ accelerated styles exist. * :doc:`adapt ` - change a simulation parameter over time * :doc:`adapt/fep ` - enhanced version of fix adapt * :doc:`addforce ` - add a force to each atom +* :doc:`add/heat ` - add a heat flux to each atom * :doc:`addtorque ` - add a torque to a group of atoms * :doc:`alchemy ` - perform an "alchemical transformation" between two partitions * :doc:`amoeba/bitorsion ` - torsion/torsion terms in AMOEBA force field @@ -369,6 +370,11 @@ accelerated styles exist. * :doc:`reaxff/species ` - write out ReaxFF molecule information * :doc:`recenter ` - constrain the center-of-mass position of a group of atoms * :doc:`restrain ` - constrain a bond, angle, dihedral +* :doc:`rheo ` - integrator for the RHEO package +* :doc:`rheo/thermal ` - thermal integrator for the RHEO package +* :doc:`rheo/oxidation ` - create oxidation bonds for the RHEO package +* :doc:`rheo/pressure ` - pressure calculation for the RHEO package +* :doc:`rheo/viscosity ` - viscosity calculation for the RHEO package * :doc:`rhok ` - add bias potential for long-range ordered systems * :doc:`rigid ` - constrain one or more clusters of atoms to move as a rigid body with NVE integration * :doc:`rigid/meso ` - constrain clusters of mesoscopic SPH/SDPD particles to move as a rigid body diff --git a/doc/src/fix_add_heat.rst b/doc/src/fix_add_heat.rst new file mode 100644 index 0000000000..5b67bd4e15 --- /dev/null +++ b/doc/src/fix_add_heat.rst @@ -0,0 +1,111 @@ +.. index:: fix add/heat + +fix add/heat command +==================== + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID add/heat style args keyword values ... + +* ID, group-ID are documented in :doc:`fix ` command +* add/heat = style name of this fix command +* style = *constant* or *linear* or *quartic* + + .. parsed-literal:: + + *constant* args = *rate* + *rate* = rate of heat flow (energy/time units) + *linear* args = :math:`T_{target}` *k* + :math:`T_{target}` = target temperature (temperature units) + *k* = prefactor (energy/(time*temperature) units) + *quartic* args = :math:`T_{target}` *k* + :math:`T_{target}` = target temperature (temperature units) + *k* = prefactor (energy/(time*temperature^4) units) + +* zero or more keyword/value pairs may be appended to args +* keyword = *overwrite* + + .. parsed-literal:: + + *overwrite* value = *yes* or *no* + *yes* = sets current heat flow of particle + *no* = adds to current heat flow of particle + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all add/heat constant v_heat + fix 1 all add/heat linear 10.0 1.0 overwrite yes + +Description +""""""""""" + +This fix adds heat to particles with the temperature attribute every timestep. +Note that this is an internal temperature of a particle intended for use with +non-atomistic models like the discrete element method. + +For the *constant* style, heat is added at the specified rate. For the *linear* style, +heat is added at a rate of :math:`k (T_{target} - T)` where :math:`k` is the +specified prefactor, :math:`T_{target}` is the specified target temperature, and +:math:`T` is the temperature of the atom. This may be more representative of a +conductive process. For the *quartic* style, heat is added at a rate of +:math:`k (T_{target}^4 - T^4)`, akin to radiative heat transfer. + +The rate or temperature can be can be specified as an equal-style or atom-style +:doc:`variable `. If the value is a variable, it should be +specified as v_name, where name is the variable name. In this case, the +variable will be evaluated each time step, and its value will be used to +determine the rate of heat added. + +Equal-style variables can specify formulas with various mathematical +functions and include :doc:`thermo_style ` command +keywords for the simulation box parameters, time step, and elapsed time +to specify time-dependent heating. + +Atom-style variables can specify the same formulas as equal-style +variables but can also include per-atom values, such as atom +coordinates to specify spatially-dependent heating. + +If the *overwrite* keyword is set to *yes*, this fix will set the total +heat flow on a particle every timestep, overwriting contributions from pair +styles or other fixes. If *overwrite* is *no*, this fix will add heat on +top of other contributions. + +---------- + +Restart, fix_modify, output, run start/stop, minimize info +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +None of the :doc:`fix_modify ` options are relevant to this fix. +No global or per-atom quantities are stored by this fix for access by various +:doc:`output commands `. No parameter of this fix can be used +with the *start/stop* keywords of the :doc:`run ` command. This fix is +not invoked during :doc:`energy minimization `. + +Restrictions +"""""""""""" + +This pair style is part of the GRANULAR package. It is +only enabled if LAMMPS was built with that package. +See the :doc:`Build package ` page for more info. + +This fix requires that atoms store temperature and heat flow +as defined by the :doc:`fix property/atom ` command. + +Related commands +"""""""""""""""" + +:doc:`fix heat/flow `, +:doc:`fix property/atom `, +:doc:`fix rheo/thermal ` + +Default +""""""" + +The default for the *overwrite* keyword is *no* diff --git a/doc/src/fix_heat_flow.rst b/doc/src/fix_heat_flow.rst index 1ca99a1686..aa2b3fbc06 100644 --- a/doc/src/fix_heat_flow.rst +++ b/doc/src/fix_heat_flow.rst @@ -1,7 +1,7 @@ .. index:: fix heat/flow fix heat/flow command -========================== +===================== Syntax """""" @@ -56,13 +56,19 @@ not invoked during :doc:`energy minimization `. Restrictions """""""""""" +This pair style is part of the GRANULAR package. It is +only enabled if LAMMPS was built with that package. +See the :doc:`Build package ` page for more info. + This fix requires that atoms store temperature and heat flow as defined by the :doc:`fix property/atom ` command. Related commands """""""""""""""" -:doc:`pair granular `, :doc:`fix property/atom ` +:doc:`pair granular `, +:doc:`fix add/heat `, +:doc:`fix property/atom ` Default """"""" diff --git a/doc/src/fix_rheo.rst b/doc/src/fix_rheo.rst new file mode 100644 index 0000000000..c9bf0a7aa0 --- /dev/null +++ b/doc/src/fix_rheo.rst @@ -0,0 +1,180 @@ +.. index:: fix rheo + +fix rheo command +================ + +Syntax +"""""" + +.. parsed-literal:: + + fix ID group-ID rheo cut kstyle zmin keyword values... + +* ID, group-ID are documented in :doc:`fix ` command +* rheo = style name of this fix command +* cut = cutoff for the kernel (distance) +* kstyle = *quintic* or *RK0* or *RK1* or *RK2* +* zmin = minimal number of neighbors for reproducing kernels +* zero or more keyword/value pairs may be appended to args +* keyword = *thermal* or *interface/reconstruct* or *surface/detection* or + *shift* or *rho/sum* or *density* or *self/mass* or *speed/sound* + + .. parsed-literal:: + + *thermal* values = none, turns on thermal evolution + *interface/reconstruct* values = none, reconstructs interfaces with solid particles + *surface/detection* values = *sdstyle* *limit* *limit/splash* + *sdstyle* = *coordination* or *divergence* + *limit* = threshold for surface particles + *limit/splash* = threshold for splash particles + *shift* values = none, turns on velocity shifting + *rho/sum* values = none, uses the kernel to compute the density of particles + *self/mass* values = none, a particle uses its own mass in a rho summation + *density* values = *rho01*, ... *rho0N* (density) + *speed/sound* values = *cs0*, ... *csN* (velocity) + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all rheo 3.0 quintic 0 thermal density 0.1 0.1 speed/sound 10.0 1.0 + fix 1 all rheo 3.0 RK1 10 shift surface/detection coordination 40 + +Description +""""""""""" + +.. versionadded:: TBD + +Perform time integration for RHEO particles, updating positions, velocities, +and densities. For a detailed breakdown of the integration timestep and +numerical details, see :ref:`(Palermo) `. For an +overview of other features available in the RHEO package, see +:doc:`the RHEO howto `. + +The type of kernel is specified using *kstyle* and the cutoff is *cut*. Four +kernels are currently available. The *quintic* kernel is a standard quintic +spline function commonly used in SPH. The other options, *RK0*, *RK1*, and +*RK2*, are zeroth, first, and second order reproducing. To generate a +reproducing kernel, a particle must have sufficient neighbors inside the +kernel cutoff distance (a coordination number) to accurately calculate +moments. This threshold is set by *zmin*. If reproducing kernels are +requested but a particle has fewer neighbors, then it will revert to a +non-reproducing quintic kernel until it gains more neighbors. + +To model temperature evolution, one must specify the *thermal* keyword, +define a separate instance of :doc:`fix rheo/thermal `, +and use atom style rheo/thermal. + +By default, the density of solid RHEO particles does not evolve and forces +with fluid particles are calculated using the current velocity of the solid +particle. If the *interface/reconstruct* keyword is used, then the density +and velocity of solid particles are alternatively reconstructed for every +fluid-solid interaction to ensure no-slip and pressure-balanced boundaries. +This is done by estimating the location of the fluid-solid interface and +extrapolating fluid particle properties across the interface to calculate a +temporary apparent density and velocity for a solid particle. The numerical +details are the same as those described in +:ref:`(Palermo) ` except there is an additional +restriction that the reconstructed solid density cannot be less than the +equilibrium density. This prevents fluid particles from sticking to solid +surfaces. + +A modified form of Fickian particle shifting can be enabled with the +*shift* keyword. This effectively shifts particle positions to generate a +more uniform spatial distribution. Shifting currently does not consider the +type of a particle and therefore may be inappropriate in systems consisting +of multiple fluid phases. + +In systems with free surfaces, the *surface/detection* keyword can be used +to classify the location of particles as being within the bulk fluid, on a +free surface, or isolated from other particles in a splash or droplet. +Shifting is then disabled in the normal direction away from the free surface +to prevent particles from diffusing away. Surface detection can also be used +to control surface-nucleated effects like oxidation when used in combination +with :doc:`fix rheo/oxidation `. Surface detection is not +performed on solid bodies. + +The *surface/detection* keyword takes three arguments: *sdstyle*, *limit*, +and *limit/splash*. The first, *sdstyle*, specifies whether surface particles +are identified using a coordination number (*coordination*) or the divergence +of the local particle positions (*divergence*). The threshold value for a +surface particle for either of these criteria is set by the numerical value +of *limit*. Additionally, if a particle's coordination number is too low, +i.e. if it has separated off from the bulk in a droplet, it is not possible +to define surfaces and the particle is classified as a splash. The coordination +threshold for this classification is set by the numerical value of +*limit/splash*. + +By default, RHEO integrates particles' densities using a mass diffusion +equation. Alternatively, one can update densities every timestep by performing +a kernel summation of the masses of neighboring particles by specifying the *rho/sum* +keyword. + +The *self/mass* keyword modifies the behavior of the density summation in *rho/sum*. +Typically, the density :math:`\rho` of a particle is calculated as the sum over neighbors + +.. math:: + \rho_i = \sum_{j} W_{ij} M_j + +where :math:`W_{ij}` is the kernel, and :math:`M_j` is the mass of particle :math:`j`. +The *self/mass* keyword augments this expression by replacing :math:`M_j` with +:math:`M_i`. This may be useful in simulations of multiple fluid phases with large +differences in density, :ref:`(Hu) `. + +The *density* keyword is used to specify the equilibrium density of each of the N +particle types. It must be followed by N numerical values specifying each type's +equilibrium density *rho0*. + +The *speed/sound* keyword is used to specify the speed of sound of each of the +N particle types. It must be followed by N numerical values specifying each type's +speed of sound *cs*. + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +None of the :doc:`fix_modify ` options +are relevant to this fix. No global or per-atom quantities are stored +by this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix must be used with atom style rheo or rheo/thermal. This fix must +be used in conjunction with :doc:`fix rheo/pressure `. +and :doc:`fix rheo/viscosity `. If the *thermal* setting +is used, there must also be an instance of +:doc:`fix rheo/thermal `. The fix group must be set to all. +Only one instance of fix rheo may be defined and it must be defined prior +to all other RHEO fixes in the input script. + +This fix is part of the RHEO package. It is only enabled if LAMMPS was built +with that package. See the :doc:`Build package ` page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo/viscosity `, +:doc:`fix rheo/pressure `, +:doc:`fix rheo/thermal `, +:doc:`pair rheo `, +:doc:`compute rheo/property/atom ` + +Default +""""""" + +*rho0* and *cs* are set to 1.0 for all atom types. + +---------- + +.. _rheo_palermo: + +**(Palermo)** Palermo, Wolf, Clemmer, O'Connor, in preparation. + +.. _fix_rheo_hu: + +**(Hu)** Hu, and Adams J. Comp. Physics, 213, 844-861 (2006). diff --git a/doc/src/fix_rheo_oxidation.rst b/doc/src/fix_rheo_oxidation.rst new file mode 100644 index 0000000000..ba3ead3f1f --- /dev/null +++ b/doc/src/fix_rheo_oxidation.rst @@ -0,0 +1,85 @@ +.. index:: fix rheo/oxidation + +fix rheo/oxidation command +========================== + +Syntax +"""""" + +.. parsed-literal:: + + fix ID group-ID rheo/oxidation cut btype rsurf + +* ID, group-ID are documented in :doc:`fix ` command +* rheo/oxidation = style name of this fix command +* cut = maximum bond length (distance units) +* btype = type of bonds created +* rsurf = distance from surface to create bonds (distance units) + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all rheo/oxidation 1.5 2 0.0 + fix 1 all rheo/oxidation 1.0 1 2.0 + +Description +""""""""""" + +.. versionadded:: TBD + +This fix dynamically creates bonds on the surface of fluids to +represent physical processes such as oxidation. It is intended +for use with bond style :doc:`bond rheo/shell `. + +Every timestep, particles check neighbors within a distance of *cut*. +This distance must be smaller than the kernel length defined in +:doc:`fix rheo `. Bonds of type *btype* are created between +a fluid particle and either a fluid or solid neighbor. The fluid particles +must also be on the fluid surface, or within a distance of *rsurf* from +the surface. This process is further described in +:ref:`(Clemmer) `. + +If used in conjunction with solid bodies, such as those generated +by the *react* option of :doc:`fix rheo/thermal `, +it is recommended to use a :doc:`hybrid bond style ` +with different bond types for solid and oxide bonds. + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +None of the :doc:`fix_modify ` options +are relevant to this fix. No global or per-atom quantities are stored +by this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during :doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix must be used with the bond style :doc:`rheo/shell ` +and :doc:`fix rheo ` with surface detection enabled. + +This fix is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the :doc:`Build package ` +page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo `, +:doc:`bond rheo/shell `, +:doc:`compute rheo/property/atom ` + +Default +""""""" + +none + +---------- + +.. _howto_rheo_clemmer2: + +**(Clemmer)** Clemmer, Pierce, O'Connor, Nevins, Jones, Lechman, Tencer, Appl. Math. Model., 130, 310-326 (2024). diff --git a/doc/src/fix_rheo_pressure.rst b/doc/src/fix_rheo_pressure.rst new file mode 100644 index 0000000000..40d623ae07 --- /dev/null +++ b/doc/src/fix_rheo_pressure.rst @@ -0,0 +1,106 @@ +.. index:: fix rheo/pressure + +fix rheo/pressure command +========================= + +Syntax +"""""" + +.. parsed-literal:: + + fix ID group-ID rheo/pressure type1 pstyle1 args1 ... typeN pstyleN argsN + +* ID, group-ID are documented in :doc:`fix ` command +* rheo/pressure = style name of this fix command +* one or more types and pressure styles must be appended +* types = lists of types (see below) +* pstyle = *linear* or *taitwater* or *cubic* + + .. parsed-literal:: + + *linear* args = none + *taitwater* args = none + *cubic* args = cubic prefactor :math:`A_3` (pressure/density\^2) + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all rheo/pressure * linear + fix 1 all rheo/pressure 1 linear 2 cubic 10.0 + +Description +""""""""""" + +.. versionadded:: TBD + +This fix defines a pressure equation of state for RHEO particles. One can +define different equations of state for different atom types. An equation +must be specified for every atom type. + +One first defines the atom *types*. A wild-card asterisk can be used in place +of or in conjunction with the *types* argument to set the coefficients for +multiple pairs of atom types. This takes the form "\*" or "\*n" or "m\*" +or "m\*n". If :math:`N` is the number of atom types, then an asterisk with +no numeric values means all types from 1 to :math:`N`. A leading asterisk +means all types from 1 to n (inclusive). A trailing asterisk means all types +from m to :math:`N` (inclusive). A middle asterisk means all types from m to n +(inclusive). + +The *types* definition is followed by the pressure style, *pstyle*. Current +options *linear*, *taitwater*, and *cubic*. Style *linear* is a linear +equation of state with a particle pressure :math:`P` calculated as + +.. math:: + + P = c (\rho - \rho_0) + +where :math:`c` is the speed of sound, :math:`\rho_0` is the equilibrium density, +and :math:`\rho` is the current density of a particle. The numerical values of +:math:`c` and :math:`\rho_0` are set in :doc:`fix rheo `. Style *cubic* +is a cubic equation of state which has an extra argument :math:`A_3`, + +.. math:: + + P = c ((\rho - \rho_0) + A_3 (\rho - \rho_0)^3) . + +Style *taitwater* is Tait's equation of state: + +.. math:: + + P = \frac{c^2 \rho_0}{7} \biggl[\left(\frac{\rho}{\rho_0}\right)^{7} - 1\biggr]. + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +None of the :doc:`fix_modify ` options +are relevant to this fix. No global or per-atom quantities are stored +by this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during :doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix must be used with an atom style that includes density +such as atom_style rheo or rheo/thermal. This fix must be used in +conjunction with :doc:`fix rheo `. The fix group must be +set to all. Only one instance of fix rheo/pressure can be defined. + +This fix is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the :doc:`Build package ` +page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo `, +:doc:`pair rheo `, +:doc:`compute rheo/property/atom ` + +Default +""""""" + +none diff --git a/doc/src/fix_rheo_thermal.rst b/doc/src/fix_rheo_thermal.rst new file mode 100644 index 0000000000..cf245cbdca --- /dev/null +++ b/doc/src/fix_rheo_thermal.rst @@ -0,0 +1,128 @@ +.. index:: fix rheo/thermal + +fix rheo/thermal command +======================== + +Syntax +"""""" + +.. parsed-literal:: + + fix ID group-ID rheo/thermal attribute values ... + +* ID, group-ID are documented in :doc:`fix ` command +* rheo/thermal = style name of this fix command +* one or more attributes may be appended +* attribute = *conductivity* or *specific/heat* or *latent/heat* or *Tfreeze* or *react* + + .. parsed-literal:: + + *conductivity* args = types style args + types = lists of types (see below) + style = *constant* + *constant* arg = conductivity (power/temperature) + *specific/heat* args = types style args + types = lists of types (see below) + style = *constant* + *constant* arg = specific heat (energy/(mass*temperature)) + *latent/heat* args = types style args + types = lists of types (see below) + style = *constant* + *constant* arg = latent heat (energy/mass) + *Tfreeze* args = types style args + types = lists of types (see below) + style = *constant* + *constant* arg = freezing temperature (temperature) + *react* args = cut type + cut = maximum bond distance + type = bond type + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all rheo/thermal conductivity * constant 1.0 specific/heat * constant 1.0 Tfreeze * constant 1.0 + fix 1 all rheo/pressure conductivity 1*2 constant 1.0 conductivity 3*4 constant 2.0 specific/heat * constant 1.0 + +Description +""""""""""" + +.. versionadded:: TBD + +This fix performs time integration of temperature for atom style rheo/thermal. +In addition, it defines multiple thermal properties of particles and handles +melting/solidification, if applicable. For more details on phase transitions +in RHEO, see :doc:`the RHEO howto `. + +Note that the temperature of a particle is always derived from the energy. +This implies the *temperature* attribute of :doc:`the set command ` does +not affect particles. Instead, one should use the *sph/e* attribute. + +For each atom type, one can define expressions for the *conductivity*, +*specific/heat*, *latent/heat*, and critical temperature (*Tfreeze*). +The conductivity and specific heat must be defined for all atom types. +The latent heat and critical temperature are optional. However, a +critical temperature must be defined to specify a latent heat. + +Note, if shifting is turned on in :doc:`fix rheo `, the gradient +of the energy is used to shift energies. This may be inappropriate in systems +with multiple atom types with different specific heats. + +For each property, one must first define a list of atom types. A wild-card +asterisk can be used in place of or in conjunction with the *types* argument +to set the coefficients for multiple pairs of atom types. This takes the +form "\*" or "\*n" or "m\*" or "m\*n". If :math:`N` is the number of atom +types, then an asterisk with no numeric values means all types from 1 to +:math:`N`. A leading asterisk means all types from 1 to n (inclusive). +A trailing asterisk means all types from m to :math:`N` (inclusive). A +middle asterisk means all types from m to n (inclusive). + +The *types* definition for each property is followed by the style. Currently, +the only option is *constant*. Style *constant* simply applies a constant value +of respective property to each particle of the assigned type. + +The *react* keyword controls whether bonds are created/deleted when particles +transition between a fluid and solid state. This option only applies to atom +types that have a defined value of *Tfreeze*. When a fluid particle's +temperature drops below *Tfreeze*, bonds of type *btype* are created between +nearby solid particles within a distance of *cut*. The particle's status also +swaps to a solid state. When a solid particle's temperature rises above +*Tfreeze*, all bonds of type *btype* are broken and the particle's status swaps +to a fluid state. + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +None of the :doc:`fix_modify ` options +are relevant to this fix. No global or per-atom quantities are stored +by this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during :doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix must be used with an atom style that includes temperature, +heatflow, and conductivity such as atom_style rheo/thermal This fix +must be used in conjunction with :doc:`fix rheo ` with the +*thermal* setting. The fix group must be set to all. Only one +instance of fix rheo/pressure can be defined. + +This fix is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the :doc:`Build package ` +page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo `, +:doc:`pair rheo `, +:doc:`compute rheo/property/atom `, +:doc:`fix add/heat ` + +Default +""""""" + +none diff --git a/doc/src/fix_rheo_viscosity.rst b/doc/src/fix_rheo_viscosity.rst new file mode 100644 index 0000000000..5eca39dcdd --- /dev/null +++ b/doc/src/fix_rheo_viscosity.rst @@ -0,0 +1,117 @@ +.. index:: fix rheo/viscosity + +fix rheo/viscosity command +========================== + +Syntax +"""""" + +.. parsed-literal:: + + fix ID group-ID rheo/viscosity type1 pstyle1 args1 ... typeN pstyleN argsN + +* ID, group-ID are documented in :doc:`fix ` command +* rheo/viscosity = style name of this fix command +* one or more types and viscosity styles must be appended +* types = lists of types (see below) +* vstyle = *constant* or *power* + + .. parsed-literal:: + + *constant* args = *eta* + *eta* = viscosity + + *power* args = *eta*, *gd0*, *K*, *n* + *eta* = viscosity + *gd0* = critical strain rate + *K* = consistency index + *n* = power-law exponent + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all rheo/viscosity * constant 1.0 + fix 1 all rheo/viscosity 1 constant 1.0 2 power 0.1 5e-4 0.001 0.5 + +Description +""""""""""" + +.. versionadded:: TBD + +This fix defines a viscosity for RHEO particles. One can define different +viscosities for different atom types, but a viscosity must be specified for +every atom type. + +One first defines the atom *types*. A wild-card asterisk can be used in place +of or in conjunction with the *types* argument to set the coefficients for +multiple pairs of atom types. This takes the form "\*" or "\*n" or "m\*" +or "m\*n". If :math:`N` is the number of atom types, then an asterisk with +no numeric values means all types from 1 to :math:`N`. A leading asterisk +means all types from 1 to n (inclusive). A trailing asterisk means all types +from m to :math:`N` (inclusive). A middle asterisk means all types from m to n +(inclusive). + +The *types* definition is followed by the viscosity style, *vstyle*. Two +options are available, *constant* and *power*. Style *constant* simply +applies a constant value of the viscosity *eta* to each particle of the +assigned type. Style *power* is a Hershchel-Bulkley constitutive equation +for the stress :math:`\tau` + +.. math:: + + \tau = \left(\frac{\tau_0}{\dot{\gamma}} + K \dot{\gamma}^{n - 1}\right) \dot{\gamma}, \tau \ge \tau_0 + +where :math:`\dot{\gamma}` is the strain rate and :math:`\tau_0` is the critical +yield stress, below which :math:`\dot{\gamma} = 0.0`. To avoid divergences, this +expression is regularized by defining a critical strain rate *gd0*. If the local +strain rate on a particle falls below this limit, a constant viscosity of *eta* +is assigned. This implies a value of + +.. math:: + \tau_0 = \eta \dot{\gamma}_0 - K \dot{\gamma}_0^N + +as further discussed in :ref:`(Palermo) `. + + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +None of the :doc:`fix_modify ` options +are relevant to this fix. No global or per-atom quantities are stored +by this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix must be used with an atom style that includes viscosity +such as atom_style rheo or rheo/thermal. This fix must be used in +conjunction with :doc:`fix rheo `. The fix group must be +set to all. Only one instance of fix rheo/viscosity can be defined. + +This fix is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the +:doc:`Build package ` page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo `, +:doc:`pair rheo `, +:doc:`compute rheo/property/atom ` + +Default +""""""" + +none + +---------- + +.. _rheo_palermo2: + +**(Palermo)** Palermo, Wolf, Clemmer, O'Connor, in preparation. diff --git a/doc/src/pair_rheo.rst b/doc/src/pair_rheo.rst new file mode 100644 index 0000000000..993ec3cee3 --- /dev/null +++ b/doc/src/pair_rheo.rst @@ -0,0 +1,102 @@ +.. index:: pair_style rheo + +pair_style rheo command +======================= + +Syntax +"""""" + +.. code-block:: LAMMPS + + pair_style rheo cutoff keyword values + +* cutoff = global cutoff for kernel (distance units) +* zero or more keyword/value pairs may be appended to args +* keyword = *rho/damp* or *artificial/visc* or *harmonic/means* + +.. parsed-literal:: + + *rho/damp* args = density damping prefactor :math:`\xi` + *artificial/visc* args = artificial viscosity prefactor :math:`\zeta` + *harmonic/means* args = none + +Examples +"""""""" + +.. code-block:: LAMMPS + + pair_style rheo 3.0 rho/damp 1.0 artificial/visc 2.0 + pair_coeff * * + +Description +""""""""""" + +.. versionadded:: TBD + +Pair style *rheo* computes pressure and viscous forces between particles +in the :doc:`rheo package `. If thermal evolution is turned +on in :doc:`fix rheo `, then the pair style also calculates +heat exchanged between particles. + +The *artificial/viscosity* keyword is used to specify the magnitude +:math:`\zeta` of an optional artificial viscosity contribution to forces. +This factor can help stabilize simulations by smoothing out small length +scale variations in velocity fields. Artificial viscous forces typically +are only exchanged by fluid particles. However, if interfaces are not +reconstructed in fix rheo, fluid particles will also exchange artificial +viscous forces with solid particles to improve stability. + +The *rho/damp* keyword is used to specify the magnitude :math:`\xi` of +an optional pairwise damping term between the density of particles. This +factor can help stabilize simulations by smoothing out small length +scale variations in density fields. However, in systems that develop +a density gradient in equilibrium (e.g. in a hydrostatic column underlying +gravity), this option may be inappropriate. + +If particles have different viscosities or conductivities, the +*harmonic/means* keyword changes how they are averaged before calculating +pairwise forces or heat exchanges. By default, an arithmetic averaged is +used, however, a harmonic mean may improve stability in systems with multiple +fluid phases with large disparities in viscosities. + +No coefficients are defined for each pair of atoms types via the +:doc:`pair_coeff ` command as in the examples +above. + +---------- + +Mixing, shift, table, tail correction, restart, rRESPA info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +This style does not support the :doc:`pair_modify ` +shift, table, and tail options. + +This style does not write information to :doc:`binary restart files `. +Thus, you need to re-specify the pair_style and pair_coeff commands in an input +script that reads a restart file. + +This style can only be used via the *pair* keyword of the +:doc:`run_style respa ` command. It does not support the *inner*, +*middle*, *outer* keywords. + +Restrictions +"""""""""""" + +This fix is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the +:doc:`Build package ` page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo `, +:doc:`fix rheo/pressure `, +:doc:`fix rheo/thermal `, +:doc:`fix rheo/viscosity `, +:doc:`compute rheo/property/atom ` + +Default +""""""" + +Density damping and artificial viscous forces are not calculated. +Arithmetic means are used for mixing particle properties. diff --git a/doc/src/pair_rheo_solid.rst b/doc/src/pair_rheo_solid.rst new file mode 100644 index 0000000000..0b1ed47fb8 --- /dev/null +++ b/doc/src/pair_rheo_solid.rst @@ -0,0 +1,112 @@ +.. index:: pair_style rheo/solid + +pair_style rheo/solid command +============================= + +Syntax +"""""" + +.. code-block:: LAMMPS + + pair_style rheo/solid + +Examples +"""""""" + +.. code-block:: LAMMPS + + pair_style rheo/solid + pair_coeff * * 1.0 1.5 1.0 + +Description +""""""""""" + +.. versionadded:: TBD + +Style *rheo/solid* is effectively a copy of pair style +:doc:`bpm/spring ` except it only applies forces +between solid RHEO particles, determined by checking the status of +each pair of neighboring particles before calculating forces. + +The style computes pairwise forces with the formula + +.. math:: + + F = k (r - r_c) + +where :math:`k` is a stiffness and :math:`r_c` is the cutoff length. +An additional damping force is also applied to interacting +particles. The force is proportional to the difference in the +normal velocity of particles + +.. math:: + + F_D = - \gamma w (\hat{r} \bullet \vec{v}) + +where :math:`\gamma` is the damping strength, :math:`\hat{r}` is the +displacement normal vector, :math:`\vec{v}` is the velocity difference +between the two particles, and :math:`w` is a smoothing factor. +This smoothing factor is constructed such that damping forces go to zero +as particles come out of contact to avoid discontinuities. It is +given by + +.. math:: + + w = 1.0 - \left( \frac{r}{r_c} \right)^8 . + +The following coefficients must be defined for each pair of atom types +via the :doc:`pair_coeff ` command as in the examples +above, or in the data file or restart files read by the +:doc:`read_data ` or :doc:`read_restart ` +commands, or by mixing as described below: + +* :math:`k` (force/distance units) +* :math:`r_c` (distance units) +* :math:`\gamma` (force/velocity units) + + +---------- + +Mixing, shift, table, tail correction, restart, rRESPA info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +For atom type pairs I,J and I != J, the A coefficient and cutoff +distance for this pair style can be mixed. A is always mixed via a +*geometric* rule. The cutoff is mixed according to the pair_modify +mix value. The default mix value is *geometric*\ . See the +"pair_modify" command for details. + +This pair style does not support the :doc:`pair_modify ` +shift option, since the pair interaction goes to 0.0 at the cutoff. + +The :doc:`pair_modify ` table and tail options are not +relevant for this pair style. + +This pair style writes its information to :doc:`binary restart files +`, so pair_style and pair_coeff commands do not need to be +specified in an input script that reads a restart file. + +This pair style can only be used via the *pair* keyword of the +:doc:`run_style respa ` command. It does not support the +*inner*, *middle*, *outer* keywords. + +---------- + +Restrictions +"""""""""""" + +This pair style is part of the RHEO package. It is only enabled if +LAMMPS was built with that package. See the :doc:`Build package +` page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix rheo `, +:doc:`fix rheo/thermal `, +:doc:`pair bpm/spring ` + +Default +""""""" + +none diff --git a/doc/src/pair_style.rst b/doc/src/pair_style.rst index 75157d6127..1cb85ff739 100644 --- a/doc/src/pair_style.rst +++ b/doc/src/pair_style.rst @@ -337,6 +337,8 @@ accelerated styles exist. * :doc:`reaxff ` - ReaxFF potential * :doc:`rebo ` - Second generation REBO potential of Brenner * :doc:`rebomos ` - REBOMoS potential for MoS2 +* :doc:`rheo ` - fluid interactions in RHEO package +* :doc:`rheo/solid ` - solid interactions in RHEO package * :doc:`resquared ` - Everaers RE-Squared ellipsoidal potential * :doc:`saip/metal ` - Interlayer potential for hetero-junctions formed with hexagonal 2D materials and metal surfaces * :doc:`sdpd/taitwater/isothermal ` - Smoothed dissipative particle dynamics for water at isothermal conditions diff --git a/doc/src/read_data.rst b/doc/src/read_data.rst index 88060a105b..cbeb46eb3e 100644 --- a/doc/src/read_data.rst +++ b/doc/src/read_data.rst @@ -859,6 +859,10 @@ of analysis. - atom-ID molecule-ID atom-type x y z * - peri - atom-ID atom-type volume density x y z + * - rheo + - atom-ID atom-type status rho x y z + * - rheo/thermal + - atom-ID atom-type status rho energy x y z * - smd - atom-ID atom-type molecule volume mass kradius cradius x0 y0 z0 x y z * - sph diff --git a/doc/src/set.rst b/doc/src/set.rst index 8a6510f88f..6ef654c5a7 100644 --- a/doc/src/set.rst +++ b/doc/src/set.rst @@ -120,6 +120,8 @@ Syntax *angle* value = numeric angle type or angle type label, for all angles between selected atoms *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms *improper* value = numeric improper type or improper type label, for all impropers between selected atoms + *rheo/rho* value = density of RHEO particles (mass/distance\^3) + *rheo/status* value = status or phase of RHEO particles (unitless) *sph/e* value = energy of SPH particles (need units) value can be an atom-style variable (see below) *sph/cv* value = heat capacity of SPH particles (need units) @@ -506,6 +508,10 @@ by the *bond types* (\ *angle types*, etc) field in the header of the data file read by the :doc:`read_data ` command. These keywords do not allow use of an atom-style variable. +Keywords *rheo/rho* and *rheo/status* set the density and the status of +rheo particles. In particular, one can only set the phase in the status +as described by the :doc:`RHEO howto page `. + Keywords *sph/e*, *sph/cv*, and *sph/rho* set the energy, heat capacity, and density of smoothed particle hydrodynamics (SPH) particles. See `this PDF guide `_ to using SPH in LAMMPS. diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index c300cf608d..babe66d27d 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -393,6 +393,7 @@ buf builtin Bulacu Bulatov +Bulkley Bureekaew burlywood Bussi @@ -564,6 +565,7 @@ cond conda Conda Condens +conductivities conf config configfile @@ -1440,6 +1442,7 @@ henrich Henrich Hermitian Herrmann +Hershchel Hertizian hertzian Hertzsch @@ -1831,6 +1834,7 @@ Kspace KSpace KSpaceStyle Kspring +kstyle kT kTequil kth @@ -2271,6 +2275,7 @@ modelled modelling Modelling Modine +modularity moduli mofff MOFFF @@ -2488,6 +2493,7 @@ Neumann Nevent nevery Nevery +Nevins newfile Newns newtype @@ -3067,6 +3073,7 @@ quatw queryargs Queteschiner quickmin +quintic qw qx qy @@ -3078,6 +3085,7 @@ radialscreenedspin radialspin radian radians +radiative radj Rafferty rahman @@ -3181,6 +3189,7 @@ rg Rg Rhaphson Rhe +rheo rheological rheology rhodo @@ -3268,6 +3277,7 @@ rsort rsq rst rstyle +rsurf Rubensson Rubia Rud @@ -3651,6 +3661,7 @@ Telsa tempCorrCoeff templated Templeton +Tencer Tequil ters tersoff @@ -3997,6 +4008,7 @@ Vries Vsevolod Vsmall Vstream +vstyle vtarget vtk VTK diff --git a/examples/rheo/balloon/in.rheo.balloon b/examples/rheo/balloon/in.rheo.balloon new file mode 100644 index 0000000000..24e400f40f --- /dev/null +++ b/examples/rheo/balloon/in.rheo.balloon @@ -0,0 +1,75 @@ +# ------ 2D water balloon ------ # + +dimension 2 +units lj +atom_style hybrid rheo bond +boundary m m p +comm_modify vel yes +newton off + +region box block -40 40 0 80 -0.01 0.01 units box +create_box 1 box bond/types 1 extra/bond/per/atom 15 extra/special/per/atom 50 + +region fluid sphere -10 40 0 30 units box side in +lattice hex 1.0 +create_atoms 1 region fluid + +region shell sphere -10 40 0 27 units box side out +group shell region shell + +set group shell rheo/status 1 +set group all vx 0.005 vy -0.04 + +# ------ Model parameters ------# + +variable cut equal 3.0 +variable n equal 1.0 +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable zeta equal 0.05 +variable kappa equal 0.01*${rho0}/${mp} +variable dt_max equal 0.1*${cut}/${cs}/3 +variable eta equal 0.05 +variable Cv equal 1.0 +variable L equal 1.0 +variable Tf equal 1.0 + +mass * ${mp} +timestep 0.1 + +pair_style hybrid/overlay rheo ${cut} artificial/visc ${zeta} rheo/solid +pair_coeff * * rheo +pair_coeff * * rheo/solid 1.0 1.0 1.0 + +special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0 +create_bonds many shell shell 1 0 1.5 +special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0 + +bond_style bpm/spring +bond_coeff 1 1.0 1.0 1.0 + +# A lower critical strain allows the balloon to pop +#bond_coeff 1 1.0 0.05 1.0 + +# ------ Drop balloon ------# + +fix 1 all rheo ${cut} quintic 0 & + shift & + surface/detection coordination 22 8 +fix 2 all rheo/viscosity * constant ${eta} +fix 3 all rheo/pressure * linear +fix 4 all wall/harmonic ylo EDGE 2.0 1.0 1.0 +fix 5 all enforce2d + +compute rho all rheo/property/atom rho +compute phase all rheo/property/atom phase +compute nbond all nbond/atom + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press atoms + +#dump 1 all custom 200 atomDump id type x y vx vy fx fy c_phase c_nbond c_rho +run 30000 diff --git a/examples/rheo/balloon/log.17Apr2024.balloon.g++.4 b/examples/rheo/balloon/log.17Apr2024.balloon.g++.4 new file mode 100644 index 0000000000..28fcc4b590 --- /dev/null +++ b/examples/rheo/balloon/log.17Apr2024.balloon.g++.4 @@ -0,0 +1,382 @@ +LAMMPS (17 Apr 2024 - Development - patch_5May2020-18508-g3c0eaf6870-modified) +# ------ 2D water balloon ------ # + +dimension 2 +units lj +atom_style hybrid rheo bond +boundary m m p +comm_modify vel yes +newton off + +region box block -40 40 0 80 -0.01 0.01 units box +create_box 1 box bond/types 1 extra/bond/per/atom 15 extra/special/per/atom 50 +Created orthogonal box = (-40 0 -0.01) to (40 80 0.01) + 2 by 2 by 1 MPI processor grid + +region fluid sphere -10 40 0 30 units box side in +lattice hex 1.0 +Lattice spacing in x,y,z = 1.0745699 1.8612097 1.0745699 +create_atoms 1 region fluid +Created 2830 atoms + using lattice units in orthogonal box = (-40 0 -0.01) to (40 80 0.01) + create_atoms CPU = 0.001 seconds + +region shell sphere -10 40 0 27 units box side out +group shell region shell +544 atoms in group shell + +set group shell rheo/status 1 +Setting atom values ... + 544 settings made for rheo/status +set group all vx 0.005 vy -0.04 +Setting atom values ... + 2830 settings made for vx + 2830 settings made for vy + +# ------ Model parameters ------# + +variable cut equal 3.0 +variable n equal 1.0 +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable mp equal 1/${n} +variable mp equal 1/1 +variable zeta equal 0.05 +variable kappa equal 0.01*${rho0}/${mp} +variable kappa equal 0.01*1/${mp} +variable kappa equal 0.01*1/1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable dt_max equal 0.1*3/${cs}/3 +variable dt_max equal 0.1*3/1/3 +variable eta equal 0.05 +variable Cv equal 1.0 +variable L equal 1.0 +variable Tf equal 1.0 + +mass * ${mp} +mass * 1 +timestep 0.1 + +pair_style hybrid/overlay rheo ${cut} artificial/visc ${zeta} rheo/solid +pair_style hybrid/overlay rheo 3 artificial/visc ${zeta} rheo/solid +pair_style hybrid/overlay rheo 3 artificial/visc 0.05 rheo/solid +pair_coeff * * rheo +pair_coeff * * rheo/solid 1.0 1.0 1.0 + +special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0 +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 1 1 + special bond factors coul: 0 1 1 + 0 = max # of 1-2 neighbors + 101 = max # of special neighbors + special bonds CPU = 0.000 seconds +create_bonds many shell shell 1 0 1.5 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 49 49 1 + 3 neighbor lists, perpetual/occasional/extra = 2 1 0 + (1) command create_bonds, occasional + attributes: full, newton off + pair build: full/bin + stencil: full/bin/2d + bin: standard + (2) pair rheo, perpetual + attributes: half, newton off + pair build: half/bin/newtoff + stencil: full/bin/2d + bin: standard + (3) pair rheo/solid, perpetual, trim from (2) + attributes: half, newton off, cut 1.3 + pair build: trim + stencil: none + bin: none +Added 1263 bonds, new total = 1263 +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 1 1 + special bond factors coul: 0 1 1 + 6 = max # of 1-2 neighbors + 101 = max # of special neighbors + special bonds CPU = 0.000 seconds +special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0 + +bond_style bpm/spring +bond_coeff 1 1.0 1.0 1.0 + +# A lower critical strain allows the balloon to pop +#bond_coeff 1 1.0 0.05 1.0 + +# ------ Drop balloon ------# + +fix 1 all rheo ${cut} quintic 0 shift surface/detection coordination 22 8 +fix 1 all rheo 3 quintic 0 shift surface/detection coordination 22 8 +fix 2 all rheo/viscosity * constant ${eta} +fix 2 all rheo/viscosity * constant 0.05 +fix 3 all rheo/pressure * linear +fix 4 all wall/harmonic ylo EDGE 2.0 1.0 1.0 +fix 5 all enforce2d + +compute rho all rheo/property/atom rho +compute phase all rheo/property/atom phase +compute nbond all nbond/atom + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press atoms + +dump 1 all custom 200 atomDump id type x y vx vy fx fy c_phase c_nbond c_rho +run 30000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- BPM bond style: doi:10.1039/D3SM01373A + +@Article{Clemmer2024, + author = {Clemmer, Joel T. and Monti, Joseph M. and Lechman, Jeremy B.}, + title = {A soft departure from jamming: the compaction of deformable + granular matter under high pressures}, + journal = {Soft Matter}, + year = 2024, + volume = 20, + number = 8, + pages = {1702--1718} +} + +- @article{PalermoInPrep, + journal = {in prep}, + title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows}, + year = {2024}, + author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 49 49 1 + 6 neighbor lists, perpetual/occasional/extra = 6 0 0 + (1) pair rheo, perpetual, half/full from (3) + attributes: half, newton off + pair build: halffull/newtoff + stencil: none + bin: none + (2) pair rheo/solid, perpetual, trim from (1) + attributes: half, newton off, cut 1.3 + pair build: trim + stencil: none + bin: none + (3) compute RHEO/KERNEL, perpetual + attributes: full, newton off + pair build: full/bin + stencil: full/bin/2d + bin: standard + (4) compute RHEO/GRAD, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (5) compute RHEO/VSHIFT, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (6) compute RHEO/SURFACE, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 17.63 | 17.64 | 17.65 Mbytes + Step Time KinEng Press Atoms + 0 0 0.0008125 0.00035927734 2830 + 200 20 0.0008125 0.00035927734 2830 + 400 40 0.0008125 0.00035927734 2830 + 600 60 0.0008125 0.00035927734 2830 + 800 80 0.0008125 0.00035927734 2830 + 1000 100 0.0008125 0.00035927734 2830 + 1200 120 0.0008125 0.00035927734 2830 + 1400 140 0.0008125 0.00035927734 2830 + 1600 160 0.0008125 0.00035927734 2830 + 1800 180 0.0008125 0.00035927734 2830 + 2000 200 0.0008125 0.00035927734 2830 + 2200 220 0.0008125 0.00035927734 2830 + 2400 240 0.00079033569 0.00043037861 2830 + 2600 260 0.0007549229 0.00045188383 2830 + 2800 280 0.00072808836 0.00031695003 2830 + 3000 300 0.0007017958 1.6121754e-05 2830 + 3200 320 0.00067479047 -0.00015725514 2830 + 3400 340 0.00064762254 -0.00023361314 2830 + 3600 360 0.00061960255 -0.00033837679 2830 + 3800 380 0.0005857206 -0.00051770716 2830 + 4000 400 0.00055061733 -0.00070309251 2830 + 4200 420 0.00051884719 -0.0008247795 2830 + 4400 440 0.00049022236 -0.00099918413 2830 + 4600 460 0.00046060011 -0.0010923159 2830 + 4800 480 0.00042900173 -0.0011524571 2830 + 5000 500 0.00039751503 -0.0012586358 2830 + 5200 520 0.00036620054 -0.0013973543 2830 + 5400 540 0.00033130023 -0.0015185231 2830 + 5600 560 0.00030565892 -0.0016159836 2830 + 5800 580 0.00028209836 -0.0016925198 2830 + 6000 600 0.00024695044 -0.0017796892 2830 + 6200 620 0.00021190635 -0.0018706272 2830 + 6400 640 0.0001947093 -0.0019146643 2830 + 6600 660 0.00018903936 -0.0019146199 2830 + 6800 680 0.00017753371 -0.0019390155 2830 + 7000 700 0.00015170593 -0.0020247472 2830 + 7200 720 0.00011509692 -0.0021222209 2830 + 7400 740 7.9861785e-05 -0.0022033181 2830 + 7600 760 6.1350463e-05 -0.0022511971 2830 + 7800 780 6.5269523e-05 -0.0022222806 2830 + 8000 800 8.5709569e-05 -0.0021089664 2830 + 8200 820 0.00011746348 -0.0019351493 2830 + 8400 840 0.00015698134 -0.0017079928 2830 + 8600 860 0.00019758065 -0.0014618965 2830 + 8800 880 0.00023338199 -0.0012365832 2830 + 9000 900 0.00026282353 -0.0010348527 2830 + 9200 920 0.00028604776 -0.00085287884 2830 + 9400 940 0.00030388767 -0.000681122 2830 + 9600 960 0.000317589 -0.00052203521 2830 + 9800 980 0.00032716728 -0.00037501187 2830 + 10000 1000 0.00033270692 -0.00025576132 2830 + 10200 1020 0.00033485986 -0.00016554207 2830 + 10400 1040 0.00033476763 -9.8525417e-05 2830 + 10600 1060 0.00033351922 -5.1166347e-05 2830 + 10800 1080 0.00033161645 -2.0773965e-05 2830 + 11000 1100 0.00032913022 2.2384421e-07 2830 + 11200 1120 0.00032618376 1.2304773e-05 2830 + 11400 1140 0.00032310409 1.3725982e-05 2830 + 11600 1160 0.0003202128 9.0431945e-06 2830 + 11800 1180 0.00031760386 -5.3537879e-07 2830 + 12000 1200 0.00031518884 -1.331708e-05 2830 + 12200 1220 0.00031283958 -3.0838612e-05 2830 + 12400 1240 0.0003104901 -5.0038548e-05 2830 + 12600 1260 0.00030811597 -6.9699925e-05 2830 + 12800 1280 0.00030555782 -8.9972287e-05 2830 + 13000 1300 0.00030256671 -0.00011712941 2830 + 13200 1320 0.00029907961 -0.00015495826 2830 + 13400 1340 0.00029504656 -0.00020292633 2830 + 13600 1360 0.0002905184 -0.00024892421 2830 + 13800 1380 0.00028564542 -0.000295085 2830 + 14000 1400 0.00028073246 -0.00034571956 2830 + 14200 1420 0.00027611457 -0.00039341977 2830 + 14400 1440 0.00027217382 -0.0004281012 2830 + 14600 1460 0.00026919129 -0.00045342545 2830 + 14800 1480 0.00026727674 -0.00047323419 2830 + 15000 1500 0.0002663482 -0.00048423944 2830 + 15200 1520 0.00026616663 -0.0004816085 2830 + 15400 1540 0.00026634862 -0.00047573486 2830 + 15600 1560 0.0002664314 -0.00046803192 2830 + 15800 1580 0.00026603348 -0.00045753668 2830 + 16000 1600 0.00026511015 -0.00044676105 2830 + 16200 1620 0.00026373403 -0.00044075794 2830 + 16400 1640 0.00026217342 -0.00043684036 2830 + 16600 1660 0.0002607038 -0.00042774771 2830 + 16800 1680 0.00025951097 -0.00041603026 2830 + 17000 1700 0.00025869088 -0.00040302996 2830 + 17200 1720 0.00025825588 -0.00038415247 2830 + 17400 1740 0.00025818373 -0.00035742127 2830 + 17600 1760 0.00025843381 -0.00032854722 2830 + 17800 1780 0.00025897836 -0.00029821183 2830 + 18000 1800 0.00025981472 -0.00026108907 2830 + 18200 1820 0.00026095775 -0.00021731058 2830 + 18400 1840 0.00026239688 -0.00017030825 2830 + 18600 1860 0.00026404432 -0.00011868778 2830 + 18800 1880 0.00026574247 -5.9556286e-05 2830 + 19000 1900 0.00026729563 2.3014881e-06 2830 + 19200 1920 0.00026852418 6.2100169e-05 2830 + 19400 1940 0.00026929086 0.00012090325 2830 + 19600 1960 0.0002695407 0.00017904223 2830 + 19800 1980 0.00026929677 0.00023112254 2830 + 20000 2000 0.00026863577 0.0002756697 2830 + 20200 2020 0.00026765699 0.0003158399 2830 + 20400 2040 0.00026646841 0.00035200747 2830 + 20600 2060 0.00026516938 0.00038018442 2830 + 20800 2080 0.00026383495 0.00040179111 2830 + 21000 2100 0.00026252489 0.00042030921 2830 + 21200 2120 0.00026128616 0.00043466976 2830 + 21400 2140 0.00026014896 0.00044221445 2830 + 21600 2160 0.00025912325 0.00044531883 2830 + 21800 2180 0.00025821515 0.00044661709 2830 + 22000 2200 0.00025742576 0.00044409089 2830 + 22200 2220 0.00025674938 0.00043634999 2830 + 22400 2240 0.00025617111 0.00042630344 2830 + 22600 2260 0.0002556791 0.00041561603 2830 + 22800 2280 0.00025525963 0.00040166735 2830 + 23000 2300 0.00025489538 0.00038430419 2830 + 23200 2320 0.00025456861 0.0003669402 2830 + 23400 2340 0.00025426747 0.00034972373 2830 + 23600 2360 0.00025398353 0.0003302242 2830 + 23800 2380 0.00025370842 0.00030993088 2830 + 24000 2400 0.00025344084 0.00029143258 2830 + 24200 2420 0.00025318683 0.00027421708 2830 + 24400 2440 0.0002529591 0.00025603123 2830 + 24600 2460 0.0002527713 0.00023950245 2830 + 24800 2480 0.00025264228 0.00022644812 2830 + 25000 2500 0.00025259021 0.00021540748 2830 + 25200 2520 0.00025262892 0.00020544201 2830 + 25400 2540 0.00025276229 0.00019845807 2830 + 25600 2560 0.0002529876 0.00019449958 2830 + 25800 2580 0.00025329374 0.00019082606 2830 + 26000 2600 0.00025366066 0.00018700064 2830 + 26200 2620 0.00025406164 0.00018426061 2830 + 26400 2640 0.00025446737 0.00018098339 2830 + 26600 2660 0.00025484714 0.00017471869 2830 + 26800 2680 0.00025516604 0.00016565557 2830 + 27000 2700 0.00025538911 0.00015493626 2830 + 27200 2720 0.00025548177 0.00014075592 2830 + 27400 2740 0.00025541168 0.00012205573 2830 + 27600 2760 0.00025514889 0.00010039772 2830 + 27800 2780 0.00025467547 7.7069215e-05 2830 + 28000 2800 0.0002539915 5.1158042e-05 2830 + 28200 2820 0.00025312083 2.3468384e-05 2830 + 28400 2840 0.00025211323 -3.2184465e-06 2830 + 28600 2860 0.00025104366 -2.7726301e-05 2830 + 28800 2880 0.00025000263 -5.0202987e-05 2830 + 29000 2900 0.00024907814 -6.9244776e-05 2830 + 29200 2920 0.00024833815 -8.2874516e-05 2830 + 29400 2940 0.0002478155 -9.1854992e-05 2830 + 29600 2960 0.00024750313 -9.766055e-05 2830 + 29800 2980 0.00024735538 -9.9681291e-05 2830 + 30000 3000 0.00024730191 -9.818759e-05 2830 +Loop time of 177.982 on 4 procs for 30000 steps with 2830 atoms + +Performance: 1456330.235 tau/day, 168.557 timesteps/s, 477.016 katom-step/s +99.7% CPU use with 4 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 22.913 | 27.061 | 34.594 | 87.2 | 15.20 +Bond | 0.22386 | 0.26159 | 0.30792 | 6.0 | 0.15 +Neigh | 0.84412 | 0.84509 | 0.8462 | 0.1 | 0.47 +Comm | 0.50015 | 0.55579 | 0.60346 | 5.2 | 0.31 +Output | 0.65854 | 0.69412 | 0.72473 | 2.8 | 0.39 +Modify | 133.13 | 136 | 137.38 | 14.5 | 76.41 +Other | | 12.57 | | | 7.06 + +Nlocal: 707.5 ave 1576 max 53 min +Histogram: 2 0 0 0 0 0 1 0 0 1 +Nghost: 164.75 ave 239 max 94 min +Histogram: 1 0 1 0 0 0 0 1 0 1 +Neighs: 12307.8 ave 27380 max 983 min +Histogram: 2 0 0 0 0 0 1 0 0 1 +FullNghs: 23517 ave 53040 max 1502 min +Histogram: 2 0 0 0 0 0 1 0 0 1 + +Total # of neighbors = 94068 +Ave neighs/atom = 33.239576 +Ave special neighs/atom = 0.89257951 +Neighbor list builds = 783 +Dangerous builds = 0 +Total wall time: 0:02:58 diff --git a/examples/rheo/dam-break/in.rheo.dam.break b/examples/rheo/dam-break/in.rheo.dam.break new file mode 100644 index 0000000000..870b3529b6 --- /dev/null +++ b/examples/rheo/dam-break/in.rheo.dam.break @@ -0,0 +1,76 @@ +# ------ 2D dam break ------ # + +dimension 2 +units lj +atom_style rheo +boundary f s p +comm_modify vel yes +newton off + +# ------ Create simulation box ------ # + +variable n equal 1.0 +variable cut equal 2.2 +variable dx equal 3.0 + +region box block -1 150 -1 80 -0.1 0.1 units box +create_box 2 box +lattice hex ${n} + +region fluid block $(xlo+v_dx+1.0) $(xlo+40.0) $(ylo+v_dx+1.0) $(yhi-20.0) EDGE EDGE units box +region walls1 block $(xlo+v_dx) $(xhi-v_dx) $(ylo+v_dx) $(yhi-v_dx) EDGE EDGE side out units box +region walls2 block EDGE EDGE EDGE $(yhi-v_dx) EDGE EDGE side in units box +region walls intersect 2 walls1 walls2 + +create_atoms 1 region fluid +create_atoms 2 region walls + +group fluid type 1 +group rig type 2 + +# ------ Model parameters ------ # + +variable rho0 equal 1.0 +variable mp equal ${rho0}/${n} +variable cs equal 1.0 +variable zeta equal 0.1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable eta equal 0.1 +variable Dr equal 0.1 + +mass 1 ${mp} +mass 2 $(2*v_mp) +set group all rheo/rho ${rho0} + +set group all rheo/status 0 +set group rig rheo/status 1 + +timestep ${dt_max} + +pair_style rheo ${cut} artificial/visc ${zeta} #rho/damp ${Dr} +pair_coeff * * + +# ------ Fixes & computes ------ # + +fix 1 all rheo ${cut} quintic 10 & + surface/detection coordination 22 8 & + rho/sum +fix 2 all rheo/viscosity * constant ${eta} +fix 3 all rheo/pressure * linear +fix 4 all gravity 1e-3 vector 0 -1 0 +fix 5 rig setforce 0.0 0.0 0.0 +fix 6 all enforce2d + +compute rho all rheo/property/atom rho +compute p all rheo/property/atom pressure +compute surf all rheo/property/atom surface +compute sn all rheo/property/atom surface/n/x surface/n/y + +# ------ Output & Run ------ # + +thermo 20 +thermo_style custom step time ke press + +#dump 1 all custom 200 atomDump id type x y vx vy fx fy c_rho c_surf c_p c_sn[*] + +run 30000 diff --git a/examples/rheo/dam-break/log.17Apr2024.dam.g++.4 b/examples/rheo/dam-break/log.17Apr2024.dam.g++.4 new file mode 100644 index 0000000000..6388d9e478 --- /dev/null +++ b/examples/rheo/dam-break/log.17Apr2024.dam.g++.4 @@ -0,0 +1,1694 @@ +LAMMPS (17 Apr 2024 - Development - patch_5May2020-18508-g3c0eaf6870-modified) +# ------ 2D dam break ------ # + +dimension 2 +units lj +atom_style rheo +boundary f s p +comm_modify vel yes +newton off + +# ------ Create simulation box ------ # + +variable n equal 1.0 +variable cut equal 2.2 +variable dx equal 3.0 + +region box block -1 150 -1 80 -0.1 0.1 units box +create_box 2 box +Created orthogonal box = (-1 -1 -0.1) to (150 80 0.1) + 2 by 2 by 1 MPI processor grid +lattice hex ${n} +lattice hex 1 +Lattice spacing in x,y,z = 1.0745699 1.8612097 1.0745699 + +region fluid block $(xlo+v_dx+1.0) $(xlo+40.0) $(ylo+v_dx+1.0) $(yhi-20.0) EDGE EDGE units box +region fluid block 3 $(xlo+40.0) $(ylo+v_dx+1.0) $(yhi-20.0) EDGE EDGE units box +region fluid block 3 39 $(ylo+v_dx+1.0) $(yhi-20.0) EDGE EDGE units box +region fluid block 3 39 2.991900000000000226 $(yhi-20.0) EDGE EDGE units box +region fluid block 3 39 2.991900000000000226 60.008099999999998886 EDGE EDGE units box +region walls1 block $(xlo+v_dx) $(xhi-v_dx) $(ylo+v_dx) $(yhi-v_dx) EDGE EDGE side out units box +region walls1 block 2 $(xhi-v_dx) $(ylo+v_dx) $(yhi-v_dx) EDGE EDGE side out units box +region walls1 block 2 147 $(ylo+v_dx) $(yhi-v_dx) EDGE EDGE side out units box +region walls1 block 2 147 1.9919000000000000039 $(yhi-v_dx) EDGE EDGE side out units box +region walls1 block 2 147 1.9919000000000000039 77.008099999999998886 EDGE EDGE side out units box +region walls2 block EDGE EDGE EDGE $(yhi-v_dx) EDGE EDGE side in units box +region walls2 block EDGE EDGE EDGE 77.008099999999998886 EDGE EDGE side in units box +region walls intersect 2 walls1 walls2 + +create_atoms 1 region fluid +Created 2044 atoms + using lattice units in orthogonal box = (-1 -1.0081 -0.1) to (150 80.0081 0.1) + create_atoms CPU = 0.001 seconds +create_atoms 2 region walls +Created 1002 atoms + using lattice units in orthogonal box = (-1 -1.0081 -0.1) to (150 80.0081 0.1) + create_atoms CPU = 0.000 seconds + +group fluid type 1 +2044 atoms in group fluid +group rig type 2 +1002 atoms in group rig + +# ------ Model parameters ------ # + +variable rho0 equal 1.0 +variable mp equal ${rho0}/${n} +variable mp equal 1/${n} +variable mp equal 1/1 +variable cs equal 1.0 +variable zeta equal 0.1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable dt_max equal 0.1*2.2/${cs}/3 +variable dt_max equal 0.1*2.2/1/3 +variable eta equal 0.1 +variable Dr equal 0.1 + +mass 1 ${mp} +mass 1 1 +mass 2 $(2*v_mp) +mass 2 2 +set group all rheo/rho ${rho0} +set group all rheo/rho 1 +Setting atom values ... + 3046 settings made for rheo/rho + +set group all rheo/status 0 +Setting atom values ... + 3046 settings made for rheo/status +set group rig rheo/status 1 +Setting atom values ... + 1002 settings made for rheo/status + +timestep ${dt_max} +timestep 0.0733333333333333 + +pair_style rheo ${cut} artificial/visc ${zeta} #rho/damp ${Dr} +pair_style rheo 2.2 artificial/visc ${zeta} +pair_style rheo 2.2 artificial/visc 0.1 +pair_coeff * * + +# ------ Fixes & computes ------ # + +fix 1 all rheo ${cut} quintic 10 surface/detection coordination 22 8 rho/sum +fix 1 all rheo 2.2 quintic 10 surface/detection coordination 22 8 rho/sum +fix 2 all rheo/viscosity * constant ${eta} +fix 2 all rheo/viscosity * constant 0.1 +fix 3 all rheo/pressure * linear +fix 4 all gravity 1e-3 vector 0 -1 0 +fix 5 rig setforce 0.0 0.0 0.0 +fix 6 all enforce2d + +compute rho all rheo/property/atom rho +compute p all rheo/property/atom pressure +compute surf all rheo/property/atom surface +compute sn all rheo/property/atom surface/n/x surface/n/y + +# ------ Output & Run ------ # + +thermo 20 +thermo_style custom step time ke press + +dump 1 all custom 200 atomDump id type x y vx vy fx fy c_rho c_surf c_p c_sn[*] + +run 30000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- @article{PalermoInPrep, + journal = {in prep}, + title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows}, + year = {2024}, + author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 1 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 2.5 + ghost atom cutoff = 2.5 + binsize = 1.25, bins = 121 65 1 + 5 neighbor lists, perpetual/occasional/extra = 5 0 0 + (1) pair rheo, perpetual, half/full from (2) + attributes: half, newton off + pair build: halffull/newtoff + stencil: none + bin: none + (2) compute RHEO/KERNEL, perpetual + attributes: full, newton off + pair build: full/bin/atomonly + stencil: full/bin/2d + bin: standard + (3) compute RHEO/GRAD, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (4) compute RHEO/RHO/SUM, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (5) compute RHEO/SURFACE, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 5.707 | 5.721 | 5.736 Mbytes + Step Time KinEng Press + 0 0 0 -8.9662357e-06 + 20 1.4666667 0.00034058796 8.9684994e-05 + 40 2.9333333 6.9365611e-05 2.3675864e-05 + 60 4.4 6.1074185e-05 1.6680783e-05 + 80 5.8666667 5.0534793e-05 1.2623473e-05 + 100 7.3333333 4.1073516e-05 1.1708742e-05 + 120 8.8 4.9303871e-05 1.3714304e-05 + 140 10.266667 5.1669035e-05 1.3579535e-05 + 160 11.733333 6.0107096e-05 1.606084e-05 + 180 13.2 6.9154593e-05 1.8429091e-05 + 200 14.666667 8.0009963e-05 2.0757671e-05 + 220 16.133333 9.1883493e-05 2.3542955e-05 + 240 17.6 0.00010524584 2.6786532e-05 + 260 19.066667 0.00011982479 3.0390295e-05 + 280 20.533333 0.00013474016 3.4766566e-05 + 300 22 0.00015081777 4.0596983e-05 + 320 23.466667 0.00016922091 4.7811202e-05 + 340 24.933333 0.00018746472 5.436563e-05 + 360 26.4 0.00020594739 5.8634772e-05 + 380 27.866667 0.00022673738 6.0759081e-05 + 400 29.333333 0.00024754656 6.1922882e-05 + 420 30.8 0.00026882061 6.4956859e-05 + 440 32.266667 0.00029203 7.2311959e-05 + 460 33.733333 0.00031627032 8.1297842e-05 + 480 35.2 0.00034113307 8.9913587e-05 + 500 36.666667 0.00036599396 9.7909338e-05 + 520 38.133333 0.00039120212 0.0001055925 + 540 39.6 0.00041728537 0.00011265914 + 560 41.066667 0.00044402713 0.00011842088 + 580 42.533333 0.00047160578 0.00012321574 + 600 44 0.00050005372 0.00012842455 + 620 45.466667 0.00052908365 0.00013533445 + 640 46.933333 0.00055833314 0.00014412684 + 660 48.4 0.00058760766 0.00015385416 + 680 49.866667 0.00061704537 0.00016323184 + 700 51.333333 0.00064676026 0.0001720558 + 720 52.8 0.00067674239 0.00018065137 + 740 54.266667 0.00070699735 0.00018906348 + 760 55.733333 0.00073745009 0.00019856234 + 780 57.2 0.00076805806 0.00020874484 + 800 58.666667 0.00079892632 0.00021905295 + 820 60.133333 0.00083019385 0.00022890532 + 840 61.6 0.00086204047 0.00023806257 + 860 63.066667 0.00089463638 0.00024675987 + 880 64.533333 0.0009280011 0.00025519683 + 900 66 0.00096201218 0.00026350368 + 920 67.466667 0.00099657113 0.00027166253 + 940 68.933333 0.0010317502 0.00027992975 + 960 70.4 0.0010676863 0.00028790134 + 980 71.866667 0.0011043796 0.00029680468 + 1000 73.333333 0.0011417187 0.00030600061 + 1020 74.8 0.001179618 0.00031551941 + 1040 76.266667 0.0012180222 0.00032540799 + 1060 77.733333 0.0012568886 0.00033557079 + 1080 79.2 0.0012962727 0.00034616068 + 1100 80.666667 0.0013363417 0.00035717164 + 1120 82.133333 0.0013772784 0.00036920892 + 1140 83.6 0.0014192183 0.00038068516 + 1160 85.066667 0.0014621933 0.00039223594 + 1180 86.533333 0.0015061045 0.00040532576 + 1200 88 0.001550789 0.00041895976 + 1220 89.466667 0.0015961278 0.00043309673 + 1240 90.933333 0.0016420919 0.0004476234 + 1260 92.4 0.001688693 0.00046248791 + 1280 93.866667 0.0017358804 0.00047764479 + 1300 95.333333 0.0017834857 0.0004929783 + 1320 96.8 0.0018313096 0.00050814477 + 1340 98.266667 0.0018793086 0.00052401678 + 1360 99.733333 0.0019277217 0.00053716885 + 1380 101.2 0.0019769204 0.00055180327 + 1400 102.66667 0.0020270711 0.0005656469 + 1420 104.13333 0.0020779701 0.00057917022 + 1440 105.6 0.0021293579 0.00059160854 + 1460 107.06667 0.0021813213 0.00060392999 + 1480 108.53333 0.0022341025 0.00061636071 + 1500 110 0.00228757 0.00062924749 + 1520 111.46667 0.0023412951 0.00064266414 + 1540 112.93333 0.0023952355 0.0006565177 + 1560 114.4 0.0024498098 0.00067063291 + 1580 115.86667 0.0025051272 0.00068509378 + 1600 117.33333 0.0025608522 0.00069926059 + 1620 118.8 0.0026168714 0.000713059 + 1640 120.26667 0.0026733349 0.00072675496 + 1660 121.73333 0.0027302055 0.00074010812 + 1680 123.2 0.0027874761 0.00075390199 + 1700 124.66667 0.0028453711 0.00076786487 + 1720 126.13333 0.0029038156 0.0007820191 + 1740 127.6 0.0029624061 0.00079619745 + 1760 129.06667 0.0030211707 0.00081053823 + 1780 130.53333 0.0030802801 0.00082493927 + 1800 132 0.0031393313 0.00083943639 + 1820 133.46667 0.0031981476 0.00085389118 + 1840 134.93333 0.0032572803 0.00086793469 + 1860 136.4 0.0033167316 0.00088219559 + 1880 137.86667 0.0033757606 0.00089612646 + 1900 139.33333 0.0034343394 0.00090982709 + 1920 140.8 0.0034930349 0.00092382861 + 1940 142.26667 0.0035518482 0.00093805745 + 1960 143.73333 0.0036105788 0.00095257985 + 1980 145.2 0.0036693157 0.00096734041 + 2000 146.66667 0.0037279206 0.00098228262 + 2020 148.13333 0.0037863272 0.00099753272 + 2040 149.6 0.0038448977 0.0010129675 + 2060 151.06667 0.0039035631 0.0010289263 + 2080 152.53333 0.0039618021 0.001044226 + 2100 154 0.0040196981 0.001059823 + 2120 155.46667 0.0040776598 0.0010754207 + 2140 156.93333 0.0041356267 0.0010912489 + 2160 158.4 0.0041933707 0.0011068916 + 2180 159.86667 0.0042506844 0.001122462 + 2200 161.33333 0.0043076551 0.0011378276 + 2220 162.8 0.004364899 0.0011531367 + 2240 164.26667 0.0044223607 0.0011685928 + 2260 165.73333 0.0044790909 0.001183629 + 2280 167.2 0.0045350513 0.0011983147 + 2300 168.66667 0.0045910698 0.0012128941 + 2320 170.13333 0.0046473036 0.0012274902 + 2340 171.6 0.0047034572 0.0012420483 + 2360 173.06667 0.0047594904 0.001256434 + 2380 174.53333 0.0048154857 0.0012710526 + 2400 176 0.0048713579 0.0012854643 + 2420 177.46667 0.0049268461 0.0012999539 + 2440 178.93333 0.0049821065 0.0013141319 + 2460 180.4 0.0050376352 0.0013286044 + 2480 181.86667 0.0050932684 0.0013428647 + 2500 183.33333 0.0051487541 0.0013573039 + 2520 184.8 0.0052041856 0.001371655 + 2540 186.26667 0.005259265 0.0013858701 + 2560 187.73333 0.0053140412 0.0014000303 + 2580 189.2 0.0053687577 0.0014142597 + 2600 190.66667 0.0054226172 0.0014281564 + 2620 192.13333 0.0054756639 0.0014420369 + 2640 193.6 0.0055290419 0.0014559949 + 2660 195.06667 0.0055821088 0.0014698039 + 2680 196.53333 0.0056340694 0.0014837338 + 2700 198 0.0056859198 0.0014973779 + 2720 199.46667 0.0057376404 0.0015110075 + 2740 200.93333 0.0057882397 0.0015247587 + 2760 202.4 0.0058380714 0.0015376559 + 2780 203.86667 0.0058874524 0.0015511804 + 2800 205.33333 0.0059360376 0.0015643594 + 2820 206.8 0.0059840503 0.0015776406 + 2840 208.26667 0.0060315172 0.0015904895 + 2860 209.73333 0.0060778724 0.0016030297 + 2880 211.2 0.0061232681 0.0016153868 + 2900 212.66667 0.0061684129 0.0016276456 + 2920 214.13333 0.0062133058 0.0016395859 + 2940 215.6 0.0062576324 0.0016507189 + 2960 217.06667 0.0063013566 0.0016623583 + 2980 218.53333 0.0063443506 0.0016735007 + 3000 220 0.0063871542 0.001684583 + 3020 221.46667 0.006430519 0.001697154 + 3040 222.93333 0.0064740424 0.0017087524 + 3060 224.4 0.0065176616 0.0017189916 + 3080 225.86667 0.0065615555 0.0017301805 + 3100 227.33333 0.006605039 0.0017410152 + 3120 228.8 0.0066482973 0.0017517164 + 3140 230.26667 0.0066915406 0.0017619713 + 3160 231.73333 0.0067344437 0.0017722386 + 3180 233.2 0.006777227 0.0017824734 + 3200 234.66667 0.006819344 0.0017926386 + 3220 236.13333 0.0068607536 0.0018023968 + 3240 237.6 0.0069026957 0.0018127097 + 3260 239.06667 0.0069450313 0.0018236711 + 3280 240.53333 0.0069865151 0.0018341375 + 3300 242 0.0070275294 0.0018448641 + 3320 243.46667 0.0070688646 0.0018561596 + 3340 244.93333 0.0071092014 0.0018662927 + 3360 246.4 0.0071487936 0.0018770385 + 3380 247.86667 0.0071890814 0.001886802 + 3400 249.33333 0.0072281891 0.0018972625 + 3420 250.8 0.0072657267 0.0019062877 + 3440 252.26667 0.0073033651 0.0019160172 + 3460 253.73333 0.0073406213 0.0019254146 + 3480 255.2 0.0073773312 0.0019343899 + 3500 256.66667 0.0074135814 0.0019431867 + 3520 258.13333 0.0074488904 0.0019521168 + 3540 259.6 0.0074841693 0.0019611895 + 3560 261.06667 0.0075194817 0.0019697561 + 3580 262.53333 0.0075540131 0.0019782744 + 3600 264 0.0075880612 0.0019869585 + 3620 265.46667 0.0076217162 0.0019954264 + 3640 266.93333 0.0076541332 0.0020048511 + 3660 268.4 0.0076854774 0.0020121513 + 3680 269.86667 0.0077170032 0.002020407 + 3700 271.33333 0.0077479535 0.002028555 + 3720 272.8 0.0077778112 0.002035829 + 3740 274.26667 0.0078075791 0.0020445579 + 3760 275.73333 0.0078373125 0.002051243 + 3780 277.2 0.0078671935 0.0020596139 + 3800 278.66667 0.0078966016 0.0020667611 + 3820 280.13333 0.0079259829 0.0020737998 + 3840 281.6 0.0079561144 0.0020823896 + 3860 283.06667 0.0079856022 0.0020898018 + 3880 284.53333 0.0080155451 0.0020975877 + 3900 286 0.008045725 0.0021058637 + 3920 287.46667 0.00807515 0.0021132131 + 3940 288.93333 0.0081055524 0.0021220937 + 3960 290.4 0.0081357323 0.0021293745 + 3980 291.86667 0.0081660373 0.0021372148 + 4000 293.33333 0.0081969984 0.0021452255 + 4020 294.8 0.0082267987 0.0021525847 + 4040 296.26667 0.0082567948 0.0021608073 + 4060 297.73333 0.0082871434 0.0021682544 + 4080 299.2 0.0083173455 0.0021769568 + 4100 300.66667 0.0083480923 0.0021843095 + 4120 302.13333 0.008377833 0.0021919136 + 4140 303.6 0.0084065176 0.0022000503 + 4160 305.06667 0.0084359624 0.0022072124 + 4180 306.53333 0.0084657862 0.0022153288 + 4200 308 0.008494679 0.0022227735 + 4220 309.46667 0.008523307 0.002229996 + 4240 310.93333 0.008553561 0.0022382672 + 4260 312.4 0.0085842107 0.0022462238 + 4280 313.86667 0.0086124223 0.0022536478 + 4300 315.33333 0.0086404396 0.0022608951 + 4320 316.8 0.0086693991 0.0022683957 + 4340 318.26667 0.0086973954 0.0022764575 + 4360 319.73333 0.0087253957 0.0022829952 + 4380 321.2 0.0087529268 0.0022901779 + 4400 322.66667 0.0087798869 0.0022970351 + 4420 324.13333 0.0088070731 0.0023035923 + 4440 325.6 0.0088336854 0.0023108163 + 4460 327.06667 0.00886034 0.002317611 + 4480 328.53333 0.008886686 0.0023244292 + 4500 330 0.0089126796 0.0023323098 + 4520 331.46667 0.0089380439 0.002338006 + 4540 332.93333 0.0089625802 0.0023439698 + 4560 334.4 0.0089876608 0.0023508279 + 4580 335.86667 0.0090119764 0.0023567519 + 4600 337.33333 0.0090358053 0.0023630419 + 4620 338.8 0.0090597056 0.0023696207 + 4640 340.26667 0.0090827564 0.0023757413 + 4660 341.73333 0.0091057102 0.0023825055 + 4680 343.2 0.0091280804 0.0023880185 + 4700 344.66667 0.0091501664 0.0023938041 + 4720 346.13333 0.0091724992 0.0024006288 + 4740 347.6 0.0091940571 0.0024066505 + 4760 349.06667 0.0092145857 0.0024118199 + 4780 350.53333 0.0092353995 0.0024187452 + 4800 352 0.0092558703 0.0024235776 + 4820 353.46667 0.009275219 0.0024285703 + 4840 354.93333 0.0092944603 0.0024339815 + 4860 356.4 0.0093126366 0.0024385746 + 4880 357.86667 0.0093312838 0.0024434876 + 4900 359.33333 0.0093497163 0.0024488983 + 4920 360.8 0.009365989 0.0024527436 + 4940 362.26667 0.0093829249 0.0024572285 + 4960 363.73333 0.0093999951 0.0024620002 + 4980 365.2 0.0094162511 0.0024654432 + 5000 366.66667 0.009432966 0.0024696871 + 5020 368.13333 0.0094491728 0.0024752768 + 5040 369.6 0.0094654395 0.0024791774 + 5060 371.06667 0.0094822028 0.0024833783 + 5080 372.53333 0.0094987002 0.0024876159 + 5100 374 0.0095154669 0.0024916919 + 5120 375.46667 0.0095317268 0.0024971427 + 5140 376.93333 0.0095488298 0.0025012162 + 5160 378.4 0.0095659696 0.0025049341 + 5180 379.86667 0.0095824397 0.0025092752 + 5200 381.33333 0.0096000959 0.0025131409 + 5220 382.8 0.0096178056 0.0025171802 + 5240 384.26667 0.0096358075 0.0025217474 + 5260 385.73333 0.0096536841 0.0025259115 + 5280 387.2 0.0096720374 0.0025307756 + 5300 388.66667 0.0096903176 0.0025371145 + 5320 390.13333 0.0097081278 0.002540216 + 5340 391.6 0.0097268941 0.0025456853 + 5360 393.06667 0.009745217 0.0025499166 + 5380 394.53333 0.0097634815 0.0025546822 + 5400 396 0.0097813844 0.0025591351 + 5420 397.46667 0.0097989874 0.0025645654 + 5440 398.93333 0.0098165651 0.0025681155 + 5460 400.4 0.0098343876 0.0025724122 + 5480 401.86667 0.0098522329 0.0025783873 + 5500 403.33333 0.0098691009 0.0025818597 + 5520 404.8 0.0098860184 0.0025857495 + 5540 406.26667 0.0099028987 0.002590578 + 5560 407.73333 0.0099197309 0.0025942164 + 5580 409.2 0.0099359956 0.0025983095 + 5600 410.66667 0.0099524424 0.0026024035 + 5620 412.13333 0.0099690162 0.0026067584 + 5640 413.6 0.0099843964 0.002611251 + 5660 415.06667 0.010000092 0.0026151565 + 5680 416.53333 0.010015971 0.0026189738 + 5700 418 0.01003088 0.0026226851 + 5720 419.46667 0.010046448 0.0026266212 + 5740 420.93333 0.010061779 0.0026305773 + 5760 422.4 0.010077085 0.002634556 + 5780 423.86667 0.010092596 0.0026403454 + 5800 425.33333 0.010107214 0.0026431069 + 5820 426.8 0.010122323 0.0026467806 + 5840 428.26667 0.010136615 0.0026505801 + 5860 429.73333 0.0101514 0.0026545146 + 5880 431.2 0.010165938 0.0026575254 + 5900 432.66667 0.010180061 0.0026611852 + 5920 434.13333 0.010193978 0.0026651517 + 5940 435.6 0.010207399 0.0026700025 + 5960 437.06667 0.010221274 0.0026724013 + 5980 438.53333 0.0102342 0.002675843 + 6000 440 0.010246851 0.0026796139 + 6020 441.46667 0.010259615 0.0026826456 + 6040 442.93333 0.010271994 0.0026856149 + 6060 444.4 0.010284566 0.0026891263 + 6080 445.86667 0.01029697 0.0026934663 + 6100 447.33333 0.010297087 0.0026929648 + 6120 448.8 0.01026953 0.0026859415 + 6140 450.26667 0.010241322 0.0026788232 + 6160 451.73333 0.010201572 0.0026685955 + 6180 453.2 0.010167529 0.0026596809 + 6200 454.66667 0.010140751 0.0026523585 + 6220 456.13333 0.010096077 0.002641072 + 6240 457.6 0.010043217 0.0026282922 + 6260 459.06667 0.0099830892 0.0026127228 + 6280 460.53333 0.0099406642 0.0026021682 + 6300 462 0.0099151275 0.002595732 + 6320 463.46667 0.0098900642 0.0025891145 + 6340 464.93333 0.0098560891 0.0025805017 + 6360 466.4 0.0098293518 0.0025741231 + 6380 467.86667 0.0098089665 0.0025692332 + 6400 469.33333 0.0097886264 0.0025633005 + 6420 470.8 0.0097672621 0.0025580882 + 6440 472.26667 0.0097438543 0.0025530359 + 6460 473.73333 0.0097156792 0.0025441423 + 6480 475.2 0.0096824023 0.0025359007 + 6500 476.66667 0.0096556854 0.0025282404 + 6520 478.13333 0.0096245146 0.0025200185 + 6540 479.6 0.0095942888 0.0025112709 + 6560 481.06667 0.0095630005 0.0025029005 + 6580 482.53333 0.0095307546 0.0024945223 + 6600 484 0.0094979676 0.0024851442 + 6620 485.46667 0.0094678543 0.0024768078 + 6640 486.93333 0.009440454 0.0024694763 + 6660 488.4 0.0094144007 0.0024632333 + 6680 489.86667 0.0093906089 0.0024562358 + 6700 491.33333 0.0093653494 0.0024490631 + 6720 492.8 0.0093388466 0.0024421324 + 6740 494.26667 0.0093068273 0.0024334756 + 6760 495.73333 0.0092747153 0.0024247141 + 6780 497.2 0.0092468798 0.0024172005 + 6800 498.66667 0.0092160816 0.002409021 + 6820 500.13333 0.0091844109 0.0024010176 + 6840 501.6 0.0091543943 0.0023931861 + 6860 503.06667 0.0091225364 0.00238459 + 6880 504.53333 0.009091163 0.0023764251 + 6900 506 0.0090620145 0.0023688628 + 6920 507.46667 0.0090327696 0.0023610683 + 6940 508.93333 0.0090043995 0.0023537352 + 6960 510.4 0.0089749557 0.0023459457 + 6980 511.86667 0.0089447271 0.0023385936 + 7000 513.33333 0.0089161633 0.0023311311 + 7020 514.8 0.008888379 0.002323798 + 7040 516.26667 0.0088597051 0.0023162749 + 7060 517.73333 0.0088314196 0.0023094901 + 7080 519.2 0.0088032697 0.0023017143 + 7100 520.66667 0.0087764174 0.0022945937 + 7120 522.13333 0.0087493465 0.0022878231 + 7140 523.6 0.0087208106 0.0022805679 + 7160 525.06667 0.0086901023 0.0022726678 + 7180 526.53333 0.0086602781 0.0022649995 + 7200 528 0.0086338883 0.0022581858 + 7220 529.46667 0.0086086121 0.002252324 + 7240 530.93333 0.0085801758 0.0022441934 + 7260 532.4 0.0085495659 0.0022361561 + 7280 533.86667 0.0085199727 0.0022288965 + 7300 535.33333 0.0084891254 0.0022216958 + 7320 536.8 0.0084557275 0.0022130525 + 7340 538.26667 0.0084218841 0.002203592 + 7360 539.73333 0.0083899168 0.0021958184 + 7380 541.2 0.0083585487 0.002188024 + 7400 542.66667 0.0083279264 0.0021795695 + 7420 544.13333 0.0082956611 0.0021711337 + 7440 545.6 0.0082600396 0.0021620937 + 7460 547.06667 0.008222435 0.0021524246 + 7480 548.53333 0.0081847492 0.0021422603 + 7500 550 0.0081480769 0.0021324926 + 7520 551.46667 0.0081129495 0.0021237168 + 7540 552.93333 0.0080794573 0.0021154414 + 7560 554.4 0.0080465003 0.0021057182 + 7580 555.86667 0.0080134857 0.0020967731 + 7600 557.33333 0.0079807769 0.0020882759 + 7620 558.8 0.007949081 0.0020799016 + 7640 560.26667 0.0079178914 0.0020720038 + 7660 561.73333 0.0078871135 0.0020650346 + 7680 563.2 0.007856599 0.0020563039 + 7700 564.66667 0.0078260839 0.002048286 + 7720 566.13333 0.007796051 0.0020402506 + 7740 567.6 0.0077667325 0.0020324247 + 7760 569.06667 0.0077368975 0.0020242564 + 7780 570.53333 0.0077063146 0.002016025 + 7800 572 0.0076756813 0.0020076974 + 7820 573.46667 0.0076444658 0.0019992537 + 7840 574.93333 0.0076122527 0.0019912246 + 7860 576.4 0.00757938 0.0019824601 + 7880 577.86667 0.0075457657 0.0019739889 + 7900 579.33333 0.0075114496 0.0019644524 + 7920 580.8 0.0074775871 0.0019556077 + 7940 582.26667 0.0074449114 0.0019470595 + 7960 583.73333 0.0074125826 0.0019386798 + 7980 585.2 0.0073795946 0.0019298994 + 8000 586.66667 0.0073460046 0.0019208737 + 8020 588.13333 0.0073122744 0.0019120703 + 8040 589.6 0.0072783913 0.0019033047 + 8060 591.06667 0.0072440775 0.0018943414 + 8080 592.53333 0.0072092735 0.0018852102 + 8100 594 0.0071736521 0.0018758623 + 8120 595.46667 0.0071373132 0.0018664102 + 8140 596.93333 0.0071013244 0.0018569886 + 8160 598.4 0.0070657891 0.0018477343 + 8180 599.86667 0.0070299646 0.0018383955 + 8200 601.33333 0.0069940522 0.001829006 + 8220 602.8 0.0069586108 0.0018197189 + 8240 604.26667 0.0069231457 0.0018112586 + 8260 605.73333 0.0068871373 0.0018016096 + 8280 607.2 0.0068512951 0.0017928173 + 8300 608.66667 0.006816413 0.0017834399 + 8320 610.13333 0.0067820205 0.0017745017 + 8340 611.6 0.0067473828 0.0017654991 + 8360 613.06667 0.0067124905 0.0017569034 + 8380 614.53333 0.0066773905 0.0017474775 + 8400 616 0.0066417638 0.0017387333 + 8420 617.46667 0.0066057074 0.0017293058 + 8440 618.93333 0.0065700041 0.0017200093 + 8460 620.4 0.0065351174 0.0017110662 + 8480 621.86667 0.0065006001 0.0017017664 + 8500 623.33333 0.0064659553 0.0016926237 + 8520 624.8 0.0064314284 0.0016834464 + 8540 626.26667 0.0063972759 0.0016730222 + 8560 627.73333 0.006363104 0.0016535358 + 8580 629.2 0.0063283374 0.0016341308 + 8600 630.66667 0.0062929939 0.0016145833 + 8620 632.13333 0.0062575534 0.0015952196 + 8640 633.6 0.0062223967 0.0015767924 + 8660 635.06667 0.0061876077 0.0015584021 + 8680 636.53333 0.0061531388 0.0015432462 + 8700 638 0.0061189895 0.0015255547 + 8720 639.46667 0.0060849843 0.0015087078 + 8740 640.93333 0.0060508603 0.0014912511 + 8760 642.4 0.0060166368 0.0014741414 + 8780 643.86667 0.0059825217 0.0014570326 + 8800 645.33333 0.0059487275 0.0014404208 + 8820 646.8 0.005915195 0.001427214 + 8840 648.26667 0.0058815506 0.0014108717 + 8860 649.73333 0.0058475012 0.001394823 + 8880 651.2 0.005813175 0.0013791763 + 8900 652.66667 0.0057788055 0.0013635495 + 8920 654.13333 0.0057442301 0.0013485291 + 8940 655.6 0.0057092563 0.0013329993 + 8960 657.06667 0.0056742445 0.0013200488 + 8980 658.53333 0.0056395856 0.0013052312 + 9000 660 0.005604919 0.0012908181 + 9020 661.46667 0.0055697452 0.001276258 + 9040 662.93333 0.0055345006 0.0012617179 + 9060 664.4 0.0054999699 0.0012488732 + 9080 665.86667 0.0054658705 0.0012342743 + 9100 667.33333 0.0054312056 0.0012219265 + 9120 668.8 0.0053958845 0.0012069595 + 9140 670.26667 0.0053607107 0.0011946481 + 9160 671.73333 0.0053258562 0.0011805403 + 9180 673.2 0.005290634 0.0011685879 + 9200 674.66667 0.0052548527 0.0011548258 + 9220 676.13333 0.0052191394 0.0011431756 + 9240 677.6 0.0051838155 0.0011292222 + 9260 679.06667 0.0051486178 0.0011177695 + 9280 680.53333 0.0051136287 0.0011043218 + 9300 682 0.0050793517 0.001093456 + 9320 683.46667 0.0050458249 0.00108072 + 9340 684.93333 0.0050124909 0.0010699656 + 9360 686.4 0.0049790841 0.0010577503 + 9380 687.86667 0.0049458438 0.0010471846 + 9400 689.33333 0.0049128193 0.0010353066 + 9420 690.8 0.0048796878 0.0010250736 + 9440 692.26667 0.0048463678 0.0010133357 + 9460 693.73333 0.0048130621 0.0010034192 + 9480 695.2 0.0047797612 0.00099181501 + 9500 696.66667 0.0047463058 0.00098192704 + 9520 698.13333 0.0047129773 0.00097114316 + 9540 699.6 0.0046802695 0.0009614797 + 9560 701.06667 0.0046481303 0.00095001935 + 9580 702.53333 0.0046159995 0.00094018625 + 9600 704 0.0045836057 0.00093048866 + 9620 705.46667 0.0045513113 0.00092093431 + 9640 706.93333 0.0045195288 0.00091163732 + 9660 708.4 0.0044881214 0.00090108788 + 9680 709.86667 0.0044565522 0.00089178586 + 9700 711.33333 0.0044245471 0.00088289706 + 9720 712.8 0.0043923571 0.00087366447 + 9740 714.26667 0.0043603446 0.00086340815 + 9760 715.73333 0.0043285042 0.00085450195 + 9780 717.2 0.0042965444 0.00084545827 + 9800 718.66667 0.0042643896 0.00083689129 + 9820 720.13333 0.0042323768 0.00082818681 + 9840 721.6 0.0042008631 0.00081834996 + 9860 723.06667 0.0041697784 0.00081001308 + 9880 724.53333 0.0041387393 0.00080132405 + 9900 726 0.0041075523 0.00079289302 + 9920 727.46667 0.0040764684 0.00078371229 + 9940 728.93333 0.004045842 0.00077617702 + 9960 730.4 0.0040156553 0.00076786882 + 9980 731.86667 0.0039855818 0.00075942893 + 10000 733.33333 0.0039554481 0.0007511838 + 10020 734.8 0.0039255002 0.00074338609 + 10040 736.26667 0.0038961167 0.0007357845 + 10060 737.73333 0.0038673423 0.00072863577 + 10080 739.2 0.0038388258 0.00072101271 + 10100 740.66667 0.0038101889 0.00071325927 + 10120 742.13333 0.0037813579 0.00070577634 + 10140 743.6 0.0037524894 0.00069840857 + 10160 745.06667 0.0037236699 0.0006912217 + 10180 746.53333 0.0036948382 0.00068398999 + 10200 748 0.0036659574 0.0006765938 + 10220 749.46667 0.003637161 0.00066944812 + 10240 750.93333 0.0036086524 0.00066246958 + 10260 752.4 0.0035804876 0.00065555896 + 10280 753.86667 0.0035525249 0.00064877214 + 10300 755.33333 0.003524549 0.00064262835 + 10320 756.8 0.0034964925 0.0006359586 + 10340 758.26667 0.0034685139 0.00062899447 + 10360 759.73333 0.0034408225 0.00062253344 + 10380 761.2 0.0034134787 0.00061569541 + 10400 762.66667 0.0033863357 0.00061002091 + 10420 764.13333 0.0033591874 0.00060376799 + 10440 765.6 0.0033319865 0.00059696082 + 10460 767.06667 0.0033049023 0.00059041399 + 10480 768.53333 0.0032781346 0.00058417754 + 10500 770 0.0032516844 0.0005781413 + 10520 771.46667 0.0032253297 0.00057280542 + 10540 772.93333 0.0031988384 0.00056654214 + 10560 774.4 0.0031722162 0.00056022576 + 10580 775.86667 0.0031457039 0.0005547685 + 10600 777.33333 0.0031195399 0.00054891424 + 10620 778.8 0.003093753 0.00054282948 + 10640 780.26667 0.0030681782 0.0005378126 + 10660 781.73333 0.0030426412 0.00053187104 + 10680 783.2 0.0030171127 0.00052598426 + 10700 784.66667 0.0029917103 0.00052087104 + 10720 786.13333 0.0029665734 0.00051521228 + 10740 787.6 0.0029417486 0.00050965329 + 10760 789.06667 0.0029171964 0.000504914 + 10780 790.53333 0.0028928685 0.00049932491 + 10800 792 0.0028687686 0.00049451045 + 10820 793.46667 0.0028449566 0.00048905426 + 10840 794.93333 0.0028215175 0.00048442583 + 10860 796.4 0.0027985141 0.00047942674 + 10880 797.86667 0.0027759233 0.00047495434 + 10900 799.33333 0.0027536322 0.00046989793 + 10920 800.8 0.0027315039 0.00046490714 + 10940 802.26667 0.0027094846 0.00046064051 + 10960 803.73333 0.0026876651 0.00045602046 + 10980 805.2 0.002666198 0.00045168389 + 11000 806.66667 0.0026451664 0.00044707481 + 11020 808.13333 0.0026244819 0.00044301025 + 11040 809.6 0.0026039186 0.00043882304 + 11060 811.06667 0.0025833111 0.00043484293 + 11080 812.53333 0.0025627062 0.0004302122 + 11100 814 0.0025423309 0.00042635689 + 11120 815.46667 0.0025223953 0.00042237706 + 11140 816.93333 0.002502881 0.00041811928 + 11160 818.4 0.002483558 0.00041427004 + 11180 819.86667 0.0024642 0.00041016131 + 11200 821.33333 0.002444785 0.00040680079 + 11220 822.8 0.0024255271 0.00040255216 + 11240 824.26667 0.0024066719 0.0003989581 + 11260 825.73333 0.0023882699 0.00039531616 + 11280 827.2 0.0023701608 0.00039149232 + 11300 828.66667 0.0023521641 0.00038812202 + 11320 830.13333 0.0023342875 0.00038432826 + 11340 831.6 0.0023167154 0.00038122373 + 11360 833.06667 0.0022996036 0.00037780451 + 11380 834.53333 0.0022829198 0.00037461979 + 11400 836 0.0022664799 0.00037151931 + 11420 837.46667 0.0022501566 0.00036807932 + 11440 838.93333 0.0022340312 0.00036508287 + 11460 840.4 0.0022183033 0.00036190422 + 11480 841.86667 0.0022030817 0.00035916212 + 11500 843.33333 0.0021882572 0.00035628429 + 11520 844.8 0.0021735959 0.00035351859 + 11540 846.26667 0.0021589553 0.00035088484 + 11560 847.73333 0.002144383 0.00034780033 + 11580 849.2 0.0021300334 0.00034517904 + 11600 850.66667 0.0021160134 0.00034238069 + 11620 852.13333 0.0021022646 0.00034000514 + 11640 853.6 0.0020886207 0.00033719824 + 11660 855.06667 0.0020749807 0.00033475998 + 11680 856.53333 0.0020613877 0.0003323936 + 11700 858 0.002047954 0.0003295216 + 11720 859.46667 0.0020347589 0.00032713228 + 11740 860.93333 0.0020218117 0.00032474079 + 11760 862.4 0.0020091095 0.00032239213 + 11780 863.86667 0.0019966993 0.00031989799 + 11800 865.33333 0.0019846286 0.00031771663 + 11820 866.8 0.0019728573 0.0003157215 + 11840 868.26667 0.0019612776 0.00031355627 + 11860 869.73333 0.0019498221 0.00031127816 + 11880 871.2 0.0019385448 0.00030917103 + 11900 872.66667 0.0019275959 0.00030717234 + 11920 874.13333 0.0019170876 0.00030529115 + 11940 875.6 0.0019069791 0.00030345863 + 11960 877.06667 0.0018971139 0.00030170128 + 11980 878.53333 0.0018873555 0.0003001492 + 12000 880 0.0018776861 0.000298125 + 12020 881.46667 0.0018681863 0.0002963477 + 12040 882.93333 0.0018589294 0.00029463961 + 12060 884.4 0.0018499098 0.00029287916 + 12080 885.86667 0.0018410776 0.00029127697 + 12100 887.33333 0.0018324309 0.00028984289 + 12120 888.8 0.0018240594 0.00028840492 + 12140 890.26667 0.0018160961 0.00028702304 + 12160 891.73333 0.0018086145 0.00028549007 + 12180 893.2 0.0018015575 0.00028402955 + 12200 894.66667 0.0017947657 0.00028282399 + 12220 896.13333 0.0017880903 0.00028154717 + 12240 897.6 0.0017814942 0.00028017139 + 12260 899.06667 0.0017750529 0.00027900454 + 12280 900.53333 0.0017688698 0.00027808648 + 12300 902 0.0017629899 0.00027685309 + 12320 903.46667 0.0017573722 0.00027580637 + 12340 904.93333 0.0017519364 0.00027485838 + 12360 906.4 0.0017466397 0.00027394007 + 12380 907.86667 0.001741517 0.00027291856 + 12400 909.33333 0.0017366544 0.00027203238 + 12420 910.8 0.0017321325 0.00027110163 + 12440 912.26667 0.0017279827 0.00027027898 + 12460 913.73333 0.0017241867 0.00026956597 + 12480 915.2 0.0017207028 0.00026893832 + 12500 916.66667 0.0017174942 0.0002684279 + 12520 918.13333 0.0017145473 0.00026791943 + 12540 919.6 0.0017118647 0.00026744382 + 12560 921.06667 0.0017094489 0.00026685887 + 12580 922.53333 0.0017072871 0.00026638424 + 12600 924 0.0017053649 0.00026597657 + 12620 925.46667 0.0017036738 0.00026563478 + 12640 926.93333 0.0017022202 0.00026540665 + 12660 928.4 0.0017010329 0.00026520386 + 12680 929.86667 0.0017001522 0.00026507626 + 12700 931.33333 0.0016995942 0.00026477717 + 12720 932.8 0.0016993235 0.0002646703 + 12740 934.26667 0.0016992705 0.00026461169 + 12760 935.73333 0.0016993774 0.00026456725 + 12780 937.2 0.0016996306 0.00026455988 + 12800 938.66667 0.001700059 0.0002646213 + 12820 940.13333 0.0017007039 0.00026482076 + 12840 941.6 0.0017015791 0.00026487824 + 12860 943.06667 0.0017026482 0.00026493272 + 12880 944.53333 0.0017038391 0.00026510172 + 12900 946 0.0017050887 0.00026529547 + 12920 947.46667 0.0017063854 0.00026551572 + 12940 948.93333 0.001707774 0.00026599737 + 12960 950.4 0.0017093344 0.00026611126 + 12980 951.86667 0.0017111446 0.00026624827 + 13000 953.33333 0.0017132414 0.00026655284 + 13020 954.8 0.0017156029 0.00026692012 + 13040 956.26667 0.0017181728 0.00026731624 + 13060 957.73333 0.001720904 0.00026783066 + 13080 959.2 0.0017237902 0.00026836703 + 13100 960.66667 0.0017268644 0.0002689476 + 13120 962.13333 0.0017301659 0.0002694946 + 13140 963.6 0.0017336967 0.00026985524 + 13160 965.06667 0.0017374153 0.00027047141 + 13180 966.53333 0.0017412627 0.00027116583 + 13200 968 0.0017451982 0.00027186788 + 13220 969.46667 0.0017492157 0.00027241441 + 13240 970.93333 0.0017533345 0.00027303315 + 13260 972.4 0.001757579 0.00027374363 + 13280 973.86667 0.0017619627 0.00027451986 + 13300 975.33333 0.0017664863 0.00027525007 + 13320 976.8 0.0017711394 0.00027591661 + 13340 978.26667 0.0017759051 0.00027671531 + 13360 979.73333 0.0017807725 0.00027754179 + 13380 981.2 0.0017857381 0.00027848699 + 13400 982.66667 0.0017907994 0.00027931598 + 13420 984.13333 0.0017959473 0.00028027815 + 13440 985.6 0.0018011601 0.00028113792 + 13460 987.06667 0.0018064143 0.00028211623 + 13480 988.53333 0.0018117101 0.00028327908 + 13500 990 0.0018170864 0.00028409026 + 13520 991.46667 0.0018225918 0.00028501376 + 13540 992.93333 0.0018282476 0.00028596031 + 13560 994.4 0.0018340585 0.00028716447 + 13580 995.86667 0.0018400197 0.00028805463 + 13600 997.33333 0.0018461017 0.00028921664 + 13620 998.8 0.0018522484 0.00029037184 + 13640 1000.2667 0.0018583764 0.00029143019 + 13660 1001.7333 0.001864373 0.00029269198 + 13680 1003.2 0.0018701272 0.0002936223 + 13700 1004.6667 0.001875598 0.00029471055 + 13720 1006.1333 0.0018808354 0.00029567952 + 13740 1007.6 0.0018859376 0.00029685882 + 13760 1009.0667 0.0018910107 0.00029796198 + 13780 1010.5333 0.0018961401 0.00029897911 + 13800 1012 0.0019013893 0.0002998773 + 13820 1013.4667 0.0019068286 0.00030092291 + 13840 1014.9333 0.0019125242 0.00030190868 + 13860 1016.4 0.0019185061 0.00030309941 + 13880 1017.8667 0.001924749 0.00030441051 + 13900 1019.3333 0.0019311778 0.00030560739 + 13920 1020.8 0.001937711 0.00030711748 + 13940 1022.2667 0.0019442933 0.00030842988 + 13960 1023.7333 0.0019508956 0.00030970219 + 13980 1025.2 0.0019575153 0.00031088886 + 14000 1026.6667 0.0019641693 0.00031199334 + 14020 1028.1333 0.0019708823 0.00031333167 + 14040 1029.6 0.0019776662 0.0003147189 + 14060 1031.0667 0.0019845097 0.0003161484 + 14080 1032.5333 0.0019913915 0.00031776661 + 14100 1034 0.0019983071 0.00031912667 + 14120 1035.4667 0.0020052807 0.00032037968 + 14140 1036.9333 0.0020123438 0.00032176152 + 14160 1038.4 0.002019523 0.00032328697 + 14180 1039.8667 0.0020268687 0.00032480224 + 14200 1041.3333 0.0020344454 0.0003263506 + 14220 1042.8 0.0020422702 0.00032803708 + 14240 1044.2667 0.0020503074 0.00032950555 + 14260 1045.7333 0.0020584954 0.00033107602 + 14280 1047.2 0.0020667453 0.00033272838 + 14300 1048.6667 0.0020749518 0.00033440292 + 14320 1050.1333 0.0020830298 0.00033616301 + 14340 1051.6 0.0020909561 0.00033777436 + 14360 1053.0667 0.002098763 0.00033939304 + 14380 1054.5333 0.0021064571 0.00034108867 + 14400 1056 0.0021139812 0.00034279091 + 14420 1057.4667 0.0021212743 0.00034442447 + 14440 1058.9333 0.0021283312 0.00034608006 + 14460 1060.4 0.0021351913 0.00034766535 + 14480 1061.8667 0.0021418558 0.00034931633 + 14500 1063.3333 0.0021482781 0.00035065187 + 14520 1064.8 0.0021544661 0.00035206483 + 14540 1066.2667 0.0021605274 0.00035349517 + 14560 1067.7333 0.0021666138 0.00035497387 + 14580 1069.2 0.002172775 0.00035650749 + 14600 1070.6667 0.0021789434 0.00035816361 + 14620 1072.1333 0.0021850567 0.00035981347 + 14640 1073.6 0.0021911017 0.00036119002 + 14660 1075.0667 0.0021970459 0.00036263527 + 14680 1076.5333 0.002202891 0.00036408979 + 14700 1078 0.0022086678 0.00036558706 + 14720 1079.4667 0.0022143659 0.00036708363 + 14740 1080.9333 0.0022200095 0.00036872316 + 14760 1082.4 0.0022256795 0.00037031852 + 14780 1083.8667 0.0022314598 0.00037172104 + 14800 1085.3333 0.0022373988 0.00037326473 + 14820 1086.8 0.0022435042 0.00037481567 + 14840 1088.2667 0.0022497418 0.0003767171 + 14860 1089.7333 0.0022560684 0.00037860978 + 14880 1091.2 0.002262451 0.00038015024 + 14900 1092.6667 0.0022688473 0.00038171512 + 14920 1094.1333 0.0022751666 0.00038333305 + 14940 1095.6 0.0022812118 0.00038546448 + 14960 1097.0667 0.0022867513 0.00038693328 + 14980 1098.5333 0.0022917745 0.00038844788 + 15000 1100 0.002296287 0.00038988563 + 15020 1101.4667 0.0022999653 0.00039138878 + 15040 1102.9333 0.0023028622 0.00039244167 + 15060 1104.4 0.002305798 0.00039349216 + 15080 1105.8667 0.0023089263 0.00039463979 + 15100 1107.3333 0.0023120599 0.00039582741 + 15120 1108.8 0.0023154124 0.00039746408 + 15140 1110.2667 0.0023192069 0.00039877981 + 15160 1111.7333 0.0023234403 0.00040024924 + 15180 1113.2 0.0023275332 0.00040194985 + 15200 1114.6667 0.0023309379 0.00040319063 + 15220 1116.1333 0.0023333104 0.0004046024 + 15240 1117.6 0.0023350271 0.00040564766 + 15260 1119.0667 0.0023370916 0.00040733425 + 15280 1120.5333 0.0023395929 0.00040838933 + 15300 1122 0.0023424998 0.00040987095 + 15320 1123.4667 0.0023453536 0.00041107287 + 15340 1124.9333 0.0023473165 0.00041242318 + 15360 1126.4 0.0023477134 0.00041322951 + 15380 1127.8667 0.0023491753 0.0004146031 + 15400 1129.3333 0.0023509302 0.00041566144 + 15420 1130.8 0.0023529326 0.00041714975 + 15440 1132.2667 0.0023554779 0.00041837505 + 15460 1133.7333 0.0023580661 0.00042017965 + 15480 1135.2 0.0023607312 0.0004213224 + 15500 1136.6667 0.0023635957 0.00042300666 + 15520 1138.1333 0.0023666602 0.00042436098 + 15540 1139.6 0.0023691001 0.0004260457 + 15560 1141.0667 0.0023700594 0.00042714685 + 15580 1142.5333 0.0023705741 0.00042853206 + 15600 1144 0.0023711825 0.00042951675 + 15620 1145.4667 0.002371987 0.00043109076 + 15640 1146.9333 0.0023732281 0.00043221551 + 15660 1148.4 0.0023749382 0.00043370865 + 15680 1149.8667 0.0023770404 0.00043490458 + 15700 1151.3333 0.0023793818 0.0004365297 + 15720 1152.8 0.0023816701 0.00043819097 + 15740 1154.2667 0.0023836808 0.00043980236 + 15760 1155.7333 0.0023856065 0.00044146758 + 15780 1157.2 0.0023876705 0.0004433163 + 15800 1158.6667 0.0023898905 0.00044465376 + 15820 1160.1333 0.0023918799 0.00044645614 + 15840 1161.6 0.0023914238 0.00044759356 + 15860 1163.0667 0.0023885514 0.00044839265 + 15880 1164.5333 0.0023867062 0.00044939387 + 15900 1166 0.0023853424 0.00045041476 + 15920 1167.4667 0.0023837839 0.00045152066 + 15940 1168.9333 0.0023823865 0.00045222801 + 15960 1170.4 0.0023800327 0.00045327302 + 15980 1171.8667 0.0023735917 0.00045357981 + 16000 1173.3333 0.0023643861 0.00045337685 + 16020 1174.8 0.0023565577 0.00045352436 + 16040 1176.2667 0.0023484436 0.00045344895 + 16060 1177.7333 0.0023408376 0.00045346696 + 16080 1179.2 0.0023326737 0.00045286966 + 16100 1180.6667 0.0023236531 0.00045261832 + 16120 1182.1333 0.0023169178 0.00045293394 + 16140 1183.6 0.0023111828 0.00045311831 + 16160 1185.0667 0.0023064172 0.00045378709 + 16180 1186.5333 0.002302184 0.00045455946 + 16200 1188 0.0022983621 0.00045539262 + 16220 1189.4667 0.0022953512 0.00045591645 + 16240 1190.9333 0.0022929801 0.00045712856 + 16260 1192.4 0.0022909009 0.00045847159 + 16280 1193.8667 0.0022885525 0.00045961196 + 16300 1195.3333 0.0022855688 0.00046061347 + 16320 1196.8 0.002282828 0.00046188788 + 16340 1198.2667 0.0022802183 0.00046302244 + 16360 1199.7333 0.0022773774 0.00046375719 + 16380 1201.2 0.0022731903 0.00046492183 + 16400 1202.6667 0.0022645201 0.00046516447 + 16420 1204.1333 0.0022568251 0.00046542882 + 16440 1205.6 0.0022422695 0.00046437586 + 16460 1207.0667 0.0022155713 0.00046051887 + 16480 1208.5333 0.0022035759 0.00046001297 + 16500 1210 0.002190894 0.00045893493 + 16520 1211.4667 0.0021802322 0.00045942457 + 16540 1212.9333 0.0021704133 0.000459471 + 16560 1214.4 0.0021615234 0.00045918488 + 16580 1215.8667 0.0021529915 0.00045936006 + 16600 1217.3333 0.0021451373 0.00045959338 + 16620 1218.8 0.0021383906 0.0004600505 + 16640 1220.2667 0.0021325315 0.00046005064 + 16660 1221.7333 0.0021277429 0.00046108228 + 16680 1223.2 0.0021237755 0.00046243368 + 16700 1224.6667 0.0021203172 0.00046394738 + 16720 1226.1333 0.0021172137 0.00046532716 + 16740 1227.6 0.0021142084 0.00046719106 + 16760 1229.0667 0.0021110689 0.00046854799 + 16780 1230.5333 0.0021077864 0.00046991776 + 16800 1232 0.0021045002 0.00047183286 + 16820 1233.4667 0.0021013226 0.00047317989 + 16840 1234.9333 0.002098386 0.0004747552 + 16860 1236.4 0.0020957505 0.00047738008 + 16880 1237.8667 0.0020931882 0.0004792455 + 16900 1239.3333 0.0020905705 0.00048104549 + 16920 1240.8 0.0020878895 0.00048403265 + 16940 1242.2667 0.0020853857 0.00048573735 + 16960 1243.7333 0.0020831358 0.00048728108 + 16980 1245.2 0.0020808323 0.00048952128 + 17000 1246.6667 0.0020784817 0.00049099168 + 17020 1248.1333 0.0020761732 0.00049278614 + 17040 1249.6 0.0020739063 0.00049556886 + 17060 1251.0667 0.0020717239 0.00049826766 + 17080 1252.5333 0.0020697361 0.00050040771 + 17100 1254 0.0020679208 0.00050266159 + 17120 1255.4667 0.0020661569 0.00050465637 + 17140 1256.9333 0.0020645102 0.00050644859 + 17160 1258.4 0.002063175 0.00050945115 + 17180 1259.8667 0.0020620744 0.00051135072 + 17200 1261.3333 0.0020578831 0.00051271416 + 17220 1262.8 0.002036801 0.00051070868 + 17240 1264.2667 0.0020246474 0.0005105671 + 17260 1265.7333 0.0020154083 0.00051056266 + 17280 1267.2 0.0020081398 0.00051203914 + 17300 1268.6667 0.0020033592 0.00051368703 + 17320 1270.1333 0.0019993325 0.00051565203 + 17340 1271.6 0.0019965177 0.00051918806 + 17360 1273.0667 0.0019938276 0.000522221 + 17380 1274.5333 0.0019914867 0.00052433401 + 17400 1276 0.0019892544 0.0005278718 + 17420 1277.4667 0.0019871107 0.00052787286 + 17440 1278.9333 0.0019850499 0.00052722809 + 17460 1280.4 0.0019830428 0.0005263569 + 17480 1281.8667 0.0019811987 0.00052588328 + 17500 1283.3333 0.0019795831 0.00052534586 + 17520 1284.8 0.0019781827 0.00052537295 + 17540 1286.2667 0.0019770664 0.00052509105 + 17560 1287.7333 0.0019762397 0.00052445472 + 17580 1289.2 0.0019755625 0.0005240242 + 17600 1290.6667 0.001974964 0.00052397078 + 17620 1292.1333 0.0019744966 0.00052447005 + 17640 1293.6 0.0019741078 0.00052446447 + 17660 1295.0667 0.0019735916 0.0005241986 + 17680 1296.5333 0.001972809 0.00052362297 + 17700 1298 0.0019718021 0.00052322362 + 17720 1299.4667 0.0019707205 0.00052316488 + 17740 1300.9333 0.0019696972 0.00052280952 + 17760 1302.4 0.0019687912 0.00052267588 + 17780 1303.8667 0.0019679901 0.00052231283 + 17800 1305.3333 0.0019672622 0.00052253006 + 17820 1306.8 0.0019665862 0.00052301876 + 17840 1308.2667 0.0019659299 0.00052301364 + 17860 1309.7333 0.00196528 0.0005229424 + 17880 1311.2 0.0019646495 0.00052264866 + 17900 1312.6667 0.0019640476 0.00052292066 + 17920 1314.1333 0.0019634587 0.0005229915 + 17940 1315.6 0.0019628594 0.00052284877 + 17960 1317.0667 0.0019622352 0.00052292872 + 17980 1318.5333 0.0019612399 0.00052337341 + 18000 1320 0.0019519628 0.00052094399 + 18020 1321.4667 0.0019343509 0.00051533063 + 18040 1322.9333 0.0019199585 0.00051174103 + 18060 1324.4 0.001905945 0.00050822167 + 18080 1325.8667 0.0018954044 0.00050571386 + 18100 1327.3333 0.0018867099 0.0005045138 + 18120 1328.8 0.0018790423 0.00050281498 + 18140 1330.2667 0.0018724677 0.00050092806 + 18160 1331.7333 0.0018669293 0.00049977801 + 18180 1333.2 0.0018621946 0.0004988236 + 18200 1334.6667 0.0018581668 0.00049860903 + 18220 1336.1333 0.0018546088 0.00049734989 + 18240 1337.6 0.001851507 0.00049612125 + 18260 1339.0667 0.0018488437 0.00049539768 + 18280 1340.5333 0.0018464974 0.00049462331 + 18300 1342 0.0018441554 0.00049419987 + 18320 1343.4667 0.0018418357 0.00049359519 + 18340 1344.9333 0.0018400699 0.00049361929 + 18360 1346.4 0.0018391163 0.0004934397 + 18380 1347.8667 0.0018386451 0.00049401695 + 18400 1349.3333 0.0018382434 0.00049404913 + 18420 1350.8 0.0018377762 0.00049284789 + 18440 1352.2667 0.0018373163 0.00049253988 + 18460 1353.7333 0.0018368769 0.00049170154 + 18480 1355.2 0.00183642 0.00049134218 + 18500 1356.6667 0.0018359651 0.00049049622 + 18520 1358.1333 0.0018355476 0.00049018604 + 18540 1359.6 0.0018351502 0.00049009857 + 18560 1361.0667 0.0018347415 0.00049034975 + 18580 1362.5333 0.0018343456 0.00048962734 + 18600 1364 0.0018340032 0.00048910267 + 18620 1365.4667 0.0018337131 0.000489678 + 18640 1366.9333 0.0018334434 0.00048942363 + 18660 1368.4 0.0018331908 0.00048883791 + 18680 1369.8667 0.0018330003 0.00048842189 + 18700 1371.3333 0.0018328613 0.00048778042 + 18720 1372.8 0.0018326423 0.0004879605 + 18740 1374.2667 0.0018322085 0.00048760414 + 18760 1375.7333 0.0018316466 0.00048749865 + 18780 1377.2 0.0018311569 0.00048717362 + 18800 1378.6667 0.0018307322 0.0004871375 + 18820 1380.1333 0.0018303267 0.00048680704 + 18840 1381.6 0.0018299711 0.00048676556 + 18860 1383.0667 0.0018296776 0.00048663795 + 18880 1384.5333 0.0018294387 0.00048659964 + 18900 1386 0.0018292809 0.00048698663 + 18920 1387.4667 0.0018292225 0.00048709797 + 18940 1388.9333 0.0018292283 0.0004870647 + 18960 1390.4 0.0018292259 0.00048674819 + 18980 1391.8667 0.0018291569 0.00048679582 + 19000 1393.3333 0.0018290098 0.00048689638 + 19020 1394.8 0.001828716 0.00048714893 + 19040 1396.2667 0.0018281487 0.00048793626 + 19060 1397.7333 0.0018274368 0.00048766312 + 19080 1399.2 0.0018267859 0.00048800122 + 19100 1400.6667 0.0018262357 0.00048767989 + 19120 1402.1333 0.001825769 0.0004870923 + 19140 1403.6 0.001825325 0.00048705214 + 19160 1405.0667 0.0018249161 0.00048807286 + 19180 1406.5333 0.0018245622 0.0004872987 + 19200 1408 0.001824239 0.00048742747 + 19220 1409.4667 0.0018239467 0.00048750738 + 19240 1410.9333 0.0018230912 0.00048779822 + 19260 1412.4 0.0018134463 0.00048497862 + 19280 1413.8667 0.0018021878 0.00048230785 + 19300 1415.3333 0.0017955735 0.00048083973 + 19320 1416.8 0.0017872753 0.0004788259 + 19340 1418.2667 0.0017779883 0.00047646403 + 19360 1419.7333 0.0017738211 0.00047574559 + 19380 1421.2 0.0017704561 0.00047501448 + 19400 1422.6667 0.0017677224 0.00047433091 + 19420 1424.1333 0.0017653706 0.00047260445 + 19440 1425.6 0.0017632679 0.00047170106 + 19460 1427.0667 0.0017613642 0.00047105927 + 19480 1428.5333 0.001759646 0.00047082774 + 19500 1430 0.001758063 0.00047009269 + 19520 1431.4667 0.0017566191 0.00046954867 + 19540 1432.9333 0.0017551775 0.00046892643 + 19560 1434.4 0.0017536259 0.00046842898 + 19580 1435.8667 0.0017521006 0.00046822248 + 19600 1437.3333 0.0017508378 0.00046758045 + 19620 1438.8 0.0017499266 0.0004680761 + 19640 1440.2667 0.0017492698 0.00046815863 + 19660 1441.7333 0.0017486531 0.00046811847 + 19680 1443.2 0.0017479735 0.00046864003 + 19700 1444.6667 0.0017472425 0.00046795012 + 19720 1446.1333 0.0017465091 0.0004669531 + 19740 1447.6 0.0017458236 0.00046666543 + 19760 1449.0667 0.0017452108 0.00046610386 + 19780 1450.5333 0.0017446777 0.00046578676 + 19800 1452 0.0017442315 0.00046559966 + 19820 1453.4667 0.0017438755 0.00046570962 + 19840 1454.9333 0.0017435917 0.00046591684 + 19860 1456.4 0.0017433538 0.00046605781 + 19880 1457.8667 0.0017431368 0.0004662092 + 19900 1459.3333 0.0017429113 0.00046639344 + 19920 1460.8 0.0017426466 0.00046609654 + 19940 1462.2667 0.0017423307 0.00046558461 + 19960 1463.7333 0.0017419767 0.00046538275 + 19980 1465.2 0.0017416057 0.00046473626 + 20000 1466.6667 0.0017412248 0.00046427697 + 20020 1468.1333 0.0017408365 0.00046360441 + 20040 1469.6 0.0017404537 0.00046250116 + 20060 1471.0667 0.0017400878 0.00046219676 + 20080 1472.5333 0.0017397348 0.0004620366 + 20100 1474 0.0017393906 0.00046142035 + 20120 1475.4667 0.0017390634 0.00046119888 + 20140 1476.9333 0.0017387599 0.00046114118 + 20160 1478.4 0.0017384654 0.00046119273 + 20180 1479.8667 0.0017381599 0.00046112037 + 20200 1481.3333 0.001737838 0.00046085119 + 20220 1482.8 0.0017374971 0.00046088054 + 20240 1484.2667 0.0017371388 0.00046097027 + 20260 1485.7333 0.0017368201 0.00046112449 + 20280 1487.2 0.0017365948 0.00046064697 + 20300 1488.6667 0.0017364148 0.00046068874 + 20320 1490.1333 0.001736224 0.00046068502 + 20340 1491.6 0.0017360297 0.00046057861 + 20360 1493.0667 0.0017358482 0.00046044137 + 20380 1494.5333 0.0017356781 0.00046043159 + 20400 1496 0.0017355222 0.00046062752 + 20420 1497.4667 0.0017353902 0.00046067799 + 20440 1498.9333 0.0017352915 0.00046071384 + 20460 1500.4 0.0017352299 0.00046111809 + 20480 1501.8667 0.0017352025 0.0004613299 + 20500 1503.3333 0.0017352027 0.00046183541 + 20520 1504.8 0.0017352278 0.00046106542 + 20540 1506.2667 0.0017352815 0.00046149717 + 20560 1507.7333 0.0017353649 0.00046105371 + 20580 1509.2 0.0017354697 0.00046104238 + 20600 1510.6667 0.0017355805 0.00046116932 + 20620 1512.1333 0.001735681 0.00046162233 + 20640 1513.6 0.001735758 0.00046178245 + 20660 1515.0667 0.0017358047 0.00046196886 + 20680 1516.5333 0.0017358199 0.00046215457 + 20700 1518 0.0017358084 0.00046228161 + 20720 1519.4667 0.0017357806 0.00046261955 + 20740 1520.9333 0.0017357486 0.00046271037 + 20760 1522.4 0.0017357257 0.00046257919 + 20780 1523.8667 0.0017357263 0.00046250064 + 20800 1525.3333 0.0017357658 0.00046146349 + 20820 1526.8 0.0017358584 0.00046138905 + 20840 1528.2667 0.0017360144 0.00046135266 + 20860 1529.7333 0.0017362378 0.00046136088 + 20880 1531.2 0.0017365251 0.00046203214 + 20900 1532.6667 0.0017368656 0.00046240805 + 20920 1534.1333 0.0017372463 0.00046245586 + 20940 1535.6 0.0017376552 0.00046233017 + 20960 1537.0667 0.0017380838 0.00046211905 + 20980 1538.5333 0.0017385273 0.00046221175 + 21000 1540 0.0017389813 0.0004623322 + 21020 1541.4667 0.0017394408 0.00046248895 + 21040 1542.9333 0.0017399011 0.00046262683 + 21060 1544.4 0.0017403582 0.0004628631 + 21080 1545.8667 0.0017408086 0.00046287413 + 21100 1547.3333 0.0017412486 0.00046253863 + 21120 1548.8 0.0017416739 0.00046239188 + 21140 1550.2667 0.0017420824 0.00046252093 + 21160 1551.7333 0.0017424775 0.00046243663 + 21180 1553.2 0.0017428687 0.00046231674 + 21200 1554.6667 0.0017432678 0.00046228047 + 21220 1556.1333 0.0017436835 0.00046205345 + 21240 1557.6 0.0017441181 0.00046191794 + 21260 1559.0667 0.001744567 0.00046187817 + 21280 1560.5333 0.00174502 0.00046195933 + 21300 1562 0.0017454629 0.00046207568 + 21320 1563.4667 0.0017458791 0.00046237686 + 21340 1564.9333 0.0017462532 0.00046251185 + 21360 1566.4 0.00174658 0.00046256338 + 21380 1567.8667 0.0017468761 0.00046258103 + 21400 1569.3333 0.0017471787 0.00046203359 + 21420 1570.8 0.0017475092 0.00046236915 + 21440 1572.2667 0.0017478285 0.00046240886 + 21460 1573.7333 0.0017480488 0.00046268024 + 21480 1575.2 0.0017481357 0.00046249851 + 21500 1576.6667 0.0017481758 0.00046252177 + 21520 1578.1333 0.0017482237 0.00046224255 + 21540 1579.6 0.0017482326 0.00046244066 + 21560 1581.0667 0.0017481857 0.0004626825 + 21580 1582.5333 0.0017481066 0.00046272441 + 21600 1584 0.0017480121 0.00046281669 + 21620 1585.4667 0.0017479031 0.0004630027 + 21640 1586.9333 0.0017477655 0.00046237554 + 21660 1588.4 0.0017475794 0.00046236536 + 21680 1589.8667 0.0017473246 0.00046234947 + 21700 1591.3333 0.0017469863 0.00046229056 + 21720 1592.8 0.0017465596 0.00046226293 + 21740 1594.2667 0.0017460487 0.00046221488 + 21760 1595.7333 0.0017454604 0.00046228835 + 21780 1597.2 0.0017447972 0.00046224033 + 21800 1598.6667 0.0017440567 0.00046196921 + 21820 1600.1333 0.0017432373 0.00046193024 + 21840 1601.6 0.0017423442 0.00046190113 + 21860 1603.0667 0.0017413885 0.00046182645 + 21880 1604.5333 0.0017403804 0.00046153595 + 21900 1606 0.0017393239 0.00046141594 + 21920 1607.4667 0.0017382204 0.00046059163 + 21940 1608.9333 0.0017370711 0.00046011476 + 21960 1610.4 0.0017358772 0.00045995874 + 21980 1611.8667 0.001734638 0.00045946276 + 22000 1613.3333 0.0017333523 0.00045909152 + 22020 1614.8 0.0017320214 0.00045871657 + 22040 1616.2667 0.0017306506 0.00045875126 + 22060 1617.7333 0.001729244 0.00045851969 + 22080 1619.2 0.0017277891 0.00045815 + 22100 1620.6667 0.0017262472 0.00045800503 + 22120 1622.1333 0.0017245557 0.00045722613 + 22140 1623.6 0.0017226312 0.00045612428 + 22160 1625.0667 0.0017203846 0.00045558148 + 22180 1626.5333 0.0017177538 0.00045493102 + 22200 1628 0.0017147219 0.00045354235 + 22220 1629.4667 0.0017113235 0.00045252377 + 22240 1630.9333 0.0017076396 0.00045148679 + 22260 1632.4 0.0017037869 0.00045053035 + 22280 1633.8667 0.0016998953 0.0004495377 + 22300 1635.3333 0.0016960489 0.00044816777 + 22320 1636.8 0.0016922401 0.00044714973 + 22340 1638.2667 0.0016884053 0.00044610277 + 22360 1639.7333 0.0016844703 0.00044568763 + 22380 1641.2 0.0016803511 0.00044439173 + 22400 1642.6667 0.0016759401 0.00044314089 + 22420 1644.1333 0.0016711286 0.00044193566 + 22440 1645.6 0.0016658281 0.0004406589 + 22460 1647.0667 0.0016599393 0.00043844661 + 22480 1648.5333 0.001653471 0.00043656014 + 22500 1650 0.0016466439 0.00043470146 + 22520 1651.4667 0.0016396283 0.00043288723 + 22540 1652.9333 0.0016322717 0.00043091896 + 22560 1654.4 0.0016242406 0.00042878807 + 22580 1655.8667 0.0016143541 0.00042598276 + 22600 1657.3333 0.0015984531 0.00042184208 + 22620 1658.8 0.0015774545 0.00041639723 + 22640 1660.2667 0.0015581678 0.00041151234 + 22660 1661.7333 0.0015392455 0.0004074519 + 22680 1663.2 0.0015238703 0.0004031907 + 22700 1664.6667 0.0015082033 0.00039905746 + 22720 1666.1333 0.0014910701 0.00039410593 + 22740 1667.6 0.0014773215 0.00039023578 + 22760 1669.0667 0.0014646054 0.00038693028 + 22780 1670.5333 0.0014509254 0.00038338321 + 22800 1672 0.0014387044 0.00038022989 + 22820 1673.4667 0.0014276038 0.00037738369 + 22840 1674.9333 0.0014165206 0.00037467759 + 22860 1676.4 0.0014054416 0.00037186956 + 22880 1677.8667 0.0013942654 0.00036919292 + 22900 1679.3333 0.0013833555 0.00036666326 + 22920 1680.8 0.0013733025 0.00036390292 + 22940 1682.2667 0.001364207 0.00036143657 + 22960 1683.7333 0.001355472 0.00035947361 + 22980 1685.2 0.0013467462 0.00035649775 + 23000 1686.6667 0.0013381467 0.00035425964 + 23020 1688.1333 0.0013298724 0.00035194314 + 23040 1689.6 0.0013219998 0.0003499467 + 23060 1691.0667 0.0013145189 0.00034806194 + 23080 1692.5333 0.0013073428 0.00034626601 + 23100 1694 0.0013004081 0.00034470285 + 23120 1695.4667 0.0012935813 0.00034306885 + 23140 1696.9333 0.0012865972 0.0003412658 + 23160 1698.4 0.0012792092 0.00033945219 + 23180 1699.8667 0.0012712869 0.00033750315 + 23200 1701.3333 0.0012627886 0.0003353201 + 23220 1702.8 0.001253784 0.00033296654 + 23240 1704.2667 0.0012445082 0.00033053745 + 23260 1705.7333 0.001235266 0.00032759425 + 23280 1707.2 0.0012261717 0.000325215 + 23300 1708.6667 0.0012168943 0.00032279239 + 23320 1710.1333 0.0012071081 0.00032042001 + 23340 1711.6 0.0011971594 0.00031782638 + 23360 1713.0667 0.0011876725 0.00031524799 + 23380 1714.5333 0.0011786269 0.00031289556 + 23400 1716 0.001169404 0.00031049786 + 23420 1717.4667 0.0011595669 0.00030723977 + 23440 1718.9333 0.001149266 0.00030443096 + 23460 1720.4 0.001138992 0.00030161041 + 23480 1721.8667 0.001129081 0.00029923744 + 23500 1723.3333 0.0011195152 0.00029668379 + 23520 1724.8 0.0011100863 0.00029417354 + 23540 1726.2667 0.0011005982 0.00029164586 + 23560 1727.7333 0.0010910778 0.0002889626 + 23580 1729.2 0.0010816854 0.00028655072 + 23600 1730.6667 0.001072494 0.00028419823 + 23620 1732.1333 0.0010634481 0.00028189699 + 23640 1733.6 0.0010544699 0.00027928614 + 23660 1735.0667 0.0010455565 0.00027694249 + 23680 1736.5333 0.0010367472 0.00027466258 + 23700 1738 0.0010280561 0.00027240232 + 23720 1739.4667 0.0010194696 0.00027014395 + 23740 1740.9333 0.0010109726 0.00026815472 + 23760 1742.4 0.0010025582 0.00026636602 + 23780 1743.8667 0.00099420961 0.0002639384 + 23800 1745.3333 0.00098589439 0.00026185788 + 23820 1746.8 0.00097758322 0.00025980082 + 23840 1748.2667 0.00096925998 0.00025767237 + 23860 1749.7333 0.00096092015 0.00025564227 + 23880 1751.2 0.00095256615 0.0002533114 + 23900 1752.6667 0.00094419511 0.00025115421 + 23920 1754.1333 0.00093579195 0.00024903122 + 23940 1755.6 0.00092733111 0.00024683875 + 23960 1757.0667 0.00091878509 0.00024461091 + 23980 1758.5333 0.00091013147 0.00024236826 + 24000 1760 0.00090135324 0.0002404806 + 24020 1761.4667 0.00089243423 0.0002380936 + 24040 1762.9333 0.00088336053 0.00023549546 + 24060 1764.4 0.00087412784 0.00023319301 + 24080 1765.8667 0.00086474945 0.00023084155 + 24100 1767.3333 0.00085525774 0.00022851664 + 24120 1768.8 0.0008456963 0.00022615872 + 24140 1770.2667 0.00083610859 0.00022375601 + 24160 1771.7333 0.00082652908 0.00022120807 + 24180 1773.2 0.00081698057 0.00021815795 + 24200 1774.6667 0.00080747609 0.00021555543 + 24220 1776.1333 0.00079802183 0.00021298564 + 24240 1777.6 0.00078862131 0.00021045545 + 24260 1779.0667 0.00077927933 0.00020806904 + 24280 1780.5333 0.00077000523 0.0002058181 + 24300 1782 0.00076081568 0.00020320246 + 24320 1783.4667 0.00075173462 0.00020084308 + 24340 1784.9333 0.0007427896 0.00019868422 + 24360 1786.4 0.00073400423 0.00019651532 + 24380 1787.8667 0.00072538996 0.00019445357 + 24400 1789.3333 0.00071694344 0.00019222062 + 24420 1790.8 0.00070865664 0.0001900288 + 24440 1792.2667 0.00070053087 0.00018789961 + 24460 1793.7333 0.00069258266 0.0001848306 + 24480 1795.2 0.00068483291 0.00018274366 + 24500 1796.6667 0.00067729047 0.00018074446 + 24520 1798.1333 0.00066994193 0.00017882986 + 24540 1799.6 0.00066275021 0.00017698882 + 24560 1801.0667 0.00065565627 0.00017510426 + 24580 1802.5333 0.00064858738 0.00017328965 + 24600 1804 0.00064147322 0.00017147388 + 24620 1805.4667 0.00063426805 0.00016964736 + 24640 1806.9333 0.0006269663 0.00016781232 + 24660 1808.4 0.00061960354 0.00016597943 + 24680 1809.8667 0.00061223634 0.00016419561 + 24700 1811.3333 0.00060491662 0.00016237355 + 24720 1812.8 0.00059767953 0.00016075431 + 24740 1814.2667 0.00059053949 0.00015905558 + 24760 1815.7333 0.00058349084 0.00015739614 + 24780 1817.2 0.0005765115 0.00015502575 + 24800 1818.6667 0.0005695693 0.00015330761 + 24820 1820.1333 0.00056263283 0.00015162196 + 24840 1821.6 0.00055568243 0.00014995088 + 24860 1823.0667 0.00054871692 0.00014819243 + 24880 1824.5333 0.00054175223 0.00014652991 + 24900 1826 0.00053481455 0.00014490663 + 24920 1827.4667 0.00052793142 0.00014324987 + 24940 1828.9333 0.00052112566 0.00014156756 + 24960 1830.4 0.00051441308 0.0001397807 + 24980 1831.8667 0.00050780341 0.00013808181 + 25000 1833.3333 0.0005013017 0.00013637046 + 25020 1834.8 0.00049490926 0.00013464589 + 25040 1836.2667 0.00048862482 0.00013292356 + 25060 1837.7333 0.0004824453 0.0001314188 + 25080 1839.2 0.00047636617 0.0001293314 + 25100 1840.6667 0.00047038116 0.00012754146 + 25120 1842.1333 0.00046448251 0.00012554913 + 25140 1843.6 0.0004586615 0.00012383425 + 25160 1845.0667 0.00045290921 0.00012215229 + 25180 1846.5333 0.00044721746 0.00012074608 + 25200 1848 0.00044157971 0.0001189818 + 25220 1849.4667 0.00043599245 0.00011737642 + 25240 1850.9333 0.00043045564 0.00011575387 + 25260 1852.4 0.00042497205 0.00011421704 + 25280 1853.8667 0.00041954608 0.00011269281 + 25300 1855.3333 0.00041418267 0.00011124707 + 25320 1856.8 0.0004088869 0.00010985539 + 25340 1858.2667 0.00040366377 0.00010856688 + 25360 1859.7333 0.0003985179 0.00010747086 + 25380 1861.2 0.00039345294 0.00010624143 + 25400 1862.6667 0.00038847115 0.00010464611 + 25420 1864.1333 0.00038357328 0.00010342367 + 25440 1865.6 0.00037875866 0.00010197951 + 25460 1867.0667 0.0003740255 0.00010083387 + 25480 1868.5333 0.00036937131 9.9727459e-05 + 25500 1870 0.00036479358 9.8715792e-05 + 25520 1871.4667 0.00036029053 9.7693667e-05 + 25540 1872.9333 0.00035586162 9.6659947e-05 + 25560 1874.4 0.00035150779 9.5730365e-05 + 25580 1875.8667 0.000347231 9.4850676e-05 + 25600 1877.3333 0.00034303359 9.4132269e-05 + 25620 1878.8 0.00033891749 9.3355928e-05 + 25640 1880.2667 0.00033488372 9.282199e-05 + 25660 1881.7333 0.00033093187 9.2101633e-05 + 25680 1883.2 0.00032705982 9.1331225e-05 + 25700 1884.6667 0.00032326391 8.9490029e-05 + 25720 1886.1333 0.0003195392 8.8603192e-05 + 25740 1887.6 0.00031588037 8.7694411e-05 + 25760 1889.0667 0.0003122828 8.6761483e-05 + 25780 1890.5333 0.00030874312 8.5806827e-05 + 25800 1892 0.00030525908 8.4835735e-05 + 25820 1893.4667 0.00030182927 8.402954e-05 + 25840 1894.9333 0.00029845296 8.3049666e-05 + 25860 1896.4 0.00029512991 8.211056e-05 + 25880 1897.8667 0.00029186078 8.1134374e-05 + 25900 1899.3333 0.00028864743 8.0199975e-05 + 25920 1900.8 0.00028549282 7.9325687e-05 + 25940 1902.2667 0.0002824008 7.8437438e-05 + 25960 1903.7333 0.00027937535 7.7544386e-05 + 25980 1905.2 0.00027642007 7.6706594e-05 + 26000 1906.6667 0.00027353814 7.579826e-05 + 26020 1908.1333 0.00027073244 7.5008665e-05 + 26040 1909.6 0.00026800557 7.4544912e-05 + 26060 1911.0667 0.00026535971 7.3786981e-05 + 26080 1912.5333 0.00026279611 7.2166049e-05 + 26100 1914 0.00026031456 7.1403392e-05 + 26120 1915.4667 0.00025791305 7.0702466e-05 + 26140 1916.9333 0.00025558794 7.0006351e-05 + 26160 1918.4 0.00025333488 6.9317329e-05 + 26180 1919.8667 0.00025115003 6.8688062e-05 + 26200 1921.3333 0.00024903038 6.8122851e-05 + 26220 1922.8 0.00024697358 6.7568833e-05 + 26240 1924.2667 0.00024497771 6.6968209e-05 + 26260 1925.7333 0.00024304157 6.6501986e-05 + 26280 1927.2 0.0002411651 6.6088755e-05 + 26300 1928.6667 0.00023934939 6.5705322e-05 + 26320 1930.1333 0.00023759592 6.5362857e-05 + 26340 1931.6 0.00023590514 6.5049803e-05 + 26360 1933.0667 0.00023427484 6.473807e-05 + 26380 1934.5333 0.00023269956 6.4466061e-05 + 26400 1936 0.00023117121 6.4080253e-05 + 26420 1937.4667 0.0002296809 6.3752394e-05 + 26440 1938.9333 0.00022822123 6.3357126e-05 + 26460 1940.4 0.00022678837 6.3049852e-05 + 26480 1941.8667 0.00022538306 6.2753673e-05 + 26500 1943.3333 0.00022400995 6.2294535e-05 + 26520 1944.8 0.00022267608 6.2038117e-05 + 26540 1946.2667 0.00022138844 6.1782883e-05 + 26560 1947.7333 0.00022015168 6.1574119e-05 + 26580 1949.2 0.00021896802 6.1384003e-05 + 26600 1950.6667 0.00021783788 6.1156768e-05 + 26620 1952.1333 0.00021676111 6.0986244e-05 + 26640 1953.6 0.0002157381 6.0849325e-05 + 26660 1955.0667 0.00021477001 6.0683878e-05 + 26680 1956.5333 0.00021385807 6.0516059e-05 + 26700 1958 0.00021300223 6.0329517e-05 + 26720 1959.4667 0.00021220038 6.0110922e-05 + 26740 1960.9333 0.0002114485 5.9940604e-05 + 26760 1962.4 0.00021074077 5.977174e-05 + 26780 1963.8667 0.00021007047 5.9606511e-05 + 26800 1965.3333 0.00020943091 5.9060466e-05 + 26820 1966.8 0.00020881619 5.8839697e-05 + 26840 1968.2667 0.00020822134 5.8633638e-05 + 26860 1969.7333 0.00020764269 5.8541664e-05 + 26880 1971.2 0.0002070779 5.83276e-05 + 26900 1972.6667 0.00020652606 5.8076903e-05 + 26920 1974.1333 0.00020598762 5.7951516e-05 + 26940 1975.6 0.00020546407 5.7793633e-05 + 26960 1977.0667 0.00020495767 5.7642438e-05 + 26980 1978.5333 0.00020447095 5.7497463e-05 + 27000 1980 0.00020400643 5.7358967e-05 + 27020 1981.4667 0.00020356638 5.7197798e-05 + 27040 1982.9333 0.00020315297 5.7081118e-05 + 27060 1984.4 0.00020276878 5.6970958e-05 + 27080 1985.8667 0.0002024165 5.6875439e-05 + 27100 1987.3333 0.00020209914 5.6749323e-05 + 27120 1988.8 0.00020182082 5.6684087e-05 + 27140 1990.2667 0.0002015866 5.6665814e-05 + 27160 1991.7333 0.00020140121 5.6663183e-05 + 27180 1993.2 0.0002012666 5.6636454e-05 + 27200 1994.6667 0.00020117997 5.6723443e-05 + 27220 1996.1333 0.00020113417 5.6708615e-05 + 27240 1997.6 0.00020111982 5.6574526e-05 + 27260 1999.0667 0.00020112751 5.6159e-05 + 27280 2000.5333 0.00020114945 5.612955e-05 + 27300 2002 0.00020118054 5.607577e-05 + 27320 2003.4667 0.00020121792 5.6026534e-05 + 27340 2004.9333 0.00020125939 5.5904818e-05 + 27360 2006.4 0.0002013021 5.5872498e-05 + 27380 2007.8667 0.00020134272 5.5850226e-05 + 27400 2009.3333 0.00020137844 5.5792845e-05 + 27420 2010.8 0.0002014071 5.5793502e-05 + 27440 2012.2667 0.00020142601 5.5834389e-05 + 27460 2013.7333 0.00020143246 5.5853674e-05 + 27480 2015.2 0.00020142475 5.5879946e-05 + 27500 2016.6667 0.00020140167 5.5911328e-05 + 27520 2018.1333 0.000201362 5.5946112e-05 + 27540 2019.6 0.00020130361 5.5982457e-05 + 27560 2021.0667 0.00020122365 5.6018854e-05 + 27580 2022.5333 0.00020111911 5.6199876e-05 + 27600 2024 0.00020098676 5.6207908e-05 + 27620 2025.4667 0.00020082461 5.6235125e-05 + 27640 2026.9333 0.00020063251 5.6261668e-05 + 27660 2028.4 0.00020041288 5.6264024e-05 + 27680 2029.8667 0.00020017135 5.6292857e-05 + 27700 2031.3333 0.00019991548 5.6350987e-05 + 27720 2032.8 0.00019965421 5.6386525e-05 + 27740 2034.2667 0.00019939714 5.6330983e-05 + 27760 2035.7333 0.00019915264 5.6315529e-05 + 27780 2037.2 0.00019892685 5.6357912e-05 + 27800 2038.6667 0.00019872342 5.6400674e-05 + 27820 2040.1333 0.00019854343 5.592942e-05 + 27840 2041.6 0.00019838552 5.5933967e-05 + 27860 2043.0667 0.00019824625 5.5937495e-05 + 27880 2044.5333 0.00019812108 5.5939048e-05 + 27900 2046 0.00019800547 5.5938225e-05 + 27920 2047.4667 0.00019789596 5.5934984e-05 + 27940 2048.9333 0.00019779049 5.5998316e-05 + 27960 2050.4 0.00019768847 5.5990459e-05 + 27980 2051.8667 0.00019759007 5.5934942e-05 + 28000 2053.3333 0.00019749517 5.5921371e-05 + 28020 2054.8 0.00019740272 5.5903442e-05 + 28040 2056.2667 0.00019731052 5.5860176e-05 + 28060 2057.7333 0.00019721613 5.58009e-05 + 28080 2059.2 0.00019711761 5.576013e-05 + 28100 2060.6667 0.00019701413 5.5709878e-05 + 28120 2062.1333 0.00019690592 5.5650013e-05 + 28140 2063.6 0.00019679371 5.549438e-05 + 28160 2065.0667 0.00019667803 5.5419813e-05 + 28180 2066.5333 0.00019655854 5.5339684e-05 + 28200 2068 0.0001964341 5.5255642e-05 + 28220 2069.4667 0.00019630305 5.516945e-05 + 28240 2070.9333 0.00019616373 5.5082892e-05 + 28260 2072.4 0.00019601462 5.4997644e-05 + 28280 2073.8667 0.00019585462 5.4915059e-05 + 28300 2075.3333 0.00019568308 5.4836332e-05 + 28320 2076.8 0.00019549977 5.4945429e-05 + 28340 2078.2667 0.00019530501 5.4861235e-05 + 28360 2079.7333 0.00019509987 5.46661e-05 + 28380 2081.2 0.00019488603 5.4604902e-05 + 28400 2082.6667 0.00019466562 5.4548672e-05 + 28420 2084.1333 0.00019444125 5.4495481e-05 + 28440 2085.6 0.00019421575 5.4450188e-05 + 28460 2087.0667 0.00019399217 5.441163e-05 + 28480 2088.5333 0.00019377343 5.4375395e-05 + 28500 2090 0.00019356194 5.4441594e-05 + 28520 2091.4667 0.00019335923 5.4431527e-05 + 28540 2092.9333 0.00019316575 5.4433248e-05 + 28560 2094.4 0.00019298088 5.4331854e-05 + 28580 2095.8667 0.00019280294 5.4731573e-05 + 28600 2097.3333 0.00019262915 5.4763809e-05 + 28620 2098.8 0.00019245592 5.4802719e-05 + 28640 2100.2667 0.00019227949 5.4072056e-05 + 28660 2101.7333 0.00019209613 5.4088674e-05 + 28680 2103.2 0.00019190237 5.4104871e-05 + 28700 2104.6667 0.00019169556 5.4118777e-05 + 28720 2106.1333 0.00019147409 5.4129434e-05 + 28740 2107.6 0.00019123755 5.4109248e-05 + 28760 2109.0667 0.00019098676 5.4095416e-05 + 28780 2110.5333 0.00019072352 5.40944e-05 + 28800 2112 0.0001904505 5.4089923e-05 + 28820 2113.4667 0.00019017109 5.4081987e-05 + 28840 2114.9333 0.00018988915 5.4070363e-05 + 28860 2116.4 0.00018960886 5.4054643e-05 + 28880 2117.8667 0.00018933429 5.4034314e-05 + 28900 2119.3333 0.00018906938 5.4008966e-05 + 28920 2120.8 0.00018881786 5.3978254e-05 + 28940 2122.2667 0.00018858319 5.3942187e-05 + 28960 2123.7333 0.00018836835 5.3901318e-05 + 28980 2125.2 0.00018817583 5.4169759e-05 + 29000 2126.6667 0.00018800763 5.4121319e-05 + 29020 2128.1333 0.00018786525 5.4070295e-05 + 29040 2129.6 0.00018774951 5.4018165e-05 + 29060 2131.0667 0.00018766058 5.3884893e-05 + 29080 2132.5333 0.00018759795 5.3876376e-05 + 29100 2134 0.00018756047 5.3823317e-05 + 29120 2135.4667 0.00018754627 5.3770657e-05 + 29140 2136.9333 0.00018755268 5.3718045e-05 + 29160 2138.4 0.00018757627 5.3665402e-05 + 29180 2139.8667 0.00018761287 5.3612408e-05 + 29200 2141.3333 0.00018765753 5.3558506e-05 + 29220 2142.8 0.0001877046 5.3503291e-05 + 29240 2144.2667 0.00018774817 5.3446796e-05 + 29260 2145.7333 0.00018778315 5.3389512e-05 + 29280 2147.2 0.00018780643 5.3332431e-05 + 29300 2148.6667 0.00018781742 5.3277223e-05 + 29320 2150.1333 0.00018781793 5.3226314e-05 + 29340 2151.6 0.00018781143 5.3176641e-05 + 29360 2153.0667 0.00018780238 5.3141246e-05 + 29380 2154.5333 0.00018779594 5.3117607e-05 + 29400 2156 0.00018779765 5.310825e-05 + 29420 2157.4667 0.0001878128 5.3115468e-05 + 29440 2158.9333 0.00018784561 5.3139946e-05 + 29460 2160.4 0.00018789868 5.288786e-05 + 29480 2161.8667 0.00018797309 5.294168e-05 + 29500 2163.3333 0.00018806883 5.3008359e-05 + 29520 2164.8 0.0001881852 5.3085712e-05 + 29540 2166.2667 0.000188321 5.317109e-05 + 29560 2167.7333 0.00018847475 5.3261964e-05 + 29580 2169.2 0.00018864479 5.3217461e-05 + 29600 2170.6667 0.00018882945 5.3313718e-05 + 29620 2172.1333 0.00018902706 5.3374367e-05 + 29640 2173.6 0.00018923607 5.347584e-05 + 29660 2175.0667 0.00018945509 5.3579085e-05 + 29680 2176.5333 0.000189683 5.3683544e-05 + 29700 2178 0.00018991893 5.3789562e-05 + 29720 2179.4667 0.00019016223 5.3898155e-05 + 29740 2180.9333 0.00019041244 5.4010173e-05 + 29760 2182.4 0.00019066923 5.4125994e-05 + 29780 2183.8667 0.00019093232 5.4245712e-05 + 29800 2185.3333 0.00019120142 5.436933e-05 + 29820 2186.8 0.00019147625 5.449677e-05 + 29840 2188.2667 0.00019175653 5.4627812e-05 + 29860 2189.7333 0.00019204205 5.476186e-05 + 29880 2191.2 0.00019233262 5.4897917e-05 + 29900 2192.6667 0.00019262806 5.5034988e-05 + 29920 2194.1333 0.00019292829 5.5172428e-05 + 29940 2195.6 0.00019323338 5.5309532e-05 + 29960 2197.0667 0.0001935435 5.5445368e-05 + 29980 2198.5333 0.00019385897 5.5579065e-05 + 30000 2200 0.00019418014 5.5710007e-05 +Loop time of 120.806 on 4 procs for 30000 steps with 3046 atoms + +Performance: 1573425.361 tau/day, 248.331 timesteps/s, 756.416 katom-step/s +99.3% CPU use with 4 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.89764 | 12.463 | 25.361 | 316.2 | 10.32 +Neigh | 0.083839 | 0.94363 | 1.8654 | 87.4 | 0.78 +Comm | 0.23436 | 0.25427 | 0.27244 | 2.9 | 0.21 +Output | 1.2745 | 2.0289 | 2.7205 | 46.3 | 1.68 +Modify | 88.101 | 92.266 | 95.765 | 34.6 | 76.38 +Other | | 12.85 | | | 10.64 + +Nlocal: 761.5 ave 1685 max 105 min +Histogram: 2 0 0 0 0 0 1 0 0 1 +Nghost: 28.5 ave 51 max 7 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Neighs: 6128.5 ave 14174 max 567 min +Histogram: 2 0 0 0 0 0 1 0 0 1 +FullNghs: 12164 ave 28184 max 1117 min +Histogram: 2 0 0 0 0 0 1 0 0 1 + +Total # of neighbors = 48656 +Ave neighs/atom = 15.973736 +Neighbor list builds = 3012 +Dangerous builds = 0 + +Total wall time: 0:02:00 diff --git a/examples/rheo/ice-cubes/in.rheo.ice.cubes b/examples/rheo/ice-cubes/in.rheo.ice.cubes new file mode 100644 index 0000000000..91e02c780d --- /dev/null +++ b/examples/rheo/ice-cubes/in.rheo.ice.cubes @@ -0,0 +1,82 @@ +# ------ 2D Ice Cube Pour ------ # + +dimension 2 +units lj +atom_style hybrid rheo/thermal bond +boundary m m p +comm_modify vel yes +newton off +special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0 + +region box block -25 25 0 100 -0.01 0.01 units box +create_box 1 box bond/types 1 extra/bond/per/atom 15 extra/special/per/atom 50 + +region fluid block $(xlo+1) $(xhi-1) $(ylo+1) $(ylo+30) EDGE EDGE units box +lattice sq 1.0 +create_atoms 1 region fluid + +set group all sph/e 8.0 + +# ------ Model parameters ------# + +variable cut equal 3.0 +variable n equal 1.0 +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable zeta equal 0.05 +variable kappa equal 0.01*${rho0}/${mp} +variable dt_max equal 0.1*${cut}/${cs}/3 +variable eta equal 0.05 +variable Cv equal 1.0 +variable L equal 1.0 +variable Tf equal 1.0 + +mass * ${mp} +timestep 0.1 + +pair_style hybrid/overlay rheo ${cut} artificial/visc ${zeta} rheo/solid +pair_coeff * * rheo +pair_coeff * * rheo/solid 1.0 1.0 1.0 + +bond_style bpm/spring +bond_coeff 1 1.0 1.0 1.0 + +# ------ Pour particles ------# + +molecule my_mol "square.mol" + +# Wall region extends far enough in z to avoid contact +region wall block EDGE EDGE EDGE EDGE -5 5 side in open 4 units box +region drop block -16 16 70 90 EDGE EDGE side in units box + +fix 1 all rheo ${cut} quintic 0 & + thermal & + shift & + surface/detection coordination 22 8 +fix 2 all rheo/viscosity * constant ${eta} +fix 3 all rheo/pressure * linear +fix 4 all rheo/thermal conductivity * constant ${kappa} & + specific/heat * constant ${Cv} & + Tfreeze * constant ${Tf} & + latent/heat * constant ${L} & + react 1.5 1 +fix 5 all wall/region wall harmonic 1.0 1.0 1.0 +fix 6 all gravity 5e-4 vector 0 -1 0 +fix 7 all deposit 8 0 1000 37241459 mol my_mol region drop near 2.0 vy -0.02 -0.02 +fix 8 all enforce2d + +compute rho all rheo/property/atom rho +compute phase all rheo/property/atom phase +compute temp all rheo/property/atom temperature +compute eng all rheo/property/atom energy +compute nbond all nbond/atom + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press atoms + +#dump 1 all custom 200 atomDump id type x y vx vy fx fy c_phase c_temp c_eng c_nbond c_rho + +run 30000 diff --git a/examples/rheo/ice-cubes/log.17Apr2024.ice.g++.4 b/examples/rheo/ice-cubes/log.17Apr2024.ice.g++.4 new file mode 100644 index 0000000000..98fc2e7540 --- /dev/null +++ b/examples/rheo/ice-cubes/log.17Apr2024.ice.g++.4 @@ -0,0 +1,379 @@ +LAMMPS (17 Apr 2024 - Development - patch_5May2020-18508-g3c0eaf6870-modified) +# ------ 2D Ice Cube Pour ------ # + +dimension 2 +units lj +atom_style hybrid rheo/thermal bond +boundary m m p +comm_modify vel yes +newton off +special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0 + +region box block -25 25 0 100 -0.01 0.01 units box +create_box 1 box bond/types 1 extra/bond/per/atom 15 extra/special/per/atom 50 +Created orthogonal box = (-25 0 -0.01) to (25 100 0.01) + 2 by 2 by 1 MPI processor grid + +region fluid block $(xlo+1) $(xhi-1) $(ylo+1) $(ylo+30) EDGE EDGE units box +region fluid block -24 $(xhi-1) $(ylo+1) $(ylo+30) EDGE EDGE units box +region fluid block -24 24 $(ylo+1) $(ylo+30) EDGE EDGE units box +region fluid block -24 24 1 $(ylo+30) EDGE EDGE units box +region fluid block -24 24 1 30 EDGE EDGE units box +lattice sq 1.0 +Lattice spacing in x,y,z = 1 1 1 +create_atoms 1 region fluid +Created 1470 atoms + using lattice units in orthogonal box = (-25 0 -0.01) to (25 100 0.01) + create_atoms CPU = 0.001 seconds + +set group all sph/e 8.0 +Setting atom values ... + 1470 settings made for sph/e + +# ------ Model parameters ------# + +variable cut equal 3.0 +variable n equal 1.0 +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable mp equal 1/${n} +variable mp equal 1/1 +variable zeta equal 0.05 +variable kappa equal 0.01*${rho0}/${mp} +variable kappa equal 0.01*1/${mp} +variable kappa equal 0.01*1/1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable dt_max equal 0.1*3/${cs}/3 +variable dt_max equal 0.1*3/1/3 +variable eta equal 0.05 +variable Cv equal 1.0 +variable L equal 1.0 +variable Tf equal 1.0 + +mass * ${mp} +mass * 1 +timestep 0.1 + +pair_style hybrid/overlay rheo ${cut} artificial/visc ${zeta} rheo/solid +pair_style hybrid/overlay rheo 3 artificial/visc ${zeta} rheo/solid +pair_style hybrid/overlay rheo 3 artificial/visc 0.05 rheo/solid +pair_coeff * * rheo +pair_coeff * * rheo/solid 1.0 1.0 1.0 + +bond_style bpm/spring +bond_coeff 1 1.0 1.0 1.0 + +# ------ Pour particles ------# + +molecule my_mol "square.mol" +Read molecule template my_mol: +#Made with create_mol.py + 1 molecules + 0 fragments + 100 atoms with max type 1 + 342 bonds with max type 1 + 0 angles with max type 0 + 0 dihedrals with max type 0 + 0 impropers with max type 0 + +# Wall region extends far enough in z to avoid contact +region wall block EDGE EDGE EDGE EDGE -5 5 side in open 4 units box +region drop block -16 16 70 90 EDGE EDGE side in units box + +fix 1 all rheo ${cut} quintic 0 thermal shift surface/detection coordination 22 8 +fix 1 all rheo 3 quintic 0 thermal shift surface/detection coordination 22 8 +fix 2 all rheo/viscosity * constant ${eta} +fix 2 all rheo/viscosity * constant 0.05 +fix 3 all rheo/pressure * linear +fix 4 all rheo/thermal conductivity * constant ${kappa} specific/heat * constant ${Cv} Tfreeze * constant ${Tf} latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.01 specific/heat * constant ${Cv} Tfreeze * constant ${Tf} latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.01 specific/heat * constant 1 Tfreeze * constant ${Tf} latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.01 specific/heat * constant 1 Tfreeze * constant 1 latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.01 specific/heat * constant 1 Tfreeze * constant 1 latent/heat * constant 1 react 1.5 1 +fix 5 all wall/region wall harmonic 1.0 1.0 1.0 +fix 6 all gravity 5e-4 vector 0 -1 0 +fix 7 all deposit 8 0 1000 37241459 mol my_mol region drop near 2.0 vy -0.02 -0.02 +WARNING: Molecule attributes do not match system attributes (../molecule.cpp:1881) +fix 8 all enforce2d + +compute rho all rheo/property/atom rho +compute phase all rheo/property/atom phase +compute temp all rheo/property/atom temperature +compute eng all rheo/property/atom energy +compute nbond all nbond/atom + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press atoms + +dump 1 all custom 200 atomDump id type x y vx vy fx fy c_phase c_temp c_eng c_nbond c_rho + +run 30000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- BPM bond style: doi:10.1039/D3SM01373A + +@Article{Clemmer2024, + author = {Clemmer, Joel T. and Monti, Joseph M. and Lechman, Jeremy B.}, + title = {A soft departure from jamming: the compaction of deformable + granular matter under high pressures}, + journal = {Soft Matter}, + year = 2024, + volume = 20, + number = 8, + pages = {1702--1718} +} + +- @article{PalermoInPrep, + journal = {in prep}, + title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows}, + year = {2024}, + author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor}, +} + +- @article{ApplMathModel.130.310, + title = {A hybrid smoothed-particle hydrodynamics model of oxide skins on molten aluminum}, + journal = {Applied Mathematical Modelling}, + volume = {130}, + pages = {310-326}, + year = {2024}, + issn = {0307-904X}, + doi = {https://doi.org/10.1016/j.apm.2024.02.027}, + author = {Joel T. Clemmer and Flint Pierce and Thomas C. O'Connor and Thomas D. Nevins and Elizabeth M.C. Jones and Jeremy B. Lechman and John Tencer}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 31 61 1 + 7 neighbor lists, perpetual/occasional/extra = 6 1 0 + (1) pair rheo, perpetual, half/full from (3) + attributes: half, newton off + pair build: halffull/newtoff + stencil: none + bin: none + (2) pair rheo/solid, perpetual, trim from (4) + attributes: half, newton off, cut 1.3 + pair build: trim + stencil: none + bin: none + (3) compute RHEO/KERNEL, perpetual + attributes: full, newton off + pair build: full/bin + stencil: full/bin/2d + bin: standard + (4) compute RHEO/GRAD, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (5) compute RHEO/VSHIFT, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (6) compute RHEO/SURFACE, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (7) fix rheo/thermal, occasional, trim from (4) + attributes: half, newton off, cut 3 + pair build: trim + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 15.53 | 15.61 | 15.69 Mbytes + Step Time KinEng Press Atoms + 0 0 0 0 1470 + 200 20 5.6002982e-05 3.4434234e-05 1570 + 400 40 8.2173099e-05 8.6171768e-05 1570 + 600 60 8.019018e-05 0.00010750355 1570 + 800 80 0.00013866953 0.00010265608 1570 + 1000 100 0.00018965028 8.1985605e-05 1570 + 1200 120 0.00022033242 7.4736443e-05 1670 + 1400 140 0.00030767062 0.00011264333 1670 + 1600 160 0.00040770127 0.00018779992 1670 + 1800 180 0.00047476332 0.00023153009 1670 + 2000 200 0.00059116774 0.00027200445 1670 + 2200 220 0.0007151733 0.0002919963 1770 + 2400 240 0.00083392135 0.00029757889 1770 + 2600 260 0.00099653466 0.00036547269 1770 + 2800 280 0.0011964069 0.00045983458 1770 + 3000 300 0.0013716953 0.00055013647 1770 + 3200 320 0.0015174096 0.00064203572 1870 + 3400 340 0.0016539743 0.00086671622 1870 + 3600 360 0.0015887858 0.00066353749 1870 + 3800 380 0.0016451684 0.00070551483 1870 + 4000 400 0.0017330971 0.00080722283 1870 + 4200 420 0.001812193 0.00073573903 1970 + 4400 440 0.001755871 0.0010621909 1970 + 4600 460 0.0016190772 0.00072913706 1970 + 4800 480 0.0015741931 0.00073524088 1970 + 5000 500 0.0016488815 0.00088684275 1970 + 5200 520 0.0017213288 0.00077042378 2070 + 5400 540 0.0018509598 0.0010219434 2070 + 5600 560 0.0020251064 0.00083182483 2070 + 5800 580 0.0022473255 0.00095076144 2070 + 6000 600 0.0024843519 0.0011247014 2070 + 6200 620 0.0022282321 0.0018105932 2170 + 6400 640 0.0020289063 0.0014158497 2170 + 6600 660 0.002145241 0.0011359383 2170 + 6800 680 0.0024313937 0.0016475504 2170 + 7000 700 0.0021000599 0.0020983745 2170 + 7200 720 0.0019137235 0.0010439152 2270 + 7400 740 0.0018801367 0.00095436448 2270 + 7600 760 0.0017979449 0.0011184039 2270 + 7800 780 0.0018005205 0.0009243205 2270 + 8000 800 0.0017827073 0.0013671228 2270 + 8200 820 0.0018387108 0.0015426012 2270 + 8400 840 0.0016000788 0.0016751514 2270 + 8600 860 0.0013954964 0.0016884335 2270 + 8800 880 0.0013283728 0.0012399398 2270 + 9000 900 0.001389385 0.0012968496 2270 + 9200 920 0.0012295438 0.0012995821 2270 + 9400 940 0.0010522655 0.00082245528 2270 + 9600 960 0.00097085496 0.00053833131 2270 + 9800 980 0.0009398987 0.00063467387 2270 + 10000 1000 0.00092710392 0.00059494446 2270 + 10200 1020 0.00095545471 0.00074560644 2270 + 10400 1040 0.0009645841 0.00085429807 2270 + 10600 1060 0.00064037148 0.0017222246 2270 + 10800 1080 0.00046790978 0.00088204234 2270 + 11000 1100 0.00030106229 0.00074950209 2270 + 11200 1120 0.00027746016 0.00052831745 2270 + 11400 1140 0.0002533348 0.0006272715 2270 + 11600 1160 0.00021825085 0.00029691552 2270 + 11800 1180 0.0001451308 0.00015037478 2270 + 12000 1200 0.0001314823 0.00017227174 2270 + 12200 1220 0.00013693632 0.00017791384 2270 + 12400 1240 0.00014987347 0.0002286677 2270 + 12600 1260 0.00015092598 0.0003698436 2270 + 12800 1280 0.0001291653 0.00047229532 2270 + 13000 1300 0.00011949988 0.00049560375 2270 + 13200 1320 0.00011694665 0.00057542084 2270 + 13400 1340 9.6164519e-05 0.00062714755 2270 + 13600 1360 8.4517591e-05 0.00044156913 2270 + 13800 1380 0.00019140516 0.0003264745 2270 + 14000 1400 0.00013868599 0.00037753497 2270 + 14200 1420 9.3701636e-05 0.00031517848 2270 + 14400 1440 6.7389077e-05 0.0002946861 2270 + 14600 1460 5.3640086e-05 0.00026650711 2270 + 14800 1480 4.2699992e-05 0.00023789279 2270 + 15000 1500 5.3012016e-05 0.00019933234 2270 + 15200 1520 5.8834197e-05 0.00022407007 2270 + 15400 1540 5.0899982e-05 0.00029695531 2270 + 15600 1560 3.0476742e-05 0.00039119066 2270 + 15800 1580 1.6633264e-05 0.00033770401 2270 + 16000 1600 1.098906e-05 0.00036684894 2270 + 16200 1620 1.464848e-05 0.00036449759 2270 + 16400 1640 1.9598429e-05 0.00021056689 2270 + 16600 1660 1.2644955e-05 0.00020781781 2270 + 16800 1680 8.8428553e-06 0.000165 2270 + 17000 1700 8.8971439e-06 0.00012266475 2270 + 17200 1720 1.7032781e-05 0.00019873443 2270 + 17400 1740 1.9448563e-05 0.00025661663 2270 + 17600 1760 1.3714713e-05 0.000324022 2270 + 17800 1780 9.1326468e-06 0.00031392513 2270 + 18000 1800 9.2464802e-06 0.00029729527 2270 + 18200 1820 1.5553042e-05 0.00027488475 2270 + 18400 1840 1.4132933e-05 0.00019565459 2270 + 18600 1860 9.4734832e-06 0.00016716988 2270 + 18800 1880 5.5115145e-06 0.00013728033 2270 + 19000 1900 8.268812e-06 0.00015119605 2270 + 19200 1920 1.2470136e-05 0.00020222131 2270 + 19400 1940 9.9387775e-06 0.00024503373 2270 + 19600 1960 5.4241999e-06 0.00026921858 2270 + 19800 1980 2.7987348e-06 0.00026201267 2270 + 20000 2000 6.272538e-06 0.00025626323 2270 + 20200 2020 8.0157781e-06 0.000220139 2270 + 20400 2040 6.1652093e-06 0.00017089058 2270 + 20600 2060 2.9967592e-06 0.00014582864 2270 + 20800 2080 3.016678e-06 0.000148629 2270 + 21000 2100 7.287645e-06 0.00016486102 2270 + 21200 2120 8.6905277e-06 0.00020276916 2270 + 21400 2140 6.8453018e-06 0.00023156153 2270 + 21600 2160 3.3853799e-06 0.0002432462 2270 + 21800 2180 4.1241209e-06 0.00022829024 2270 + 22000 2200 7.0802396e-06 0.00020784823 2270 + 22200 2220 7.3361691e-06 0.00018114134 2270 + 22400 2240 5.0764593e-06 0.00014351106 2270 + 22600 2260 2.7487537e-06 0.00012919872 2270 + 22800 2280 4.620167e-06 0.00013746218 2270 + 23000 2300 6.9819357e-06 0.00015985102 2270 + 23200 2320 6.8923916e-06 0.00018713045 2270 + 23400 2340 4.1795088e-06 0.00019846682 2270 + 23600 2360 2.2871028e-06 0.00021068421 2270 + 23800 2380 3.862046e-06 0.00019553306 2270 + 24000 2400 5.2448555e-06 0.00017398041 2270 + 24200 2420 4.7565441e-06 0.00015008142 2270 + 24400 2440 2.2952135e-06 0.00012747106 2270 + 24600 2460 2.1575617e-06 0.00012516996 2270 + 24800 2480 4.1777868e-06 0.0001331902 2270 + 25000 2500 5.5679133e-06 0.00015504562 2270 + 25200 2520 4.5758741e-06 0.00017146032 2270 + 25400 2540 2.3403277e-06 0.00017611666 2270 + 25600 2560 2.7029302e-06 0.00016850788 2270 + 25800 2580 4.3601102e-06 0.00015884642 2270 + 26000 2600 5.2244249e-06 0.00013793898 2270 + 26200 2620 3.4577672e-06 0.00012395875 2270 + 26400 2640 2.361577e-06 0.00011600057 2270 + 26600 2660 2.8515644e-06 0.00011277063 2270 + 26800 2680 4.0851213e-06 0.0001290832 2270 + 27000 2700 4.2579644e-06 0.0001476495 2270 + 27200 2720 2.6593858e-06 0.00015977745 2270 + 27400 2740 1.990115e-06 0.00015612787 2270 + 27600 2760 2.6756835e-06 0.00014913772 2270 + 27800 2780 3.9032806e-06 0.00014014763 2270 + 28000 2800 3.2729446e-06 0.00012216846 2270 + 28200 2820 1.9357278e-06 0.00011078621 2270 + 28400 2840 1.7094832e-06 0.00010910509 2270 + 28600 2860 2.8731406e-06 0.00011179644 2270 + 28800 2880 3.7062354e-06 0.00012254091 2270 + 29000 2900 2.7844262e-06 0.00013060331 2270 + 29200 2920 1.7680655e-06 0.00013797514 2270 + 29400 2940 1.706873e-06 0.0001350685 2270 + 29600 2960 2.8764562e-06 0.00012428508 2270 + 29800 2980 3.1502029e-06 0.00011456718 2270 + 30000 3000 2.1833409e-06 0.00010317469 2270 +Loop time of 165.611 on 4 procs for 30000 steps with 2270 atoms + +Performance: 1565111.240 tau/day, 181.147 timesteps/s, 411.204 katom-step/s +99.7% CPU use with 4 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.63183 | 21.226 | 42.266 | 444.6 | 12.82 +Bond | 0.095073 | 0.17799 | 0.27877 | 17.0 | 0.11 +Neigh | 2.0745 | 2.0781 | 2.0822 | 0.2 | 1.25 +Comm | 0.32024 | 0.38703 | 0.45564 | 8.1 | 0.23 +Output | 0.60459 | 0.76798 | 0.93724 | 18.6 | 0.46 +Modify | 119.85 | 140.76 | 161.36 | 172.2 | 85.00 +Other | | 0.2124 | | | 0.13 + +Nlocal: 567.5 ave 1139 max 0 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 75.5 ave 152 max 0 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Neighs: 9238.25 ave 18490 max 0 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +FullNghs: 17945 ave 35917 max 0 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 71780 +Ave neighs/atom = 31.621145 +Ave special neighs/atom = 0.22026432 +Neighbor list builds = 2071 +Dangerous builds = 0 + +Total wall time: 0:02:45 diff --git a/examples/rheo/ice-cubes/square.mol b/examples/rheo/ice-cubes/square.mol new file mode 100644 index 0000000000..0344be7244 --- /dev/null +++ b/examples/rheo/ice-cubes/square.mol @@ -0,0 +1,658 @@ +#Made with create_mol.py + +100 atoms +342 bonds + +Coords +#ID x y z +1 -4 -4 0 +2 -3 -4 0 +3 -2 -4 0 +4 -1 -4 0 +5 0 -4 0 +6 1 -4 0 +7 2 -4 0 +8 3 -4 0 +9 4 -4 0 +10 5 -4 0 +11 -4 -3 0 +12 -3 -3 0 +13 -2 -3 0 +14 -1 -3 0 +15 0 -3 0 +16 1 -3 0 +17 2 -3 0 +18 3 -3 0 +19 4 -3 0 +20 5 -3 0 +21 -4 -2 0 +22 -3 -2 0 +23 -2 -2 0 +24 -1 -2 0 +25 0 -2 0 +26 1 -2 0 +27 2 -2 0 +28 3 -2 0 +29 4 -2 0 +30 5 -2 0 +31 -4 -1 0 +32 -3 -1 0 +33 -2 -1 0 +34 -1 -1 0 +35 0 -1 0 +36 1 -1 0 +37 2 -1 0 +38 3 -1 0 +39 4 -1 0 +40 5 -1 0 +41 -4 0 0 +42 -3 0 0 +43 -2 0 0 +44 -1 0 0 +45 0 0 0 +46 1 0 0 +47 2 0 0 +48 3 0 0 +49 4 0 0 +50 5 0 0 +51 -4 1 0 +52 -3 1 0 +53 -2 1 0 +54 -1 1 0 +55 0 1 0 +56 1 1 0 +57 2 1 0 +58 3 1 0 +59 4 1 0 +60 5 1 0 +61 -4 2 0 +62 -3 2 0 +63 -2 2 0 +64 -1 2 0 +65 0 2 0 +66 1 2 0 +67 2 2 0 +68 3 2 0 +69 4 2 0 +70 5 2 0 +71 -4 3 0 +72 -3 3 0 +73 -2 3 0 +74 -1 3 0 +75 0 3 0 +76 1 3 0 +77 2 3 0 +78 3 3 0 +79 4 3 0 +80 5 3 0 +81 -4 4 0 +82 -3 4 0 +83 -2 4 0 +84 -1 4 0 +85 0 4 0 +86 1 4 0 +87 2 4 0 +88 3 4 0 +89 4 4 0 +90 5 4 0 +91 -4 5 0 +92 -3 5 0 +93 -2 5 0 +94 -1 5 0 +95 0 5 0 +96 1 5 0 +97 2 5 0 +98 3 5 0 +99 4 5 0 +100 5 5 0 + +Types +#ID type +1 1 +2 1 +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +21 1 +22 1 +23 1 +24 1 +25 1 +26 1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +33 1 +34 1 +35 1 +36 1 +37 1 +38 1 +39 1 +40 1 +41 1 +42 1 +43 1 +44 1 +45 1 +46 1 +47 1 +48 1 +49 1 +50 1 +51 1 +52 1 +53 1 +54 1 +55 1 +56 1 +57 1 +58 1 +59 1 +60 1 +61 1 +62 1 +63 1 +64 1 +65 1 +66 1 +67 1 +68 1 +69 1 +70 1 +71 1 +72 1 +73 1 +74 1 +75 1 +76 1 +77 1 +78 1 +79 1 +80 1 +81 1 +82 1 +83 1 +84 1 +85 1 +86 1 +87 1 +88 1 +89 1 +90 1 +91 1 +92 1 +93 1 +94 1 +95 1 +96 1 +97 1 +98 1 +99 1 +100 1 + +Masses +#ID mass +1 1 +2 1 +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +21 1 +22 1 +23 1 +24 1 +25 1 +26 1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +33 1 +34 1 +35 1 +36 1 +37 1 +38 1 +39 1 +40 1 +41 1 +42 1 +43 1 +44 1 +45 1 +46 1 +47 1 +48 1 +49 1 +50 1 +51 1 +52 1 +53 1 +54 1 +55 1 +56 1 +57 1 +58 1 +59 1 +60 1 +61 1 +62 1 +63 1 +64 1 +65 1 +66 1 +67 1 +68 1 +69 1 +70 1 +71 1 +72 1 +73 1 +74 1 +75 1 +76 1 +77 1 +78 1 +79 1 +80 1 +81 1 +82 1 +83 1 +84 1 +85 1 +86 1 +87 1 +88 1 +89 1 +90 1 +91 1 +92 1 +93 1 +94 1 +95 1 +96 1 +97 1 +98 1 +99 1 +100 1 + +Bonds +#ID type atom1 atom2 +1 1 1 2 +2 1 1 11 +3 1 1 12 +4 1 2 3 +5 1 2 11 +6 1 2 12 +7 1 2 13 +8 1 3 4 +9 1 3 12 +10 1 3 13 +11 1 3 14 +12 1 4 5 +13 1 4 13 +14 1 4 14 +15 1 4 15 +16 1 5 6 +17 1 5 14 +18 1 5 15 +19 1 5 16 +20 1 6 7 +21 1 6 15 +22 1 6 16 +23 1 6 17 +24 1 7 8 +25 1 7 16 +26 1 7 17 +27 1 7 18 +28 1 8 9 +29 1 8 17 +30 1 8 18 +31 1 8 19 +32 1 9 10 +33 1 9 18 +34 1 9 19 +35 1 9 20 +36 1 10 19 +37 1 10 20 +38 1 11 21 +39 1 11 12 +40 1 11 22 +41 1 12 21 +42 1 12 13 +43 1 12 22 +44 1 12 23 +45 1 13 22 +46 1 13 23 +47 1 13 14 +48 1 13 24 +49 1 14 23 +50 1 14 24 +51 1 14 15 +52 1 14 25 +53 1 15 24 +54 1 15 16 +55 1 15 25 +56 1 15 26 +57 1 16 25 +58 1 16 26 +59 1 16 17 +60 1 16 27 +61 1 17 26 +62 1 17 18 +63 1 17 27 +64 1 17 28 +65 1 18 27 +66 1 18 28 +67 1 18 19 +68 1 18 29 +69 1 19 28 +70 1 19 29 +71 1 19 20 +72 1 19 30 +73 1 20 29 +74 1 20 30 +75 1 21 22 +76 1 21 31 +77 1 21 32 +78 1 22 23 +79 1 22 31 +80 1 22 32 +81 1 22 33 +82 1 23 24 +83 1 23 32 +84 1 23 33 +85 1 23 34 +86 1 24 25 +87 1 24 33 +88 1 24 34 +89 1 24 35 +90 1 25 26 +91 1 25 34 +92 1 25 35 +93 1 25 36 +94 1 26 27 +95 1 26 35 +96 1 26 36 +97 1 26 37 +98 1 27 28 +99 1 27 36 +100 1 27 37 +101 1 27 38 +102 1 28 29 +103 1 28 37 +104 1 28 38 +105 1 28 39 +106 1 29 30 +107 1 29 38 +108 1 29 39 +109 1 29 40 +110 1 30 39 +111 1 30 40 +112 1 31 32 +113 1 31 41 +114 1 31 42 +115 1 32 33 +116 1 32 41 +117 1 32 42 +118 1 32 43 +119 1 33 34 +120 1 33 42 +121 1 33 43 +122 1 33 44 +123 1 34 35 +124 1 34 43 +125 1 34 44 +126 1 34 45 +127 1 35 36 +128 1 35 44 +129 1 35 45 +130 1 35 46 +131 1 36 37 +132 1 36 45 +133 1 36 46 +134 1 36 47 +135 1 37 38 +136 1 37 46 +137 1 37 47 +138 1 37 48 +139 1 38 39 +140 1 38 47 +141 1 38 48 +142 1 38 49 +143 1 39 40 +144 1 39 48 +145 1 39 49 +146 1 39 50 +147 1 40 49 +148 1 40 50 +149 1 41 51 +150 1 41 42 +151 1 41 52 +152 1 42 51 +153 1 42 43 +154 1 42 52 +155 1 42 53 +156 1 43 52 +157 1 43 53 +158 1 43 44 +159 1 43 54 +160 1 44 53 +161 1 44 54 +162 1 44 45 +163 1 44 55 +164 1 45 54 +165 1 45 46 +166 1 45 55 +167 1 45 56 +168 1 46 55 +169 1 46 56 +170 1 46 47 +171 1 46 57 +172 1 47 56 +173 1 47 48 +174 1 47 57 +175 1 47 58 +176 1 48 57 +177 1 48 58 +178 1 48 49 +179 1 48 59 +180 1 49 58 +181 1 49 59 +182 1 49 50 +183 1 49 60 +184 1 50 59 +185 1 50 60 +186 1 51 52 +187 1 51 61 +188 1 51 62 +189 1 52 53 +190 1 52 61 +191 1 52 62 +192 1 52 63 +193 1 53 54 +194 1 53 62 +195 1 53 63 +196 1 53 64 +197 1 54 55 +198 1 54 63 +199 1 54 64 +200 1 54 65 +201 1 55 56 +202 1 55 64 +203 1 55 65 +204 1 55 66 +205 1 56 57 +206 1 56 65 +207 1 56 66 +208 1 56 67 +209 1 57 58 +210 1 57 66 +211 1 57 67 +212 1 57 68 +213 1 58 59 +214 1 58 67 +215 1 58 68 +216 1 58 69 +217 1 59 60 +218 1 59 68 +219 1 59 69 +220 1 59 70 +221 1 60 69 +222 1 60 70 +223 1 61 71 +224 1 61 62 +225 1 61 72 +226 1 62 71 +227 1 62 63 +228 1 62 72 +229 1 62 73 +230 1 63 72 +231 1 63 73 +232 1 63 64 +233 1 63 74 +234 1 64 73 +235 1 64 74 +236 1 64 65 +237 1 64 75 +238 1 65 74 +239 1 65 66 +240 1 65 75 +241 1 65 76 +242 1 66 75 +243 1 66 76 +244 1 66 67 +245 1 66 77 +246 1 67 76 +247 1 67 68 +248 1 67 77 +249 1 67 78 +250 1 68 77 +251 1 68 78 +252 1 68 69 +253 1 68 79 +254 1 69 78 +255 1 69 79 +256 1 69 70 +257 1 69 80 +258 1 70 79 +259 1 70 80 +260 1 71 72 +261 1 71 81 +262 1 71 82 +263 1 72 73 +264 1 72 81 +265 1 72 82 +266 1 72 83 +267 1 73 74 +268 1 73 82 +269 1 73 83 +270 1 73 84 +271 1 74 75 +272 1 74 83 +273 1 74 84 +274 1 74 85 +275 1 75 76 +276 1 75 84 +277 1 75 85 +278 1 75 86 +279 1 76 77 +280 1 76 85 +281 1 76 86 +282 1 76 87 +283 1 77 78 +284 1 77 86 +285 1 77 87 +286 1 77 88 +287 1 78 79 +288 1 78 87 +289 1 78 88 +290 1 78 89 +291 1 79 80 +292 1 79 88 +293 1 79 89 +294 1 79 90 +295 1 80 89 +296 1 80 90 +297 1 81 82 +298 1 81 91 +299 1 81 92 +300 1 82 83 +301 1 82 91 +302 1 82 92 +303 1 82 93 +304 1 83 84 +305 1 83 92 +306 1 83 93 +307 1 83 94 +308 1 84 85 +309 1 84 93 +310 1 84 94 +311 1 84 95 +312 1 85 86 +313 1 85 94 +314 1 85 95 +315 1 85 96 +316 1 86 87 +317 1 86 95 +318 1 86 96 +319 1 86 97 +320 1 87 88 +321 1 87 96 +322 1 87 97 +323 1 87 98 +324 1 88 89 +325 1 88 97 +326 1 88 98 +327 1 88 99 +328 1 89 90 +329 1 89 98 +330 1 89 99 +331 1 89 100 +332 1 90 99 +333 1 90 100 +334 1 91 92 +335 1 92 93 +336 1 93 94 +337 1 94 95 +338 1 95 96 +339 1 96 97 +340 1 97 98 +341 1 98 99 +342 1 99 100 diff --git a/examples/rheo/oxidation/in.rheo.oxidation b/examples/rheo/oxidation/in.rheo.oxidation new file mode 100644 index 0000000000..57bd71b917 --- /dev/null +++ b/examples/rheo/oxidation/in.rheo.oxidation @@ -0,0 +1,102 @@ +# ------ 2D oxidizing bar ------ # + +dimension 2 +units lj +atom_style hybrid rheo/thermal bond +boundary m m p +comm_modify vel yes +newton off + +region box block -60 60 0 80 -0.01 0.01 units box +create_box 3 box bond/types 2 extra/bond/per/atom 20 extra/special/per/atom 50 + +region lbar block -15 0 3 80 EDGE EDGE units box +region rbar block 0 15 3 80 EDGE EDGE units box +region bar union 2 lbar rbar +region floor block EDGE EDGE EDGE 3.0 EDGE EDGE units box + +lattice hex 1.0 +create_atoms 1 region bar +create_atoms 3 region floor + +set region rbar type 2 +group bar type 1 2 +group rbar type 2 +group floor type 3 + +set group all sph/e 0.0 +set group all rheo/status 1 + +# ------ Model parameters ------# + +variable cut equal 3.0 +variable n equal 1.0 +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable zeta equal 0.05 +variable kappa equal 0.1*${rho0}/${mp} +variable dt_max equal 0.1*${cut}/${cs}/3 +variable eta equal 0.05 +variable Cv equal 1.0 +variable L equal 0.1 +variable Tf equal 1.0 + +mass * ${mp} +timestep 0.1 + +pair_style hybrid/overlay rheo ${cut} artificial/visc ${zeta} rheo/solid +pair_coeff * * rheo +pair_coeff * * rheo/solid 1.0 1.0 1.0 + +special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0 +create_bonds many bar bar 1 0 1.5 +special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0 + +bond_style hybrid bpm/spring rheo/shell t/form 100 +bond_coeff 1 bpm/spring 1.0 1.0 1.0 +bond_coeff 2 rheo/shell 0.2 0.2 0.1 + +# ------ Apply dynamics ------# + +# Note: surface detection is not performed on solid bodies, so cannot use surface property +compute coord all rheo/property/atom coordination +variable surf atom c_coord<22 +group surf dynamic all var surf every 10 + +fix 1 all rheo ${cut} quintic 0 & + thermal & + shift & + surface/detection coordination 22 8 +fix 2 all rheo/viscosity * constant ${eta} +fix 3 all rheo/pressure * linear +fix 4 all rheo/thermal conductivity * constant ${kappa} & + specific/heat * constant ${Cv} & + Tfreeze * constant ${Tf} & + latent/heat * constant ${L} & + react 1.5 1 + +fix 5 rbar rheo/oxidation 1.5 2 1.0 +fix 6 all wall/harmonic ylo EDGE 2.0 1.0 1.0 +fix 7 all gravity 5e-5 vector 0 -1 0 +fix 8 floor setforce 0.0 0.0 0.0 +fix 9 surf add/heat linear 1.1 0.05 +fix 10 floor add/heat constant 0 overwrite yes # fix the temperature of the floor +fix 11 all enforce2d + +compute surf all rheo/property/atom surface +compute rho all rheo/property/atom rho +compute phase all rheo/property/atom phase +compute temp all rheo/property/atom temperature +compute eng all rheo/property/atom energy +compute nbond_shell all rheo/property/atom nbond/shell +compute nbond_solid all nbond/atom bond/type 1 + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press atoms + +#dump 1 all custom 200 atomDump id type x y vx vy fx fy c_phase c_temp c_eng c_nbond_solid c_nbond_shell c_rho c_surf + +run 40000 diff --git a/examples/rheo/oxidation/log.17Apr2024.oxidation.g++.4 b/examples/rheo/oxidation/log.17Apr2024.oxidation.g++.4 new file mode 100644 index 0000000000..92eb4aa94a --- /dev/null +++ b/examples/rheo/oxidation/log.17Apr2024.oxidation.g++.4 @@ -0,0 +1,488 @@ +LAMMPS (17 Apr 2024 - Development - patch_5May2020-18508-g3c0eaf6870-modified) +# ------ 2D oxidizing bar ------ # + +dimension 2 +units lj +atom_style hybrid rheo/thermal bond +boundary m m p +comm_modify vel yes +newton off + +region box block -60 60 0 80 -0.01 0.01 units box +create_box 3 box bond/types 2 extra/bond/per/atom 20 extra/special/per/atom 50 +Created orthogonal box = (-60 0 -0.01) to (60 80 0.01) + 2 by 2 by 1 MPI processor grid + +region lbar block -15 0 3 80 EDGE EDGE units box +region rbar block 0 15 3 80 EDGE EDGE units box +region bar union 2 lbar rbar +region floor block EDGE EDGE EDGE 3.0 EDGE EDGE units box + +lattice hex 1.0 +Lattice spacing in x,y,z = 1.0745699 1.8612097 1.0745699 +create_atoms 1 region bar +Created 2255 atoms + using lattice units in orthogonal box = (-60 0 -0.01) to (60 80 0.01) + create_atoms CPU = 0.001 seconds +create_atoms 3 region floor +Created 446 atoms + using lattice units in orthogonal box = (-60 0 -0.01) to (60 80 0.01) + create_atoms CPU = 0.000 seconds + +set region rbar type 2 +Setting atom values ... + 1148 settings made for type +group bar type 1 2 +2255 atoms in group bar +group rbar type 2 +1148 atoms in group rbar +group floor type 3 +446 atoms in group floor + +set group all sph/e 0.0 +Setting atom values ... + 2701 settings made for sph/e +set group all rheo/status 1 +Setting atom values ... + 2701 settings made for rheo/status + +# ------ Model parameters ------# + +variable cut equal 3.0 +variable n equal 1.0 +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable mp equal 1/${n} +variable mp equal 1/1 +variable zeta equal 0.05 +variable kappa equal 0.1*${rho0}/${mp} +variable kappa equal 0.1*1/${mp} +variable kappa equal 0.1*1/1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable dt_max equal 0.1*3/${cs}/3 +variable dt_max equal 0.1*3/1/3 +variable eta equal 0.05 +variable Cv equal 1.0 +variable L equal 0.1 +variable Tf equal 1.0 + +mass * ${mp} +mass * 1 +timestep 0.1 + +pair_style hybrid/overlay rheo ${cut} artificial/visc ${zeta} rheo/solid +pair_style hybrid/overlay rheo 3 artificial/visc ${zeta} rheo/solid +pair_style hybrid/overlay rheo 3 artificial/visc 0.05 rheo/solid +pair_coeff * * rheo +pair_coeff * * rheo/solid 1.0 1.0 1.0 + +special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0 +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 1 1 + special bond factors coul: 0 1 1 + 0 = max # of 1-2 neighbors + 101 = max # of special neighbors + special bonds CPU = 0.000 seconds +create_bonds many bar bar 1 0 1.5 +Generated 0 of 3 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 73 49 1 + 3 neighbor lists, perpetual/occasional/extra = 2 1 0 + (1) command create_bonds, occasional + attributes: full, newton off + pair build: full/bin + stencil: full/bin/2d + bin: standard + (2) pair rheo, perpetual + attributes: half, newton off + pair build: half/bin/newtoff + stencil: full/bin/2d + bin: standard + (3) pair rheo/solid, perpetual, trim from (2) + attributes: half, newton off, cut 1.3 + pair build: trim + stencil: none + bin: none +Added 6547 bonds, new total = 6547 +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 1 1 + special bond factors coul: 0 1 1 + 6 = max # of 1-2 neighbors + 101 = max # of special neighbors + special bonds CPU = 0.000 seconds +special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0 + +bond_style hybrid bpm/spring rheo/shell t/form 100 +bond_coeff 1 bpm/spring 1.0 1.0 1.0 +bond_coeff 2 rheo/shell 0.2 0.2 0.1 + +# ------ Apply dynamics ------# + +# Note: surface detection is not performed on solid bodies, so cannot use surface property +compute coord all rheo/property/atom coordination +variable surf atom c_coord<22 +group surf dynamic all var surf every 10 +dynamic group surf defined + +fix 1 all rheo ${cut} quintic 0 thermal shift surface/detection coordination 22 8 +fix 1 all rheo 3 quintic 0 thermal shift surface/detection coordination 22 8 +fix 2 all rheo/viscosity * constant ${eta} +fix 2 all rheo/viscosity * constant 0.05 +fix 3 all rheo/pressure * linear +fix 4 all rheo/thermal conductivity * constant ${kappa} specific/heat * constant ${Cv} Tfreeze * constant ${Tf} latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.1 specific/heat * constant ${Cv} Tfreeze * constant ${Tf} latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.1 specific/heat * constant 1 Tfreeze * constant ${Tf} latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.1 specific/heat * constant 1 Tfreeze * constant 1 latent/heat * constant ${L} react 1.5 1 +fix 4 all rheo/thermal conductivity * constant 0.1 specific/heat * constant 1 Tfreeze * constant 1 latent/heat * constant 0.1 react 1.5 1 + +fix 5 rbar rheo/oxidation 1.5 2 1.0 +fix 6 all wall/harmonic ylo EDGE 2.0 1.0 1.0 +fix 7 all gravity 5e-5 vector 0 -1 0 +fix 8 floor setforce 0.0 0.0 0.0 +fix 9 surf add/heat linear 1.1 0.05 +fix 10 floor add/heat constant 0 overwrite yes # fix the temperature of the floor +fix 11 all enforce2d + +compute surf all rheo/property/atom surface +compute rho all rheo/property/atom rho +compute phase all rheo/property/atom phase +compute status all rheo/property/atom status +compute temp all rheo/property/atom temperature +compute eng all rheo/property/atom energy +compute nbond_shell all rheo/property/atom nbond/shell +compute nbond_solid all nbond/atom bond/type 1 + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press atoms + +dump 1 all custom 200 atomDump id type x y vx vy fx fy c_phase c_temp c_eng c_nbond_solid c_nbond_shell c_rho c_surf c_status + +run 40000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- BPM bond style: doi:10.1039/D3SM01373A + +@Article{Clemmer2024, + author = {Clemmer, Joel T. and Monti, Joseph M. and Lechman, Jeremy B.}, + title = {A soft departure from jamming: the compaction of deformable + granular matter under high pressures}, + journal = {Soft Matter}, + year = 2024, + volume = 20, + number = 8, + pages = {1702--1718} +} + +- @article{PalermoInPrep, + journal = {in prep}, + title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows}, + year = {2024}, + author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor}, +} + +- @article{ApplMathModel.130.310, + title = {A hybrid smoothed-particle hydrodynamics model of oxide skins on molten aluminum}, + journal = {Applied Mathematical Modelling}, + volume = {130}, + pages = {310-326}, + year = {2024}, + issn = {0307-904X}, + doi = {https://doi.org/10.1016/j.apm.2024.02.027}, + author = {Joel T. Clemmer and Flint Pierce and Thomas C. O'Connor and Thomas D. Nevins and Elizabeth M.C. Jones and Jeremy B. Lechman and John Tencer}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 3 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 73 49 1 + 8 neighbor lists, perpetual/occasional/extra = 7 1 0 + (1) pair rheo, perpetual, half/full from (3) + attributes: half, newton off + pair build: halffull/newtoff + stencil: none + bin: none + (2) pair rheo/solid, perpetual, trim from (4) + attributes: half, newton off, cut 1.3 + pair build: trim + stencil: none + bin: none + (3) compute RHEO/KERNEL, perpetual + attributes: full, newton off + pair build: full/bin + stencil: full/bin/2d + bin: standard + (4) compute RHEO/GRAD, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (5) compute RHEO/VSHIFT, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (6) compute RHEO/SURFACE, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (7) fix rheo/thermal, occasional, trim from (4) + attributes: half, newton off, cut 3 + pair build: trim + stencil: none + bin: none + (8) fix rheo/oxidation, perpetual, trim from (3) + attributes: full, newton off, cut 1.8 + pair build: trim + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 25.96 | 25.96 | 25.96 Mbytes + Step Time KinEng Press Atoms + 0 0 0 0 2701 + 200 20 4.1743799e-07 1.1743617e-07 2701 + 400 40 1.6697519e-06 4.6974469e-07 2701 + 600 60 3.7127333e-06 1.0646825e-05 2701 + 800 80 4.6683656e-06 0.00015182605 2701 + 1000 100 4.7368707e-06 0.00028128761 2701 + 1200 120 3.4384322e-06 0.00045913378 2701 + 1400 140 1.4119866e-06 0.00055627091 2701 + 1600 160 4.4114517e-07 0.00058247308 2701 + 1800 180 4.8289229e-07 0.0005510948 2701 + 2000 200 1.8494183e-06 0.00048386222 2701 + 2200 220 3.3319816e-06 0.00037903264 2701 + 2400 240 3.8128922e-06 0.00024115906 2701 + 2600 260 3.1943401e-06 9.727407e-05 2701 + 2800 280 1.6172816e-06 -2.632162e-05 2701 + 3000 300 3.6100709e-07 -8.5761867e-05 2701 + 3200 320 1.4745502e-07 -5.9204127e-05 2701 + 3400 340 8.3369782e-07 8.8312464e-07 2701 + 3600 360 2.0484052e-06 5.8521477e-05 2701 + 3800 380 3.1639387e-06 0.0001685663 2701 + 4000 400 3.1692907e-06 0.00026875988 2701 + 4200 420 2.391933e-06 0.00038621787 2701 + 4400 440 1.1964404e-06 0.00048901286 2701 + 4600 460 4.0508824e-07 0.00051863639 2701 + 4800 480 5.4908507e-07 0.00049263754 2701 + 5000 500 1.3139665e-06 0.00041984264 2701 + 5200 520 2.1939161e-06 0.00033095351 2701 + 5400 540 2.3687031e-06 0.00022422981 2701 + 5600 560 1.8280882e-06 0.00011544328 2701 + 5800 580 8.8610517e-07 2.9307791e-05 2701 + 6000 600 2.0989359e-07 -1.7340941e-05 2701 + 6200 620 2.8658301e-07 -8.1237835e-06 2701 + 6400 640 9.7636239e-07 4.3755922e-05 2701 + 6600 660 1.891303e-06 0.0001185719 2701 + 6800 680 2.4149904e-06 0.00020830273 2701 + 7000 700 2.3174953e-06 0.00030114767 2701 + 7200 720 1.7918612e-06 0.00037821537 2701 + 7400 740 1.2114987e-06 0.0004233475 2701 + 7600 760 9.9661553e-07 0.00042958263 2701 + 7800 780 1.1552559e-06 0.00039944618 2701 + 8000 800 1.5249138e-06 0.00034034478 2701 + 8200 820 1.7453861e-06 0.00026826463 2701 + 8400 840 1.6259021e-06 0.00019131768 2701 + 8600 860 1.2612805e-06 0.0001162957 2701 + 8800 880 8.6964518e-07 7.1771506e-05 2701 + 9000 900 7.6892472e-07 5.6170687e-05 2701 + 9200 920 1.0780045e-06 7.1925995e-05 2701 + 9400 940 1.6514902e-06 0.00011635293 2701 + 9600 960 2.1891377e-06 0.00017599885 2701 + 9800 980 2.4551701e-06 0.00024127934 2701 + 10000 1000 2.4277051e-06 0.00029918622 2701 + 10200 1020 2.2655987e-06 0.00034067996 2701 + 10400 1040 2.1767207e-06 0.00035598133 2701 + 10600 1060 2.2796719e-06 0.00034359076 2701 + 10800 1080 2.4884225e-06 0.00030749714 2701 + 11000 1100 2.6387215e-06 0.00025725198 2701 + 11200 1120 2.5968908e-06 0.00020170699 2701 + 11400 1140 2.4108931e-06 0.00015185858 2701 + 11600 1160 2.2375166e-06 0.00011800349 2701 + 11800 1180 2.2407196e-06 0.00010646971 2701 + 12000 1200 2.4845263e-06 0.00011817498 2701 + 12200 1220 2.8733204e-06 0.00015013186 2701 + 12400 1240 3.2437087e-06 0.00019211975 2701 + 12600 1260 3.4732728e-06 0.00023620276 2701 + 12800 1280 3.5836611e-06 0.00027352269 2701 + 13000 1300 3.6592211e-06 0.00029533734 2701 + 13200 1320 3.782506e-06 0.00030032559 2701 + 13400 1340 3.9807086e-06 0.00028395722 2701 + 13600 1360 4.2023176e-06 0.00025390325 2701 + 13800 1380 4.3559781e-06 0.00021794236 2701 + 14000 1400 4.4273371e-06 0.00018026034 2701 + 14200 1420 4.49867e-06 0.0001526569 2701 + 14400 1440 4.6591574e-06 0.00013707051 2701 + 14600 1460 4.9589583e-06 0.00013803875 2701 + 14800 1480 5.3859375e-06 0.00015455425 2701 + 15000 1500 5.8639557e-06 0.00017954785 2701 + 15200 1520 6.3075561e-06 0.0002084257 2701 + 15400 1540 6.7022179e-06 0.0002347669 2701 + 15600 1560 7.0789688e-06 0.00025020766 2701 + 15800 1580 7.4734777e-06 0.00025394845 2701 + 16000 1600 7.8884743e-06 0.00024571725 2701 + 16200 1620 8.3224059e-06 0.00022706648 2701 + 16400 1640 8.7337783e-06 0.00020320706 2701 + 16600 1660 9.1454649e-06 0.00017824346 2701 + 16800 1680 9.5948793e-06 0.00015961835 2701 + 17000 1700 1.0106407e-05 0.00015135471 2701 + 17200 1720 1.0707273e-05 0.00015166884 2701 + 17400 1740 1.1392597e-05 0.0001645916 2701 + 17600 1760 1.2118829e-05 0.00018119729 2701 + 17800 1780 1.2846056e-05 0.0002003616 2701 + 18000 1800 1.3555288e-05 0.00021585952 2701 + 18200 1820 1.4301024e-05 0.00022290158 2701 + 18400 1840 1.5089217e-05 0.00021970192 2701 + 18600 1860 1.5902351e-05 0.00020911128 2701 + 18800 1880 1.6753175e-05 0.00019278718 2701 + 19000 1900 1.7602996e-05 0.00017584076 2701 + 19200 1920 1.8479378e-05 0.00016206226 2701 + 19400 1940 1.9421603e-05 0.00015575677 2701 + 19600 1960 2.0477421e-05 0.00015687558 2701 + 19800 1980 2.1617288e-05 0.00016424998 2701 + 20000 2000 2.2814347e-05 0.00017466664 2701 + 20200 2020 2.4029097e-05 0.00018647149 2701 + 20400 2040 2.5255953e-05 0.00019516077 2701 + 20600 2060 2.649418e-05 0.00019906384 2701 + 20800 2080 2.7755897e-05 0.00019630586 2701 + 21000 2100 2.9067854e-05 0.00018674721 2701 + 21200 2120 3.0396477e-05 0.0001758048 2701 + 21400 2140 3.1759719e-05 0.00016782801 2701 + 21600 2160 3.3193597e-05 0.00016324138 2701 + 21800 2180 3.4729384e-05 0.00016124274 2701 + 22000 2200 3.6367594e-05 0.00016437457 2701 + 22200 2220 3.8095131e-05 0.00017015573 2701 + 22400 2240 3.9867003e-05 0.00017649465 2701 + 22600 2260 4.169511e-05 0.00018111374 2701 + 22800 2280 4.3566134e-05 0.00018104136 2701 + 23000 2300 4.5461538e-05 0.00017822707 2701 + 23200 2320 4.7377333e-05 0.00017285066 2701 + 23400 2340 4.9354403e-05 0.00016826524 2701 + 23600 2360 5.1399791e-05 0.00016517913 2701 + 23800 2380 5.3510931e-05 0.00016299649 2701 + 24000 2400 5.5681048e-05 0.00016256674 2701 + 24200 2420 5.7902429e-05 0.00016513449 2701 + 24400 2440 6.0216049e-05 0.00016895109 2701 + 24600 2460 6.270982e-05 0.00016946227 2701 + 24800 2480 6.5390117e-05 0.00016589426 2701 + 25000 2500 6.8121899e-05 0.00016241676 2701 + 25200 2520 7.0947331e-05 0.00015624292 2701 + 25400 2540 7.4304148e-05 0.0001449537 2701 + 25600 2560 7.7745077e-05 0.00013179658 2701 + 25800 2580 8.0739829e-05 0.00013098838 2701 + 26000 2600 8.3827874e-05 0.00014278841 2701 + 26200 2620 8.7060677e-05 0.00015381649 2701 + 26400 2640 9.0266508e-05 0.00016130999 2701 + 26600 2660 9.3339049e-05 0.00016908268 2701 + 26800 2680 9.6347013e-05 0.00016771087 2701 + 27000 2700 9.9294711e-05 0.00016577315 2701 + 27200 2720 0.00010230007 0.0001670893 2701 + 27400 2740 0.00010547172 0.00016569077 2701 + 27600 2760 0.00010872426 0.00016506303 2701 + 27800 2780 0.00011201844 0.00016482702 2701 + 28000 2800 0.00011532129 0.00016694886 2701 + 28200 2820 0.00011869854 0.00016163005 2701 + 28400 2840 0.00012209747 0.00015339281 2701 + 28600 2860 0.00012549322 0.00014765883 2701 + 28800 2880 0.00012898685 0.00014241765 2701 + 29000 2900 0.00013259039 0.00014215724 2701 + 29200 2920 0.00013628209 0.00014881155 2701 + 29400 2940 0.00014001213 0.00015671333 2701 + 29600 2960 0.00014379216 0.00016446215 2701 + 29800 2980 0.00014764687 0.0001639602 2701 + 30000 3000 0.00015142301 0.00015664816 2701 + 30200 3020 0.00015496407 0.00015545099 2701 + 30400 3040 0.00015797338 0.00015368625 2701 + 30600 3060 0.00016042141 0.00015679918 2701 + 30800 3080 0.00016244716 0.00016093678 2701 + 31000 3100 0.00016202247 0.00016066954 2701 + 31200 3120 0.0001613312 0.00015932059 2701 + 31400 3140 0.00016274961 0.00015988567 2701 + 31600 3160 0.00016541518 0.00015724809 2701 + 31800 3180 0.00016809362 0.00015498827 2701 + 32000 3200 0.00017067801 0.00014830489 2701 + 32200 3220 0.00017333906 0.00014371345 2701 + 32400 3240 0.0001759011 0.00014421259 2701 + 32600 3260 0.00017849952 0.00014228443 2701 + 32800 3280 0.00017801812 0.00014117391 2701 + 33000 3300 0.00017718857 0.00014644675 2701 + 33200 3320 0.00017833666 0.0001291286 2701 + 33400 3340 0.000178576 0.00014878558 2701 + 33600 3360 0.00017846711 0.00013905481 2701 + 33800 3380 0.00017822937 0.00015535996 2701 + 34000 3400 0.00017899663 0.00016094303 2701 + 34200 3420 0.00017924661 0.00015017553 2701 + 34400 3440 0.00018024855 0.00014723549 2701 + 34600 3460 0.00018143865 0.00013903131 2701 + 34800 3480 0.00018258173 0.00013722112 2701 + 35000 3500 0.00018404873 0.00014675949 2701 + 35200 3520 0.00018538521 0.00015108242 2701 + 35400 3540 0.00018669649 0.00014564852 2701 + 35600 3560 0.00018814608 0.00013762161 2701 + 35800 3580 0.00018967415 0.00014602307 2701 + 36000 3600 0.00019146735 0.000126909 2701 + 36200 3620 0.00019414036 0.00012384379 2701 + 36400 3640 0.00019613057 0.00011059573 2701 + 36600 3660 0.00019897104 0.00013621801 2701 + 36800 3680 0.00020169688 0.00013665462 2701 + 37000 3700 0.00020447655 0.00013929258 2701 + 37200 3720 0.00020711105 0.0001363895 2701 + 37400 3740 0.00021077854 0.00013610672 2701 + 37600 3760 0.00021303084 0.00015051235 2701 + 37800 3780 0.00021619561 0.00012664801 2701 + 38000 3800 0.0002194018 0.00012808247 2701 + 38200 3820 0.00022242646 0.0001360174 2701 + 38400 3840 0.00022531568 0.00013311221 2701 + 38600 3860 0.00022821731 0.00013523939 2701 + 38800 3880 0.000231228 0.00014090695 2701 + 39000 3900 0.00023404038 0.00013661835 2701 + 39200 3920 0.00023755044 0.00013659469 2701 + 39400 3940 0.00024009059 0.00012097907 2701 + 39600 3960 0.0002432098 9.7877876e-05 2701 + 39800 3980 0.00024475294 0.0001164688 2701 + 40000 4000 0.00024171274 0.00012432219 2701 +Loop time of 192.659 on 4 procs for 40000 steps with 2701 atoms + +Performance: 1793840.118 tau/day, 207.620 timesteps/s, 560.783 katom-step/s +99.6% CPU use with 4 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 16.881 | 24.402 | 30.74 | 114.6 | 12.67 +Bond | 1.1126 | 1.8917 | 2.6935 | 43.3 | 0.98 +Neigh | 35.387 | 35.508 | 35.625 | 1.5 | 18.43 +Comm | 1.5499 | 1.6694 | 1.8006 | 7.4 | 0.87 +Output | 0.99755 | 1.0072 | 1.0165 | 0.8 | 0.52 +Modify | 120.6 | 127.43 | 135.54 | 54.8 | 66.14 +Other | | 0.7553 | | | 0.39 + +Nlocal: 675.25 ave 1373 max 7 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 103 ave 163 max 50 min +Histogram: 2 0 0 0 0 0 0 0 1 1 +Neighs: 10509 ave 21592 max 126 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +FullNghs: 20367 ave 41981 max 141 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 81468 +Ave neighs/atom = 30.162162 +Ave special neighs/atom = 1.6593854 +Neighbor list builds = 39932 +Dangerous builds = 0 + +Total wall time: 0:03:12 diff --git a/examples/rheo/poiseuille/in.rheo.poiseuille b/examples/rheo/poiseuille/in.rheo.poiseuille new file mode 100644 index 0000000000..ec283d9a00 --- /dev/null +++ b/examples/rheo/poiseuille/in.rheo.poiseuille @@ -0,0 +1,75 @@ +# ------ 2D Poiseuille flow ------ # + +dimension 2 +units lj +atom_style rheo +boundary p p p +comm_modify vel yes + +# ------ Create simulation box ------ # + +variable n equal 1.0 +variable cut equal 3.0 + +region box block 0 20 -10 10 -0.01 0.01 +create_box 2 box +lattice sq ${n} + +region inner block INF INF -7.5 7.5 INF INF units box +region walls block INF INF -7.5 7.5 INF INF units box side out + +create_atoms 2 region walls +create_atoms 1 region inner + +group fluid type 1 +group rig type 2 + +displace_atoms fluid random 0.1 0.1 0 135414 units box + +# ------ Model parameters ------ # + +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable zeta equal 1.0 +variable kappa equal 1.0*${rho0}/${mp} +variable fext equal 1e-4/${n} +variable dt_max equal 0.1*${cut}/${cs}/3 +variable Dr equal 0.05*${cut}*${cs} + +variable eta equal 0.1 +variable gd0 equal 5e-4 +variable npow equal 0.5 +variable K equal 0.001 + +mass * ${mp} +set group all rheo/rho ${rho0} +set group all rheo/status 0 +set group rig rheo/status 1 + +timestep ${dt_max} + +pair_style rheo ${cut} artificial/visc ${zeta} rho/damp ${Dr} +pair_coeff * * + +# ------ Fixes & computes ------ # + +fix 1 all rheo ${cut} quintic 0 shift +fix 2 all rheo/viscosity * constant ${eta} +#fix 2 all rheo/viscosity * power ${eta} ${gd0} ${K} ${npow} +fix 3 all rheo/pressure * linear +fix 4 rig setforce 0.0 0.0 0.0 +fix 5 fluid addforce ${fext} 0.0 0.0 +fix 6 all enforce2d + +compute rho all rheo/property/atom rho + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press + +#dump 1 all custom 200 atomDump id type x y vx vy fx fy c_rho + +run 20000 + diff --git a/examples/rheo/poiseuille/log.17Apr2024.poiseuille.g++.4 b/examples/rheo/poiseuille/log.17Apr2024.poiseuille.g++.4 new file mode 100644 index 0000000000..1fd8377b7a --- /dev/null +++ b/examples/rheo/poiseuille/log.17Apr2024.poiseuille.g++.4 @@ -0,0 +1,288 @@ +LAMMPS (17 Apr 2024 - Development - patch_5May2020-18508-g3c0eaf6870-modified) +# ------ 2D Poiseuille flow ------ # + +dimension 2 +units lj +atom_style rheo +boundary p p p +comm_modify vel yes + +# ------ Create simulation box ------ # + +variable n equal 1.0 +variable cut equal 3.0 + +region box block 0 20 -10 10 -0.01 0.01 +create_box 2 box +Created orthogonal box = (0 -10 -0.01) to (20 10 0.01) + 2 by 2 by 1 MPI processor grid +lattice sq ${n} +lattice sq 1 +Lattice spacing in x,y,z = 1 1 1 + +region inner block INF INF -7.5 7.5 INF INF units box +region walls block INF INF -7.5 7.5 INF INF units box side out + +create_atoms 2 region walls +Created 100 atoms + using lattice units in orthogonal box = (0 -10 -0.01) to (20 10 0.01) + create_atoms CPU = 0.000 seconds +create_atoms 1 region inner +Created 300 atoms + using lattice units in orthogonal box = (0 -10 -0.01) to (20 10 0.01) + create_atoms CPU = 0.000 seconds + +group fluid type 1 +300 atoms in group fluid +group rig type 2 +100 atoms in group rig + +displace_atoms fluid random 0.1 0.1 0 135414 units box +Displacing atoms ... + +# ------ Model parameters ------ # + +variable rho0 equal 1.0 +variable cs equal 1.0 +variable mp equal ${rho0}/${n} +variable mp equal 1/${n} +variable mp equal 1/1 +variable zeta equal 1.0 +variable kappa equal 1.0*${rho0}/${mp} +variable kappa equal 1.0*1/${mp} +variable kappa equal 1.0*1/1 +variable fext equal 1e-4/${n} +variable fext equal 1e-4/1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable dt_max equal 0.1*3/${cs}/3 +variable dt_max equal 0.1*3/1/3 +variable Dr equal 0.05*${cut}*${cs} +variable Dr equal 0.05*3*${cs} +variable Dr equal 0.05*3*1 + +variable eta equal 0.1 +variable gd0 equal 5e-4 +variable npow equal 0.5 +variable K equal 0.001 + +mass * ${mp} +mass * 1 +set group all rheo/rho ${rho0} +set group all rheo/rho 1 +Setting atom values ... + 400 settings made for rheo/rho +set group all rheo/status 0 +Setting atom values ... + 400 settings made for rheo/status +set group rig rheo/status 1 +Setting atom values ... + 100 settings made for rheo/status + +timestep ${dt_max} +timestep 0.1 + +pair_style rheo ${cut} artificial/visc ${zeta} rho/damp ${Dr} +pair_style rheo 3 artificial/visc ${zeta} rho/damp ${Dr} +pair_style rheo 3 artificial/visc 1 rho/damp ${Dr} +pair_style rheo 3 artificial/visc 1 rho/damp 0.15 +pair_coeff * * + +# ------ Fixes & computes ------ # + +fix 1 all rheo ${cut} quintic 0 shift +fix 1 all rheo 3 quintic 0 shift +fix 2 all rheo/viscosity * constant ${eta} +fix 2 all rheo/viscosity * constant 0.1 +#fix 2 all rheo/viscosity * power ${eta} ${gd0} ${K} ${npow} +fix 3 all rheo/pressure * linear +fix 4 rig setforce 0.0 0.0 0.0 +fix 5 fluid addforce ${fext} 0.0 0.0 +fix 5 fluid addforce 0.0001 0.0 0.0 +fix 6 all enforce2d + +compute rho all rheo/property/atom rho + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press + +dump 1 all custom 200 atomDump id type x y vx vy fx fy c_rho + +run 20000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- @article{PalermoInPrep, + journal = {in prep}, + title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows}, + year = {2024}, + author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 1 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 13 13 1 + 4 neighbor lists, perpetual/occasional/extra = 4 0 0 + (1) pair rheo, perpetual, half/full from (2) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none + (2) compute RHEO/KERNEL, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/2d + bin: standard + (3) compute RHEO/GRAD, perpetual, copy from (1) + attributes: half, newton on + pair build: copy + stencil: none + bin: none + (4) compute RHEO/VSHIFT, perpetual, copy from (1) + attributes: half, newton on + pair build: copy + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 5.693 | 5.693 | 5.693 Mbytes + Step Time KinEng Press + 0 0 0 0 + 200 20 1.2220462e-06 3.7383146e-05 + 400 40 4.345762e-06 7.5866885e-05 + 600 60 8.8559433e-06 0.00011353743 + 800 80 1.4370506e-05 0.00015135634 + 1000 100 2.0576198e-05 0.00018903722 + 1200 120 2.721926e-05 0.00022533997 + 1400 140 3.4099653e-05 0.00026016069 + 1600 160 4.1064175e-05 0.00029445207 + 1800 180 4.8001225e-05 0.00032893763 + 2000 200 5.4832849e-05 0.00036402396 + 2200 220 6.1508431e-05 0.00039945249 + 2400 240 6.8000141e-05 0.00043534411 + 2600 260 7.430136e-05 0.00046943441 + 2800 280 8.0415328e-05 0.00049807225 + 3000 300 8.6335032e-05 0.00051815375 + 3200 320 9.2021626e-05 0.00052618224 + 3400 340 9.7387936e-05 0.00051877918 + 3600 360 0.00010231526 0.00048650828 + 3800 380 0.00010676617 0.00044578079 + 4000 400 0.00011080098 0.00044777126 + 4200 420 0.00011448127 0.00047047629 + 4400 440 0.00011787852 0.00050280249 + 4600 460 0.00012106805 0.0005397213 + 4800 480 0.00012412056 0.00057885539 + 5000 500 0.0001271078 0.00061396896 + 5200 520 0.00013006637 0.00063981812 + 5400 540 0.00013295039 0.00065094073 + 5600 560 0.00013561487 0.00063918847 + 5800 580 0.00013791796 0.00059087656 + 6000 600 0.00013983422 0.00052171998 + 6200 620 0.00014144833 0.00050658002 + 6400 640 0.00014286538 0.0005248626 + 6600 660 0.00014417734 0.00055826606 + 6800 680 0.00014546931 0.00060063748 + 7000 700 0.00014682553 0.00064421411 + 7200 720 0.0001482833 0.00068252242 + 7400 740 0.00014977996 0.00070671308 + 7600 760 0.00015114829 0.00069774026 + 7800 780 0.0001522719 0.00064408311 + 8000 800 0.00015312897 0.00055977044 + 8200 820 0.00015375669 0.0005225573 + 8400 840 0.00015425683 0.00053833691 + 8600 860 0.00015471278 0.00057447427 + 8800 880 0.0001552059 0.00061980921 + 9000 900 0.00015581593 0.0006659836 + 9200 920 0.0001565564 0.00070813532 + 9400 940 0.00015733573 0.00073378551 + 9600 960 0.00015802107 0.00071560835 + 9800 980 0.00015855339 0.00065636189 + 10000 1000 0.00015890743 0.0005699855 + 10200 1020 0.00015908095 0.00053138971 + 10400 1040 0.00015915523 0.00054790708 + 10600 1060 0.00015921254 0.00058899454 + 10800 1080 0.00015934193 0.00063964906 + 11000 1100 0.00015959891 0.00069241358 + 11200 1120 0.0001599636 0.00073734651 + 11400 1140 0.00016036526 0.00074477329 + 11600 1160 0.00016075471 0.00071047555 + 11800 1180 0.00016109516 0.00064173183 + 12000 1200 0.00016131524 0.00055500553 + 12200 1220 0.00016136366 0.0005290215 + 12400 1240 0.0001613025 0.00055124296 + 12600 1260 0.00016123023 0.00059758627 + 12800 1280 0.00016123043 0.00065488735 + 13000 1300 0.00016132935 0.0007140876 + 13200 1320 0.00016152165 0.00074795629 + 13400 1340 0.00016180372 0.00074730778 + 13600 1360 0.00016216585 0.00071370995 + 13800 1380 0.0001625339 0.00065176323 + 14000 1400 0.00016274999 0.00057515371 + 14200 1420 0.00016271295 0.00055878258 + 14400 1440 0.00016249768 0.00058448193 + 14600 1460 0.00016223675 0.00063096229 + 14800 1480 0.00016201846 0.00068639548 + 15000 1500 0.00016190593 0.00072444357 + 15200 1520 0.00016194466 0.00073830636 + 15400 1540 0.00016216164 0.00072773256 + 15600 1560 0.00016253174 0.00069215481 + 15800 1580 0.00016290895 0.00063239408 + 16000 1600 0.00016306463 0.00057466273 + 16200 1620 0.00016292218 0.00057951567 + 16400 1640 0.00016261117 0.00061504156 + 16600 1660 0.00016225906 0.00066066637 + 16800 1680 0.00016197993 0.00069751908 + 17000 1700 0.0001618568 0.00072202303 + 17200 1720 0.00016194264 0.00073255034 + 17400 1740 0.00016225911 0.0007231031 + 17600 1760 0.00016270465 0.00068931224 + 17800 1780 0.00016304053 0.00062934836 + 18000 1800 0.00016302624 0.00058060272 + 18200 1820 0.00016274847 0.00058859513 + 18400 1840 0.00016236893 0.00061804803 + 18600 1860 0.00016202777 0.00065393237 + 18800 1880 0.0001618184 0.00068747094 + 19000 1900 0.0001618044 0.00071352541 + 19200 1920 0.00016204402 0.00072351769 + 19400 1940 0.00016249999 0.00071330322 + 19600 1960 0.00016297924 0.00067984167 + 19800 1980 0.00016317435 0.00061634142 + 20000 2000 0.00016301186 0.00057234115 +Loop time of 15.6198 on 4 procs for 20000 steps with 400 atoms + +Performance: 11062881.511 tau/day, 1280.426 timesteps/s, 512.170 katom-step/s +99.7% CPU use with 4 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 2.1979 | 2.4473 | 2.6992 | 15.7 | 15.67 +Neigh | 0.024709 | 0.027006 | 0.029223 | 1.3 | 0.17 +Comm | 0.4657 | 0.71686 | 0.9662 | 29.0 | 4.59 +Output | 0.033698 | 0.036781 | 0.039359 | 1.1 | 0.24 +Modify | 12.306 | 12.313 | 12.319 | 0.2 | 78.83 +Other | | 0.07916 | | | 0.51 + +Nlocal: 100 ave 107 max 93 min +Histogram: 1 0 0 1 0 0 1 0 0 1 +Nghost: 185.5 ave 192 max 179 min +Histogram: 1 0 0 1 0 0 1 0 0 1 +Neighs: 1712 ave 1848 max 1598 min +Histogram: 1 0 1 0 0 1 0 0 0 1 +FullNghs: 3424 ave 3682 max 3174 min +Histogram: 1 0 1 0 0 0 1 0 0 1 + +Total # of neighbors = 13696 +Ave neighs/atom = 34.24 +Neighbor list builds = 331 +Dangerous builds = 0 + + +Total wall time: 0:00:15 diff --git a/examples/rheo/taylor-green/in.rheo.taylor.green b/examples/rheo/taylor-green/in.rheo.taylor.green new file mode 100644 index 0000000000..4485387440 --- /dev/null +++ b/examples/rheo/taylor-green/in.rheo.taylor.green @@ -0,0 +1,65 @@ +# ------ 2D Taylor Green vortex ------ # + +dimension 2 +units lj +atom_style rheo +boundary p p p +comm_modify vel yes +newton off + +# ------ Create simulation box ------ # + +variable n equal 1.0 +variable cut equal 3.0 + +region box block 0 40 0 40 -0.01 0.01 +create_box 1 box +lattice sq ${n} + +create_atoms 1 region box + +displace_atoms all random 0.1 0.1 0 135414 units box + +# ------ Model parameters ------ # + +variable rho0 equal 1.0 +variable mp equal ${rho0}/${n} +variable cs equal 1.0 +variable eta equal 0.05 +variable zeta equal 1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable Dr equal 0.1*${cut}*${cs} + +mass * ${mp} +set group all rheo/rho ${rho0} +set group all rheo/status 0 + +variable u0 equal 0.05 +variable uy atom ${u0}*sin(2*PI*x/lx)*cos(2*PI*y/ly) +variable ux atom -${u0}*sin(2*PI*y/ly)*cos(2*PI*x/ly) +variable d0 atom ${rho0}-${u0}*${u0}*${rho0}*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/${cs}/${cs} + +velocity all set v_ux v_uy 0.0 units box + +timestep ${dt_max} + +pair_style rheo ${cut} artificial/visc ${zeta} rho/damp ${Dr} +pair_coeff * * + +# ------ Fixes & computes ------ # + +fix 1 all rheo ${cut} RK1 8 shift +fix 2 all rheo/viscosity * constant ${eta} +fix 3 all rheo/pressure * linear +fix 4 all enforce2d + +compute rho all rheo/property/atom rho + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press + +#dump 1 all custom 200 atomDump id type x y vx vy fx fy c_rho + +run 10000 \ No newline at end of file diff --git a/examples/rheo/taylor-green/log.17Apr2024.taylor.green.g++.4 b/examples/rheo/taylor-green/log.17Apr2024.taylor.green.g++.4 new file mode 100644 index 0000000000..6daf4a6eee --- /dev/null +++ b/examples/rheo/taylor-green/log.17Apr2024.taylor.green.g++.4 @@ -0,0 +1,224 @@ +LAMMPS (17 Apr 2024 - Development - patch_5May2020-18508-g3c0eaf6870-modified) +# ------ 2D Taylor Green vortex ------ # + +dimension 2 +units lj +atom_style rheo +boundary p p p +comm_modify vel yes +newton off + +# ------ Create simulation box ------ # + +variable n equal 1.0 +variable cut equal 3.0 + +region box block 0 40 0 40 -0.01 0.01 +create_box 1 box +Created orthogonal box = (0 0 -0.01) to (40 40 0.01) + 2 by 2 by 1 MPI processor grid +lattice sq ${n} +lattice sq 1 +Lattice spacing in x,y,z = 1 1 1 + +create_atoms 1 region box +Created 1600 atoms + using lattice units in orthogonal box = (0 0 -0.01) to (40 40 0.01) + create_atoms CPU = 0.001 seconds + +displace_atoms all random 0.1 0.1 0 135414 units box +Displacing atoms ... + +# ------ Model parameters ------ # + +variable rho0 equal 1.0 +variable mp equal ${rho0}/${n} +variable mp equal 1/${n} +variable mp equal 1/1 +variable cs equal 1.0 +variable eta equal 0.05 +variable zeta equal 1 +variable dt_max equal 0.1*${cut}/${cs}/3 +variable dt_max equal 0.1*3/${cs}/3 +variable dt_max equal 0.1*3/1/3 +variable Dr equal 0.1*${cut}*${cs} +variable Dr equal 0.1*3*${cs} +variable Dr equal 0.1*3*1 + +mass * ${mp} +mass * 1 +set group all rheo/rho ${rho0} +set group all rheo/rho 1 +Setting atom values ... + 1600 settings made for rheo/rho +set group all rheo/status 0 +Setting atom values ... + 1600 settings made for rheo/status + +variable u0 equal 0.05 +variable uy atom ${u0}*sin(2*PI*x/lx)*cos(2*PI*y/ly) +variable uy atom 0.05*sin(2*PI*x/lx)*cos(2*PI*y/ly) +variable ux atom -${u0}*sin(2*PI*y/ly)*cos(2*PI*x/ly) +variable ux atom -0.05*sin(2*PI*y/ly)*cos(2*PI*x/ly) +variable d0 atom ${rho0}-${u0}*${u0}*${rho0}*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/${cs}/${cs} +variable d0 atom 1-${u0}*${u0}*${rho0}*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/${cs}/${cs} +variable d0 atom 1-0.05*${u0}*${rho0}*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/${cs}/${cs} +variable d0 atom 1-0.05*0.05*${rho0}*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/${cs}/${cs} +variable d0 atom 1-0.05*0.05*1*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/${cs}/${cs} +variable d0 atom 1-0.05*0.05*1*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/1/${cs} +variable d0 atom 1-0.05*0.05*1*0.25*(cos(4*PI*x/lx)+cos(4*PI*y/ly))/1/1 + +velocity all set v_ux v_uy 0.0 units box + +timestep ${dt_max} +timestep 0.1 + +pair_style rheo ${cut} artificial/visc ${zeta} rho/damp ${Dr} +pair_style rheo 3 artificial/visc ${zeta} rho/damp ${Dr} +pair_style rheo 3 artificial/visc 1 rho/damp ${Dr} +pair_style rheo 3 artificial/visc 1 rho/damp 0.3 +pair_coeff * * + +# ------ Fixes & computes ------ # + +fix 1 all rheo ${cut} RK1 8 shift +fix 1 all rheo 3 RK1 8 shift +fix 2 all rheo/viscosity * constant ${eta} +fix 2 all rheo/viscosity * constant 0.05 +fix 3 all rheo/pressure * linear +fix 4 all enforce2d + +compute rho all rheo/property/atom rho + +# ------ Output & Run ------ # + +thermo 200 +thermo_style custom step time ke press + +dump 1 all custom 200 atomDump id type x y vx vy fx fy c_rho + +run 10000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- @article{PalermoInPrep, + journal = {in prep}, + title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows}, + year = {2024}, + author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.3 + ghost atom cutoff = 3.3 + binsize = 1.65, bins = 25 25 1 + 4 neighbor lists, perpetual/occasional/extra = 4 0 0 + (1) pair rheo, perpetual, half/full from (2) + attributes: half, newton off + pair build: halffull/newtoff + stencil: none + bin: none + (2) compute RHEO/KERNEL, perpetual + attributes: full, newton off + pair build: full/bin/atomonly + stencil: full/bin/2d + bin: standard + (3) compute RHEO/GRAD, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none + (4) compute RHEO/VSHIFT, perpetual, copy from (1) + attributes: half, newton off + pair build: copy + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 6.835 | 6.835 | 6.835 Mbytes + Step Time KinEng Press + 0 0 0.00062497276 0.00062607301 + 200 20 0.00056200647 0.00056633785 + 400 40 0.00050570968 0.00051098771 + 600 60 0.00045586684 0.00046081672 + 800 80 0.00041124523 0.00041549607 + 1000 100 0.00037065341 0.00037412741 + 1200 120 0.00033391585 0.00033580899 + 1400 140 0.00030078316 0.00030057307 + 1600 160 0.00027093231 0.00026842603 + 1800 180 0.00024403239 0.00023839026 + 2000 200 0.0002197865 0.00021148941 + 2200 220 0.0001979269 0.00018659386 + 2400 240 0.00017822267 0.00016430442 + 2600 260 0.00016047141 0.00014408514 + 2800 280 0.00014448504 0.00012574125 + 3000 300 0.00013009159 0.00010869938 + 3200 320 0.00011713578 9.414951e-05 + 3400 340 0.00010547564 8.1900579e-05 + 3600 360 9.4982139e-05 7.1285649e-05 + 3800 380 8.5538983e-05 6.1571123e-05 + 4000 400 7.7040171e-05 5.3462572e-05 + 4200 420 6.9390317e-05 4.6338308e-05 + 4400 440 6.2503763e-05 3.9697323e-05 + 4600 460 5.6303766e-05 3.4234465e-05 + 4800 480 5.0721595e-05 3.0841338e-05 + 5000 500 4.5695301e-05 2.7788566e-05 + 5200 520 4.1169161e-05 2.5744409e-05 + 5400 540 3.7093059e-05 2.3912739e-05 + 5600 560 3.3421819e-05 2.2494185e-05 + 5800 580 3.0114735e-05 2.1594384e-05 + 6000 600 2.7135224e-05 2.1164421e-05 + 6200 620 2.4450446e-05 2.0979349e-05 + 6400 640 2.2030925e-05 2.0858567e-05 + 6600 660 1.9850196e-05 2.098115e-05 + 6800 680 1.7884553e-05 2.1134827e-05 + 7000 700 1.6112763e-05 2.1242242e-05 + 7200 720 1.4515783e-05 2.1312763e-05 + 7400 740 1.3076456e-05 2.1370947e-05 + 7600 760 1.1779327e-05 2.1332126e-05 + 7800 780 1.0610469e-05 2.1156562e-05 + 8000 800 9.5573298e-06 2.0898126e-05 + 8200 820 8.6085799e-06 2.0517958e-05 + 8400 840 7.7539888e-06 1.9841551e-05 + 8600 860 6.9843033e-06 1.9114769e-05 + 8800 880 6.2911575e-06 1.8362959e-05 + 9000 900 5.6669785e-06 1.7473404e-05 + 9200 920 5.1049208e-06 1.6452745e-05 + 9400 940 4.5987908e-06 1.5578629e-05 + 9600 960 4.1429972e-06 1.4427274e-05 + 9800 980 3.7324962e-06 1.3169649e-05 + 10000 1000 3.3627455e-06 1.1938723e-05 +Loop time of 38.2006 on 4 procs for 10000 steps with 1600 atoms + +Performance: 2261743.875 tau/day, 261.776 timesteps/s, 418.841 katom-step/s +99.7% CPU use with 4 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 8.2958 | 8.7273 | 9.3582 | 15.2 | 22.85 +Neigh | 0.034282 | 0.035689 | 0.037115 | 0.7 | 0.09 +Comm | 0.16788 | 0.17018 | 0.17278 | 0.4 | 0.45 +Output | 0.066977 | 0.06882 | 0.071704 | 0.7 | 0.18 +Modify | 28.483 | 28.793 | 28.962 | 3.6 | 75.37 +Other | | 0.4053 | | | 1.06 + +Nlocal: 400 ave 402 max 399 min +Histogram: 2 0 0 1 0 0 0 0 0 1 +Nghost: 307.25 ave 308 max 305 min +Histogram: 1 0 0 0 0 0 0 0 0 3 +Neighs: 7618.25 ave 7697 max 7564 min +Histogram: 1 0 1 1 0 0 0 0 0 1 +FullNghs: 13343 ave 13497 max 13258 min +Histogram: 1 1 1 0 0 0 0 0 0 1 + +Total # of neighbors = 53372 +Ave neighs/atom = 33.3575 +Neighbor list builds = 123 +Dangerous builds = 0 +Total wall time: 0:00:38 diff --git a/lib/rheo/Makefile.lammps b/lib/rheo/Makefile.lammps new file mode 100644 index 0000000000..ec58740370 --- /dev/null +++ b/lib/rheo/Makefile.lammps @@ -0,0 +1,14 @@ +# Settings that the LAMMPS build will import when this package is installed + +ifeq ($(strip $(shell pkg-config --version)),) + # manual configuration w/o pkg-config/pkgconf + # change this to -I/path/to/your/lib/gsl/include/ + rheo_SYSINC = -I../../lib/rheo/gsl/include/ + + # change this to -L/path/to/your/lib/gsl/lib/ + rheo_SYSLIB = -L../../lib/rheo/gsl/lib/ -lgsl -lgslcblas +else + # autodetect GSL settings from pkg-config/pkgconf + rheo_SYSINC = $(shell pkg-config --cflags gsl) + rheo_SYSLIB = $(shell pkg-config --libs gsl) +endif diff --git a/lib/rheo/README b/lib/rheo/README new file mode 100644 index 0000000000..ae421b6e80 --- /dev/null +++ b/lib/rheo/README @@ -0,0 +1,7 @@ +This directory has a Makefile.lammps file with settings that allows LAMMPS to +dynamically link to the GSL library. This is required to use the RHEO package +in a LAMMPS input script. If you have the pkg-config command available, it +will automatically import the GSL settings. Otherwise they will have to be +added manually. + +See the header of Makefile.lammps for more info. diff --git a/src/.gitignore b/src/.gitignore index e5923d0149..5b13a7d55a 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -245,6 +245,9 @@ /pair_tdpd.cpp /pair_tdpd.h +/*rheo*.cpp +/*rheo*.h + /compute_grid.cpp /compute_grid.h /compute_grid_local.cpp @@ -790,6 +793,8 @@ /fix_acks2_reaxff.h /fix_adapt_fep.cpp /fix_adapt_fep.h +/fix_add_heat.cpp +/fix_add_heat.h /fix_addtorque.cpp /fix_addtorque.h /fix_append_atoms.cpp diff --git a/src/BPM/bond_bpm.cpp b/src/BPM/bond_bpm.cpp index e8521df32a..130080b349 100644 --- a/src/BPM/bond_bpm.cpp +++ b/src/BPM/bond_bpm.cpp @@ -18,6 +18,7 @@ #include "comm.h" #include "domain.h" #include "error.h" +#include "fix.h" #include "fix_bond_history.h" #include "fix_store_local.h" #include "fix_update_special_bonds.h" @@ -53,10 +54,14 @@ BondBPM::BondBPM(LAMMPS *_lmp) : pack_choice(nullptr), output_data(nullptr) { overlay_flag = 0; + ignore_special_flag = 0; prop_atom_flag = 0; break_flag = 1; nvalues = 0; + nhistory = 0; + update_flag = 0; + r0_max_estimate = 0.0; max_stretch = 1.0; @@ -64,10 +69,10 @@ BondBPM::BondBPM(LAMMPS *_lmp) : // this is so final order of Modify:fix will conform to input script // BondHistory technically only needs this if updateflag = 1 - id_fix_dummy = utils::strdup("BPM_DUMMY"); + id_fix_dummy = utils::strdup(fmt::format("BPM_DUMMY_{}", instance_total)); modify->add_fix(fmt::format("{} all DUMMY ", id_fix_dummy)); - id_fix_dummy2 = utils::strdup("BPM_DUMMY2"); + id_fix_dummy2 = utils::strdup(fmt::format("BPM_DUMMY2_{}", instance_total)); modify->add_fix(fmt::format("{} all DUMMY ", id_fix_dummy2)); if (lmp->citeme) lmp->citeme->add(cite_bpm); @@ -82,7 +87,7 @@ BondBPM::~BondBPM() if (id_fix_dummy) modify->delete_fix(id_fix_dummy); if (id_fix_dummy2) modify->delete_fix(id_fix_dummy2); if (id_fix_update) modify->delete_fix(id_fix_update); - if (id_fix_bond_history) modify->delete_fix(id_fix_bond_history); + if (fix_bond_history) modify->delete_fix(id_fix_bond_history); if (id_fix_store_local) modify->delete_fix(id_fix_store_local); if (id_fix_prop_atom) modify->delete_fix(id_fix_prop_atom); @@ -109,39 +114,46 @@ void BondBPM::init_style() fix_store_local->nvalues = nvalues; } - if (overlay_flag) { - if (force->special_lj[1] != 1.0 || force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0 || - force->special_coul[1] != 1.0 || force->special_coul[2] != 1.0 || force->special_coul[3] != 1.0) - error->all(FLERR, - "With overlay/pair yes, BPM bond styles require a value of 1.0 for all special_bonds weights"); - if (id_fix_update) { - modify->delete_fix(id_fix_update); - delete[] id_fix_update; - id_fix_update = nullptr; - } - } else { - // Require atoms know about all of their bonds and if they break - if (force->newton_bond && break_flag) - error->all(FLERR, "With overlay/pair no, or break yes, BPM bond styles require Newton bond off"); + if (!ignore_special_flag) { + if (overlay_flag) { + if (force->special_lj[1] != 1.0 || force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0 || + force->special_coul[1] != 1.0 || force->special_coul[2] != 1.0 || force->special_coul[3] != 1.0) + error->all(FLERR, + "With overlay/pair yes, BPM bond styles require a value of 1.0 for all special_bonds weights"); + if (id_fix_update) { + modify->delete_fix(id_fix_update); + delete[] id_fix_update; + id_fix_update = nullptr; + } + } else { + // Require atoms know about all of their bonds and if they break + if (force->newton_bond && break_flag) + error->all(FLERR, "With overlay/pair no, or break yes, BPM bond styles require Newton bond off"); - // special lj must be 0 1 1 to censor pair forces between bonded particles - if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0) - error->all(FLERR, - "With overlay/pair no, BPM bond styles require special LJ weights = 0,1,1"); - // if bonds can break, special coulomb must be 1 1 1 to ensure all pairs are included in the - // neighbor list and 1-3 and 1-4 special bond lists are skipped - if (break_flag && (force->special_coul[1] != 1.0 || force->special_coul[2] != 1.0 || - force->special_coul[3] != 1.0)) - error->all(FLERR, - "With overlay/pair no, and break yes, BPM bond styles requires special Coulomb weights = 1,1,1"); + // special lj must be 0 1 1 to censor pair forces between bonded particles + if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0) + error->all(FLERR, + "With overlay/pair no, BPM bond styles require special LJ weights = 0,1,1"); + // if bonds can break, special coulomb must be 1 1 1 to ensure all pairs are included in the + // neighbor list and 1-3 and 1-4 special bond lists are skipped + if (break_flag && (force->special_coul[1] != 1.0 || force->special_coul[2] != 1.0 || + force->special_coul[3] != 1.0)) + error->all(FLERR, + "With overlay/pair no, and break yes, BPM bond styles requires special Coulomb weights = 1,1,1"); - if (id_fix_dummy && break_flag) { - id_fix_update = utils::strdup("BPM_UPDATE_SPECIAL_BONDS"); - fix_update_special_bonds = dynamic_cast(modify->replace_fix( - id_fix_dummy, fmt::format("{} all UPDATE_SPECIAL_BONDS", id_fix_update), 1)); - delete[] id_fix_dummy; - id_fix_dummy = nullptr; + if (id_fix_dummy && break_flag) { + id_fix_update = utils::strdup("BPM_UPDATE_SPECIAL_BONDS"); + fix_update_special_bonds = dynamic_cast(modify->replace_fix( + id_fix_dummy, fmt::format("{} all UPDATE_SPECIAL_BONDS", id_fix_update), 1)); + delete[] id_fix_dummy; + id_fix_dummy = nullptr; + } } + + // special 1-3 and 1-4 weights must be 1 to prevent building 1-3 and 1-4 special bond lists + if (force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0 || force->special_coul[2] != 1.0 || + force->special_coul[3] != 1.0) + error->all(FLERR, "Bond style bpm requires 1-3 and 1-4 special weights of 1.0"); } if (force->angle || force->dihedral || force->improper) @@ -149,10 +161,16 @@ void BondBPM::init_style() if (atom->molecular == 2) error->all(FLERR, "Bond style bpm cannot be used with atom style template"); - // special 1-3 and 1-4 weights must be 1 to prevent building 1-3 and 1-4 special bond lists - if (force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0 || force->special_coul[2] != 1.0 || - force->special_coul[3] != 1.0) - error->all(FLERR, "Bond style bpm requires 1-3 and 1-4 special weights of 1.0"); + // find all instances of bond history to delete/shift data + // (bond hybrid may create multiple) + histories = modify->get_fix_by_style("BOND_HISTORY"); + n_histories = histories.size(); + + // If a bond type isn't set, must be using bond style hybrid + hybrid_flag = 0; + for (int i = 1; i <= atom->nbondtypes; i++) + if (!setflag[i]) hybrid_flag = 1; + fix_bond_history->setflag = setflag; } /* ---------------------------------------------------------------------- @@ -269,6 +287,14 @@ void BondBPM::settings(int narg, char **arg) } } } + + // Set up necessary history fix + if (!fix_bond_history) { + fix_bond_history = dynamic_cast(modify->replace_fix( + id_fix_dummy2, fmt::format("{} all BOND_HISTORY {} {}", id_fix_bond_history, update_flag, nhistory), 1)); + delete[] id_fix_dummy2; + id_fix_dummy2 = nullptr; + } } /* ---------------------------------------------------------------------- @@ -385,12 +411,15 @@ void BondBPM::process_broken(int i, int j) if (i < nlocal) { for (m = 0; m < num_bond[i]; m++) { - if (bond_atom[i][m] == tag[j]) { + if (bond_atom[i][m] == tag[j] && setflag[bond_type[i][m]]) { n = num_bond[i]; bond_type[i][m] = bond_type[i][n - 1]; bond_atom[i][m] = bond_atom[i][n - 1]; - fix_bond_history->shift_history(i, m, n - 1); - fix_bond_history->delete_history(i, n - 1); + for (auto &ihistory: histories) { + auto fix_bond_history2 = dynamic_cast (ihistory); + fix_bond_history2->shift_history(i, m, n - 1); + fix_bond_history2->delete_history(i, n - 1); + } num_bond[i]--; break; } @@ -399,12 +428,15 @@ void BondBPM::process_broken(int i, int j) if (j < nlocal) { for (m = 0; m < num_bond[j]; m++) { - if (bond_atom[j][m] == tag[i]) { + if (bond_atom[j][m] == tag[i] && setflag[bond_type[j][m]]) { n = num_bond[j]; bond_type[j][m] = bond_type[j][n - 1]; bond_atom[j][m] = bond_atom[j][n - 1]; - fix_bond_history->shift_history(j, m, n - 1); - fix_bond_history->delete_history(j, n - 1); + for (auto &ihistory: histories) { + auto fix_bond_history2 = dynamic_cast (ihistory); + fix_bond_history2->shift_history(j, m, n - 1); + fix_bond_history2->delete_history(j, n - 1); + } num_bond[j]--; break; } diff --git a/src/BPM/bond_bpm.h b/src/BPM/bond_bpm.h index 815b3b751f..28e4e7187e 100644 --- a/src/BPM/bond_bpm.h +++ b/src/BPM/bond_bpm.h @@ -16,8 +16,12 @@ #include "bond.h" +#include + namespace LAMMPS_NS { +class Fix; + class BondBPM : public Bond { public: BondBPM(class LAMMPS *); @@ -34,7 +38,7 @@ class BondBPM : public Bond { protected: double r0_max_estimate; double max_stretch; - int store_local_freq; + int store_local_freq, nhistory, update_flag, hybrid_flag; std::vector leftover_iarg; @@ -50,9 +54,12 @@ class BondBPM : public Bond { FnPtrPack *pack_choice; // ptrs to pack functions double *output_data; - int prop_atom_flag, nvalues, overlay_flag, break_flag; + int prop_atom_flag, nvalues, overlay_flag, break_flag, ignore_special_flag; int index_x_ref, index_y_ref, index_z_ref; + int n_histories; + std::vector histories; + void pack_id1(int, int, int); void pack_id2(int, int, int); void pack_time(int, int, int); diff --git a/src/BPM/bond_bpm_rotational.cpp b/src/BPM/bond_bpm_rotational.cpp index f2bfa3d770..aba3709dc9 100644 --- a/src/BPM/bond_bpm_rotational.cpp +++ b/src/BPM/bond_bpm_rotational.cpp @@ -52,6 +52,9 @@ BondBPMRotational::BondBPMRotational(LAMMPS *_lmp) : smooth_flag = 1; normalize_flag = 0; + nhistory = 4; + id_fix_bond_history = utils::strdup("HISTORY_BPM_ROTATIONAL"); + single_extra = 7; svector = new double[7]; } @@ -458,6 +461,9 @@ void BondBPMRotational::compute(int eflag, int vflag) store_data(); } + if (hybrid_flag) + fix_bond_history->compress_history(); + int i1, i2, itmp, n, type; double r[3], r0[3], rhat[3]; double rsq, r0_mag, r_mag, r_mag_inv; @@ -563,6 +569,9 @@ void BondBPMRotational::compute(int eflag, int vflag) ev_tally_xyz(i1, i2, nlocal, newton_bond, 0.0, -force1on2[0] * smooth, -force1on2[1] * smooth, -force1on2[2] * smooth, r[0], r[1], r[2]); } + + if (hybrid_flag) + fix_bond_history->uncompress_history(); } /* ---------------------------------------------------------------------- */ @@ -652,14 +661,6 @@ void BondBPMRotational::init_style() if (domain->dimension == 2) error->warning(FLERR, "Bond style bpm/rotational not intended for 2d use"); - - if (!id_fix_bond_history) { - id_fix_bond_history = utils::strdup("HISTORY_BPM_ROTATIONAL"); - fix_bond_history = dynamic_cast(modify->replace_fix( - id_fix_dummy2, fmt::format("{} all BOND_HISTORY 0 4", id_fix_bond_history), 1)); - delete[] id_fix_dummy2; - id_fix_dummy2 = nullptr; - } } /* ---------------------------------------------------------------------- */ diff --git a/src/BPM/bond_bpm_spring.cpp b/src/BPM/bond_bpm_spring.cpp index 28d17b408a..2863bbf317 100644 --- a/src/BPM/bond_bpm_spring.cpp +++ b/src/BPM/bond_bpm_spring.cpp @@ -39,6 +39,9 @@ BondBPMSpring::BondBPMSpring(LAMMPS *_lmp) : smooth_flag = 1; normalize_flag = 0; + nhistory = 1; + id_fix_bond_history = utils::strdup("HISTORY_BPM_SPRING"); + single_extra = 1; svector = new double[1]; } @@ -137,6 +140,9 @@ void BondBPMSpring::compute(int eflag, int vflag) store_data(); } + if (hybrid_flag) + fix_bond_history->compress_history(); + int i1, i2, itmp, n, type; double delx, dely, delz, delvx, delvy, delvz; double e, rsq, r, r0, rinv, smooth, fbond, dot; @@ -226,6 +232,9 @@ void BondBPMSpring::compute(int eflag, int vflag) if (evflag) ev_tally(i1, i2, nlocal, newton_bond, 0.0, fbond, delx, dely, delz); } + + if (hybrid_flag) + fix_bond_history->uncompress_history(); } /* ---------------------------------------------------------------------- */ @@ -283,14 +292,6 @@ void BondBPMSpring::init_style() if (comm->ghost_velocity == 0) error->all(FLERR, "Bond bpm/spring requires ghost atoms store velocity"); - - if (!id_fix_bond_history) { - id_fix_bond_history = utils::strdup("HISTORY_BPM_SPRING"); - fix_bond_history = dynamic_cast(modify->replace_fix( - id_fix_dummy2, fmt::format("{} all BOND_HISTORY 0 1", id_fix_bond_history), 1)); - delete[] id_fix_dummy2; - id_fix_dummy2 = nullptr; - } } /* ---------------------------------------------------------------------- */ diff --git a/src/BPM/compute_nbond_atom.cpp b/src/BPM/compute_nbond_atom.cpp index 85ef6f3fce..31428b1912 100644 --- a/src/BPM/compute_nbond_atom.cpp +++ b/src/BPM/compute_nbond_atom.cpp @@ -14,7 +14,9 @@ #include "compute_nbond_atom.h" #include "atom.h" +#include "atom_vec.h" #include "comm.h" +#include "error.h" #include "force.h" #include "memory.h" @@ -27,6 +29,21 @@ ComputeNBondAtom::ComputeNBondAtom(LAMMPS *_lmp, int narg, char **arg) : { if (narg < 3) utils::missing_cmd_args(FLERR, "compute nbond/atom", error); + if (atom->avec->bonds_allow == 0) + error->all(FLERR,"Compute nbond/atom used in system without bonds"); + + btype = -1; + int iarg = 3; + while (iarg < narg) { + if (strcmp(arg[iarg], "bond/type") == 0) { + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "compute nbond/atom bond/type", error); + btype = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); + iarg += 2; + } else { + error->all(FLERR, "Unknown compute nbond/atom command {}", arg[iarg]); + } + } + peratom_flag = 1; size_peratom_cols = 0; comm_reverse = 1; @@ -77,6 +94,7 @@ void ComputeNBondAtom::compute_peratom() for (i = 0; i < nlocal; i++) { for (j = 0; j < num_bond[i]; j++) { if (bond_type[i][j] <= 0) continue; + if (btype != -1 && bond_type[i][j] != btype) continue; k = atom->map(bond_atom[i][j]); if (k < 0) continue; diff --git a/src/BPM/compute_nbond_atom.h b/src/BPM/compute_nbond_atom.h index e0c2d7ce01..b55ef91e5d 100644 --- a/src/BPM/compute_nbond_atom.h +++ b/src/BPM/compute_nbond_atom.h @@ -35,7 +35,7 @@ class ComputeNBondAtom : public Compute { double memory_usage() override; private: - int nmax; + int nmax, btype; double *nbond; }; diff --git a/src/BPM/fix_update_special_bonds.cpp b/src/BPM/fix_update_special_bonds.cpp index 1b408d6d4b..c71f6973d0 100644 --- a/src/BPM/fix_update_special_bonds.cpp +++ b/src/BPM/fix_update_special_bonds.cpp @@ -90,11 +90,13 @@ void FixUpdateSpecialBonds::pre_exchange() for (auto const &it : broken_pairs) { tagi = it.first; tagj = it.second; + i = atom->map(tagi); j = atom->map(tagj); // remove i from special bond list for atom j and vice versa // ignore n2, n3 since 1-3, 1-4 special factors required to be 1.0 + // assume ghosts don't need special information if (i < nlocal) { slist = special[i]; n1 = nspecial[i][0]; @@ -126,19 +128,24 @@ void FixUpdateSpecialBonds::pre_exchange() // add i to special bond list for atom j and vice versa // ignore n2, n3 since 1-3, 1-4 special factors required to be 1.0 - n1 = nspecial[i][0]; - if (n1 >= atom->maxspecial) - error->one(FLERR, "Special list size exceeded in fix update/special/bond"); - special[i][n1] = tagj; - nspecial[i][0] += 1; - nspecial[i][1] = nspecial[i][2] = nspecial[i][0]; + // assume ghosts don't need special information + if (i < nlocal) { + n1 = nspecial[i][0]; + if (n1 >= atom->maxspecial) + error->one(FLERR, "Special list size exceeded for atom {}", tagi); + special[i][n1] = tagj; + nspecial[i][0] += 1; + nspecial[i][1] = nspecial[i][2] = nspecial[i][0]; + } - n1 = nspecial[j][0]; - if (n1 >= atom->maxspecial) - error->one(FLERR, "Special list size exceeded in fix update/special/bond"); - special[j][n1] = tagi; - nspecial[j][0] += 1; - nspecial[j][1] = nspecial[j][2] = nspecial[j][0]; + if (j < nlocal) { + n1 = nspecial[j][0]; + if (n1 >= atom->maxspecial) + error->one(FLERR, "Special list size exceeded for atom {}", tagj); + special[j][n1] = tagi; + nspecial[j][0] += 1; + nspecial[j][1] = nspecial[j][2] = nspecial[j][0]; + } } broken_pairs.clear(); @@ -162,7 +169,7 @@ void FixUpdateSpecialBonds::pre_force(int /*vflag*/) tagint *tag = atom->tag; // In theory could communicate a list of broken bonds to neighboring processors here - // to remove restriction that users use Newton bond off + // to remove restriction on Newton bond off for (int ilist = 0; ilist < neighbor->nlist; ilist++) { list = neighbor->lists[ilist]; diff --git a/src/GRANULAR/fix_add_heat.cpp b/src/GRANULAR/fix_add_heat.cpp new file mode 100644 index 0000000000..01bc22cdf4 --- /dev/null +++ b/src/GRANULAR/fix_add_heat.cpp @@ -0,0 +1,161 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Joel Clemmer (SNL) +------------------------------------------------------------------------- */ + +#include "fix_add_heat.h" + +#include "atom.h" +#include "error.h" +#include "input.h" +#include "memory.h" +#include "update.h" +#include "variable.h" + +using namespace LAMMPS_NS; +using namespace FixConst; + +enum { CONSTANT, EQUAL, ATOM }; +enum { ADD, LINEAR, QUARTIC }; + +/* ---------------------------------------------------------------------- */ + +FixAddHeat::FixAddHeat(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), varstr(nullptr), vatom(nullptr) +{ + if (narg < 5) utils::missing_cmd_args(FLERR, "fix add/heat", error); + dynamic_group_allow = 1; + overwrite_flag = 0; + + if (strcmp(arg[3], "constant") == 0) { + style = ADD; + } else if (strcmp(arg[3], "linear") == 0) { + style = LINEAR; + } else if (strcmp(arg[3], "quartic") == 0) { + style = QUARTIC; + } else { + error->all(FLERR, "Invalid option {}", arg[3]); + } + + if (utils::strmatch(arg[4], "^v_")) { + varstr = utils::strdup(arg[4] + 2); + } else { + value = utils::numeric(FLERR, arg[4], false, lmp); + vstyle = CONSTANT; + } + + int iarg = 5; + if (style != ADD) { + if (narg != 6) utils::missing_cmd_args(FLERR, "fix add/heat", error); + prefactor = utils::numeric(FLERR, arg[5], false, lmp); + iarg = 6; + } + + // optional args + + while (iarg < narg) { + if (strcmp(arg[iarg], "overwrite") == 0) { + if (iarg + 1 >= narg) utils::missing_cmd_args(FLERR, "fix add/heat", error); + overwrite_flag = utils::logical(FLERR, arg[iarg + 1], false, lmp); + iarg += 2; + } else { + error->all(FLERR, "Illegal fix add/heat command, invalid argument {}", arg[iarg]); + } + } + + maxatom = -1; +} + +/* ---------------------------------------------------------------------- */ + +FixAddHeat::~FixAddHeat() +{ + delete[] varstr; + memory->destroy(vatom); +} + +/* ---------------------------------------------------------------------- */ + +int FixAddHeat::setmask() +{ + int mask = 0; + mask |= POST_FORCE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixAddHeat::init() +{ + if (!atom->temperature_flag) + error->all(FLERR, "Fix add/heat requires atom style with temperature property"); + if (!atom->heatflow_flag) + error->all(FLERR, "Fix add/heat requires atom style with heatflow property"); + + // check variable + + if (varstr) { + var = input->variable->find(varstr); + if (var < 0) error->all(FLERR, "Variable {} for fix addforce does not exist", varstr); + if (input->variable->equalstyle(var)) + vstyle = EQUAL; + else if (input->variable->atomstyle(var)) + vstyle = ATOM; + else + error->all(FLERR, "Variable {} for fix addforce is invalid style", varstr); + } +} + +/* ---------------------------------------------------------------------- */ + +void FixAddHeat::post_force(int /*vflag*/) +{ + int *mask = atom->mask; + double *heatflow = atom->heatflow; + double *temperature = atom->temperature; + double dtinv = 1.0 / update->dt; + + if (vstyle == ATOM) { + if (atom->nmax > maxatom) { + maxatom = atom->nmax; + memory->destroy(vatom); + memory->create(vatom, maxatom, "addheat:vatom"); + } + + input->variable->compute_atom(var, igroup, &vatom[0], 1, 0); + } + + if (overwrite_flag) + for (int i = 0; i < atom->nlocal; i++) + if (mask[i] & groupbit) + heatflow[i] = 0.0; + + double vtmp, dt; + if (vstyle == CONSTANT) vtmp = value; + if (vstyle == EQUAL) vtmp = input->variable->compute_equal(var); + for (int i = 0; i < atom->nlocal; i++) { + if (mask[i] & groupbit) { + if (vstyle == ATOM) vtmp = vatom[i]; + + if (style == ADD) { + heatflow[i] += dtinv * vtmp; + } else if (style == LINEAR) { + heatflow[i] += dtinv * prefactor * (vtmp - temperature[i]); + } else if (style == QUARTIC) { + heatflow[i] += dtinv * prefactor * (pow(vtmp, 4.0) - pow(temperature[i], 4.0)); + } + } + } +} diff --git a/src/GRANULAR/fix_add_heat.h b/src/GRANULAR/fix_add_heat.h new file mode 100644 index 0000000000..4fa8adf42e --- /dev/null +++ b/src/GRANULAR/fix_add_heat.h @@ -0,0 +1,45 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(add/heat,FixAddHeat); +// clang-format on +#else + +#ifndef LMP_FIX_ADD_HEAT_H +#define LMP_FIX_ADD_HEAT_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixAddHeat : public Fix { + public: + FixAddHeat(class LAMMPS *, int, char **); + ~FixAddHeat() override; + int setmask() override; + void init() override; + void post_force(int) override; + + protected: + double value, prefactor; + int var, vstyle, maxatom, style, overwrite_flag; + char *varstr; + double *vatom; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/Makefile b/src/Makefile index 805b950112..4d8b02458a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -124,6 +124,7 @@ PACKAGE = \ reaction \ reaxff \ replica \ + rheo \ rigid \ scafacos \ shock \ @@ -233,6 +234,7 @@ PACKLIB = \ plumed \ qmmm \ ml-quip \ + rheo \ scafacos \ machdyn \ vtk \ @@ -254,6 +256,7 @@ PACKEXT = \ netcdf \ plumed \ qmmm \ + rheo \ scafacos \ voronoi \ vtk \ diff --git a/src/RHEO/Install.sh b/src/RHEO/Install.sh new file mode 100644 index 0000000000..e34ca3a555 --- /dev/null +++ b/src/RHEO/Install.sh @@ -0,0 +1,70 @@ +# Install/unInstall package files in LAMMPS +# mode = 0/1/2 for uninstall/install/update + +mode=$1 + +# enforce using portable C locale +LC_ALL=C +export LC_ALL + +# arg1 = file, arg2 = file it depends on + +action () { + if (test $mode = 0) then + rm -f ../$1 + elif (! cmp -s $1 ../$1) then + if (test -z "$2" || test -e ../$2) then + cp $1 .. + if (test $mode = 2) then + echo " updating src/$1" + fi + fi + elif (test -n "$2") then + if (test ! -e ../$2) then + rm -f ../$1 + fi + fi +} + +# some styles in RHEO have base classes in BPM + +if (test $1 = 1) then + if (test ! -e ../bond_bpm.cpp) then + echo "Must install BPM package with RHEO" + exit 1 + fi +fi + +for file in *.cpp *.h; do + action ${file} +done + +# edit 2 Makefile.package files to include/exclude package info + +if (test $1 = 1) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*rheo[^ \t]* //' ../Makefile.package + sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(rheo_SYSINC) |' ../Makefile.package + sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(rheo_SYSLIB) |' ../Makefile.package + fi + + if (test -e ../Makefile.package.settings) then + sed -i -e '/^[ \t]*include.*rheo.*$/d' ../Makefile.package.settings + # multiline form needed for BSD sed on Macs + sed -i -e '4 i \ +include ..\/..\/lib\/rheo\/Makefile.lammps +' ../Makefile.package.settings + fi + +elif (test $1 = 0) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*rheo[^ \t]* //' ../Makefile.package + fi + + if (test -e ../Makefile.package.settings) then + sed -i -e '/^[ \t]*include.*rheo.*$/d' ../Makefile.package.settings + fi + +fi diff --git a/src/RHEO/README b/src/RHEO/README new file mode 100644 index 0000000000..4b6f2a162a --- /dev/null +++ b/src/RHEO/README @@ -0,0 +1,10 @@ +RHEO or Reproducing Hydrodynamics and Elastic Objects is a package to model +multiphase fluid systems. The authors include Joel Clemmer (Sandia), Thomas +O'Connor (Carnegie Mellon), and Eric Palermo (Carnegie Mellon). + +Bond style rheo/shell, compute style rheo/property/atom, and fix style +rheo/temperature all depend on the BPM package. + +This package requires the GNU scientific library (GSL). We recommend version +2.7 or later. To build this package, one must first separately install GSL in +a location that can be found by your environment. diff --git a/src/RHEO/atom_vec_rheo.cpp b/src/RHEO/atom_vec_rheo.cpp new file mode 100644 index 0000000000..0cbebff008 --- /dev/null +++ b/src/RHEO/atom_vec_rheo.cpp @@ -0,0 +1,174 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "atom_vec_rheo.h" + +#include "atom.h" + +#include + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +AtomVecRHEO::AtomVecRHEO(LAMMPS *lmp) : AtomVec(lmp) +{ + molecular = Atom::ATOMIC; + mass_type = PER_TYPE; + forceclearflag = 1; + + atom->rheo_status_flag = 1; + atom->pressure_flag = 1; + atom->rho_flag = 1; + atom->viscosity_flag = 1; + + // strings with peratom variables to include in each AtomVec method + // strings cannot contain fields in corresponding AtomVec default strings + // order of fields in a string does not matter + // except: fields_data_atom & fields_data_vel must match data file + + fields_grow = {"rheo_status", "rho", "drho", "pressure", "viscosity"}; + fields_copy = {"rheo_status", "rho", "drho", "pressure", "viscosity"}; + fields_comm = {"rheo_status", "rho"}; + fields_comm_vel = {"rheo_status", "rho"}; + fields_reverse = {"drho"}; + fields_border = {"rheo_status", "rho"}; + fields_border_vel = {"rheo_status", "rho"}; + fields_exchange = {"rheo_status", "rho"}; + fields_restart = {"rheo_status", "rho"}; + fields_create = {"rheo_status", "rho", "drho", "pressure", "viscosity"}; + fields_data_atom = {"id", "type", "rheo_status", "rho", "x"}; + fields_data_vel = {"id", "v"}; + + setup_fields(); +} + +/* ---------------------------------------------------------------------- + set local copies of all grow ptrs used by this class, except defaults + needed in replicate when 2 atom classes exist and it calls pack_restart() +------------------------------------------------------------------------- */ + +void AtomVecRHEO::grow_pointers() +{ + rheo_status = atom->rheo_status; + pressure = atom->pressure; + rho = atom->rho; + drho = atom->drho; + viscosity = atom->viscosity; +} + +/* ---------------------------------------------------------------------- + clear extra forces starting at atom N + nbytes = # of bytes to clear for a per-atom vector +------------------------------------------------------------------------- */ + +void AtomVecRHEO::force_clear(int n, size_t nbytes) +{ + memset(&drho[n], 0, nbytes); +} + +/* ---------------------------------------------------------------------- + initialize non-zero atom quantities +------------------------------------------------------------------------- */ + +void AtomVecRHEO::create_atom_post(int ilocal) +{ + rho[ilocal] = 1.0; +} + +/* ---------------------------------------------------------------------- + modify what AtomVec::data_atom() just unpacked + or initialize other atom quantities +------------------------------------------------------------------------- */ + +void AtomVecRHEO::data_atom_post(int ilocal) +{ + drho[ilocal] = 0.0; + pressure[ilocal] = 0.0; + viscosity[ilocal] = 0.0; +} + +/* ---------------------------------------------------------------------- + assign an index to named atom property and return index + return -1 if name is unknown to this atom style +------------------------------------------------------------------------- */ + +int AtomVecRHEO::property_atom(const std::string &name) +{ + if (name == "rheo_status") return 0; + if (name == "pressure") return 1; + if (name == "rho") return 2; + if (name == "drho") return 3; + if (name == "viscosity") return 4; + return -1; +} + +/* ---------------------------------------------------------------------- + pack per-atom data into buf for ComputePropertyAtom + index maps to data specific to this atom style +------------------------------------------------------------------------- */ + +void AtomVecRHEO::pack_property_atom(int index, double *buf, int nvalues, int groupbit) +{ + int *mask = atom->mask; + int nlocal = atom->nlocal; + int n = 0; + + if (index == 0) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = rheo_status[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 1) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = pressure[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 2) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = rho[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 3) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = drho[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 4) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = viscosity[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } +} diff --git a/src/RHEO/atom_vec_rheo.h b/src/RHEO/atom_vec_rheo.h new file mode 100644 index 0000000000..8eaa01f7be --- /dev/null +++ b/src/RHEO/atom_vec_rheo.h @@ -0,0 +1,46 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef ATOM_CLASS +// clang-format off +AtomStyle(rheo,AtomVecRHEO); +// clang-format on +#else + +#ifndef LMP_ATOM_VEC_RHEO_H +#define LMP_ATOM_VEC_RHEO_H + +#include "atom_vec.h" + +namespace LAMMPS_NS { + +class AtomVecRHEO : virtual public AtomVec { + public: + AtomVecRHEO(class LAMMPS *); + + void grow_pointers() override; + void force_clear(int, size_t) override; + void create_atom_post(int) override; + void data_atom_post(int) override; + int property_atom(const std::string &) override; + void pack_property_atom(int, double *, int, int) override; + + private: + int *rheo_status; + double *pressure, *rho, *drho, *viscosity; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/atom_vec_rheo_thermal.cpp b/src/RHEO/atom_vec_rheo_thermal.cpp new file mode 100644 index 0000000000..426c059570 --- /dev/null +++ b/src/RHEO/atom_vec_rheo_thermal.cpp @@ -0,0 +1,222 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "atom_vec_rheo_thermal.h" + +#include "atom.h" + +#include + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +AtomVecRHEOThermal::AtomVecRHEOThermal(LAMMPS *lmp) : AtomVec(lmp) +{ + molecular = Atom::ATOMIC; + mass_type = PER_TYPE; + forceclearflag = 1; + + atom->rheo_status_flag = 1; + atom->conductivity_flag = 1; + atom->temperature_flag = 1; + atom->esph_flag = 1; + atom->heatflow_flag = 1; + atom->pressure_flag = 1; + atom->rho_flag = 1; + atom->viscosity_flag = 1; + + // strings with peratom variables to include in each AtomVec method + // strings cannot contain fields in corresponding AtomVec default strings + // order of fields in a string does not matter + // except: fields_data_atom & fields_data_vel must match data file + + fields_grow = {"rheo_status", "rho", "drho", "temperature", "esph", "heatflow", "conductivity", "pressure", "viscosity"}; + fields_copy = {"rheo_status", "rho", "drho", "temperature", "esph", "heatflow", "conductivity", "pressure", "viscosity"}; + fields_comm = {"rheo_status", "rho", "esph"}; + fields_comm_vel = {"rheo_status", "rho", "esph"}; + fields_reverse = {"drho", "heatflow"}; + fields_border = {"rheo_status", "rho", "esph"}; + fields_border_vel = {"rheo_status", "rho", "esph"}; + fields_exchange = {"rheo_status", "rho", "esph"}; + fields_restart = {"rheo_status", "rho", "esph"}; + fields_create = {"rheo_status", "rho", "drho", "temperature", "esph", "heatflow", "conductivity", "pressure", "viscosity"}; + fields_data_atom = {"id", "type", "rheo_status", "rho", "esph", "x"}; + fields_data_vel = {"id", "v"}; + + setup_fields(); +} + +/* ---------------------------------------------------------------------- + set local copies of all grow ptrs used by this class, except defaults + needed in replicate when 2 atom classes exist and it calls pack_restart() +------------------------------------------------------------------------- */ + +void AtomVecRHEOThermal::grow_pointers() +{ + rheo_status = atom->rheo_status; + conductivity = atom->conductivity; + temperature = atom->temperature; + esph = atom->esph; + heatflow = atom->heatflow; + pressure = atom->pressure; + rho = atom->rho; + drho = atom->drho; + viscosity = atom->viscosity; +} + +/* ---------------------------------------------------------------------- + clear extra forces starting at atom N + nbytes = # of bytes to clear for a per-atom vector +------------------------------------------------------------------------- */ + +void AtomVecRHEOThermal::force_clear(int n, size_t nbytes) +{ + memset(&drho[n], 0, nbytes); + memset(&heatflow[n], 0, nbytes); +} + +/* ---------------------------------------------------------------------- + initialize non-zero atom quantities +------------------------------------------------------------------------- */ + +void AtomVecRHEOThermal::create_atom_post(int ilocal) +{ + rho[ilocal] = 1.0; +} + +/* ---------------------------------------------------------------------- + modify what AtomVec::data_atom() just unpacked + or initialize other atom quantities +------------------------------------------------------------------------- */ + +void AtomVecRHEOThermal::data_atom_post(int ilocal) +{ + drho[ilocal] = 0.0; + heatflow[ilocal] = 0.0; + temperature[ilocal] = 0.0; + pressure[ilocal] = 0.0; + viscosity[ilocal] = 0.0; + conductivity[ilocal] = 0.0; +} + +/* ---------------------------------------------------------------------- + assign an index to named atom property and return index + return -1 if name is unknown to this atom style +------------------------------------------------------------------------- */ + +int AtomVecRHEOThermal::property_atom(const std::string &name) +{ + if (name == "rheo_status") return 0; + if (name == "rho") return 1; + if (name == "drho") return 2; + if (name == "temperature") return 3; + if (name == "esph") return 4; + if (name == "heatflow") return 5; + if (name == "conductivity") return 6; + if (name == "pressure") return 7; + if (name == "viscosity") return 8; + return -1; +} + +/* ---------------------------------------------------------------------- + pack per-atom data into buf for ComputePropertyAtom + index maps to data specific to this atom style +------------------------------------------------------------------------- */ + +void AtomVecRHEOThermal::pack_property_atom(int index, double *buf, int nvalues, int groupbit) +{ + int *mask = atom->mask; + int nlocal = atom->nlocal; + int n = 0; + + if (index == 0) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = rheo_status[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 1) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = rho[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 2) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = drho[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 3) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = temperature[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 4) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = esph[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 5) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = heatflow[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 6) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = conductivity[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 7) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = pressure[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } else if (index == 8) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) + buf[n] = viscosity[i]; + else + buf[n] = 0.0; + n += nvalues; + } + } +} diff --git a/src/RHEO/atom_vec_rheo_thermal.h b/src/RHEO/atom_vec_rheo_thermal.h new file mode 100644 index 0000000000..eaf944ca96 --- /dev/null +++ b/src/RHEO/atom_vec_rheo_thermal.h @@ -0,0 +1,47 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef ATOM_CLASS +// clang-format off +AtomStyle(rheo/thermal,AtomVecRHEOThermal); +// clang-format on +#else + +#ifndef LMP_ATOM_VEC_RHEO_THERMAL_H +#define LMP_ATOM_VEC_RHEO_THERMAL_H + +#include "atom_vec.h" + +namespace LAMMPS_NS { + +class AtomVecRHEOThermal : virtual public AtomVec { + public: + AtomVecRHEOThermal(class LAMMPS *); + + void grow_pointers() override; + void force_clear(int, size_t) override; + void create_atom_post(int) override; + void data_atom_post(int) override; + int property_atom(const std::string &) override; + void pack_property_atom(int, double *, int, int) override; + + private: + int *rheo_status; + double *conductivity, *temperature, *heatflow, *esph; + double *pressure, *rho, *drho, *viscosity; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/bond_rheo_shell.cpp b/src/RHEO/bond_rheo_shell.cpp new file mode 100644 index 0000000000..258d047086 --- /dev/null +++ b/src/RHEO/bond_rheo_shell.cpp @@ -0,0 +1,591 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "bond_rheo_shell.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_surface.h" +#include "domain.h" +#include "error.h" +#include "fix_bond_history.h" +#include "fix_rheo.h" +#include "fix_rheo_oxidation.h" +#include "fix_store_local.h" +#include "force.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "update.h" + +#include +#include + +#define EPSILON 1e-10 + +using namespace LAMMPS_NS; +using namespace RHEO_NS; + +/* ---------------------------------------------------------------------- */ + +BondRHEOShell::BondRHEOShell(LAMMPS *_lmp) : + BondBPM(_lmp), compute_surface(nullptr), k(nullptr), ecrit(nullptr), gamma(nullptr) +{ + partial_flag = 1; + comm_reverse = 1; + + nhistory = 2; + update_flag = 1; + id_fix_bond_history = utils::strdup("HISTORY_RHEO_SHELL"); + ignore_special_flag = 1; + + tform = -1; + + single_extra = 1; + svector = new double[1]; + + // For nbond, create an instance of fix property atom + // Need restarts + exchanging with neighbors since it needs to persist + // between timesteps (fix property atom will handle callbacks) + + int tmp1, tmp2; + index_nb = atom->find_custom("shell_nbond", tmp1, tmp2); + if (index_nb == -1) { + id_fix = utils::strdup("bond_rheo_shell_fix_property_atom"); + modify->add_fix(fmt::format("{} all property/atom i_shell_nbond", id_fix)); + index_nb = atom->find_custom("shell_nbond", tmp1, tmp2); + } + nbond = atom->ivector[index_nb]; + + //Store non-persistent per atom quantities, intermediate + + nmax_store = atom->nmax; + memory->create(dbond, nmax_store, "rheo/react:dbond"); +} + +/* ---------------------------------------------------------------------- */ + +BondRHEOShell::~BondRHEOShell() +{ + if (modify->nfix) modify->delete_fix(id_fix); + delete[] id_fix; + delete[] svector; + + if (allocated) { + memory->destroy(setflag); + memory->destroy(k); + memory->destroy(ecrit); + memory->destroy(gamma); + } + + memory->destroy(dbond); +} + +/* ---------------------------------------------------------------------- + Store data for a single bond - if bond added after LAMMPS init (e.g. pour) +------------------------------------------------------------------------- */ + +double BondRHEOShell::store_bond(int n, int i, int j) +{ + double **bondstore = fix_bond_history->bondstore; + tagint *tag = atom->tag; + + bondstore[n][0] = 0.0; + bondstore[n][1] = 0.0; + + if (i < atom->nlocal) { + for (int m = 0; m < atom->num_bond[i]; m++) { + if (atom->bond_atom[i][m] == tag[j]) { + fix_bond_history->update_atom_value(i, m, 0, 0.0); + fix_bond_history->update_atom_value(i, m, 1, 0.0); + } + } + } + + if (j < atom->nlocal) { + for (int m = 0; m < atom->num_bond[j]; m++) { + if (atom->bond_atom[j][m] == tag[i]) { + fix_bond_history->update_atom_value(j, m, 0, 0.0); + fix_bond_history->update_atom_value(j, m, 1, 0.0); + } + } + } + + return 0.0; +} + +/* ---------------------------------------------------------------------- + Store data for all bonds called once +------------------------------------------------------------------------- */ + +void BondRHEOShell::store_data() +{ + int i, j, m, type; + int **bond_type = atom->bond_type; + + for (i = 0; i < atom->nlocal; i++) { + for (m = 0; m < atom->num_bond[i]; m++) { + type = bond_type[i][m]; + + //Skip if bond was turned off + if (type < 0) continue; + + // map to find index n + j = atom->map(atom->bond_atom[i][m]); + if (j == -1) error->one(FLERR, "Atom missing in BPM bond"); + + fix_bond_history->update_atom_value(i, m, 0, 0.0); + fix_bond_history->update_atom_value(i, m, 1, 0.0); + } + } + + fix_bond_history->post_neighbor(); +} + +/* ---------------------------------------------------------------------- */ + +void BondRHEOShell::compute(int eflag, int vflag) +{ + if (!fix_bond_history->stored_flag) { + fix_bond_history->stored_flag = true; + store_data(); + } + + if (hybrid_flag) + fix_bond_history->compress_history(); + + int i1, i2, itmp, n, type; + double delx, dely, delz, delvx, delvy, delvz; + double e, rsq, r, r0, rinv, dr, fbond, dot, t; + double dt = update->dt; + + ev_init(eflag, vflag); + + double *rsurface = compute_surface->rsurface; + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + tagint *tag = atom->tag; + int *status = atom->rheo_status; + int **bondlist = neighbor->bondlist; + int nbondlist = neighbor->nbondlist; + int nlocal = atom->nlocal; + int newton_bond = force->newton_bond; + + double **bondstore = fix_bond_history->bondstore; + + if (atom->nmax > nmax_store){ + nmax_store = atom->nmax; + memory->destroy(dbond); + memory->create(dbond, nmax_store, "rheo/shell:dbond"); + } + + size_t nbytes = nmax_store * sizeof(int); + memset(&dbond[0], 0, nbytes); + + for (n = 0; n < nbondlist; n++) { + // skip bond if already broken + if (bondlist[n][2] <= 0) continue; + + i1 = bondlist[n][0]; + i2 = bondlist[n][1]; + type = bondlist[n][2]; + r0 = bondstore[n][0]; + t = bondstore[n][1]; + + // Ensure pair is always ordered to ensure numerical operations + // are identical to minimize the possibility that a bond straddling + // an mpi grid (newton off) doesn't break on one proc but not the other + if (tag[i2] < tag[i1]) { + itmp = i1; + i1 = i2; + i2 = itmp; + } + + delx = x[i1][0] - x[i2][0]; + dely = x[i1][1] - x[i2][1]; + delz = x[i1][2] - x[i2][2]; + rsq = delx * delx + dely * dely + delz * delz; + r = sqrt(rsq); + + // If bond hasn't been set - zero data + if (t < EPSILON || std::isnan(t)) + t = store_bond(n, i1, i2); + + delx = x[i1][0] - x[i2][0]; + dely = x[i1][1] - x[i2][1]; + delz = x[i1][2] - x[i2][2]; + + rsq = delx * delx + dely * dely + delz * delz; + r = sqrt(rsq); + + // Bond has not yet formed, check if in range + update timer + if (t < tform) { + + // Check if eligible + if (r > rmax || rsurface[i1] > rsurf || rsurface[i2] > rsurf) { + bondlist[n][2] = 0; + process_ineligibility(i1, i2); + continue; + } + + // Check ellapsed time + t += dt; + bondstore[n][1] = t; + if (t >= tform) { + bondstore[n][0] = r; + r0 = r; + if (newton_bond || i1 < nlocal) dbond[i1]++; + if (newton_bond || i2 < nlocal) dbond[i2]++; + } else { + continue; + } + } + + e = (r - r0) / r0; + if (fabs(e) > ecrit[type]) { + bondlist[n][2] = 0; + process_broken(i1, i2); + if (newton_bond || i1 < nlocal) dbond[i1]--; + if (newton_bond || i2 < nlocal) dbond[i2]--; + continue; + } + + rinv = 1.0 / r; + dr = r - r0; + fbond = 2 * k[type] * (-dr + dr * dr * dr / (r0 * r0 * ecrit[type] * ecrit[type])); + + delvx = v[i1][0] - v[i2][0]; + delvy = v[i1][1] - v[i2][1]; + delvz = v[i1][2] - v[i2][2]; + dot = delx * delvx + dely * delvy + delz * delvz; + fbond -= gamma[type] * dot * rinv; + fbond *= rinv; + + if (newton_bond || i1 < nlocal) { + f[i1][0] += delx * fbond; + f[i1][1] += dely * fbond; + f[i1][2] += delz * fbond; + } + + if (newton_bond || i2 < nlocal) { + f[i2][0] -= delx * fbond; + f[i2][1] -= dely * fbond; + f[i2][2] -= delz * fbond; + } + + if (evflag) ev_tally(i1, i2, nlocal, newton_bond, 0.0, fbond, delx, dely, delz); + } + + // Communicate changes in nbond + if (newton_bond) comm->reverse_comm(this); + + for(int i = 0; i < nlocal; i++) { + nbond[i] += dbond[i]; + + // If it has bonds, no shifting + if (nbond[i] != 0) status[i] |= STATUS_NO_SHIFT; + } + + if (hybrid_flag) + fix_bond_history->uncompress_history(); +} + +/* ---------------------------------------------------------------------- */ + +void BondRHEOShell::allocate() +{ + allocated = 1; + const int np1 = atom->nbondtypes + 1; + + memory->create(k, np1, "bond:k"); + memory->create(ecrit, np1, "bond:ecrit"); + memory->create(gamma, np1, "bond:gamma"); + + memory->create(setflag, np1, "bond:setflag"); + for (int i = 1; i < np1; i++) setflag[i] = 0; +} + +/* ---------------------------------------------------------------------- + set coeffs for one or more types +------------------------------------------------------------------------- */ + +void BondRHEOShell::coeff(int narg, char **arg) +{ + if (narg != 4) error->all(FLERR, "Incorrect args for bond coefficients"); + if (!allocated) allocate(); + + int ilo, ihi; + utils::bounds(FLERR, arg[0], 1, atom->nbondtypes, ilo, ihi, error); + + double k_one = utils::numeric(FLERR, arg[1], false, lmp); + double ecrit_one = utils::numeric(FLERR, arg[2], false, lmp); + double gamma_one = utils::numeric(FLERR, arg[3], false, lmp); + + int count = 0; + for (int i = ilo; i <= ihi; i++) { + k[i] = k_one; + ecrit[i] = ecrit_one; + gamma[i] = gamma_one; + setflag[i] = 1; + count++; + + if (1.0 + ecrit[i] > max_stretch) max_stretch = 1.0 + ecrit[i]; + } + + if (count == 0) error->all(FLERR, "Incorrect args for bond coefficients"); +} + +/* ---------------------------------------------------------------------- + check for correct settings and create fix +------------------------------------------------------------------------- */ + +void BondRHEOShell::init_style() +{ + BondBPM::init_style(); + + if (comm->ghost_velocity == 0) + error->all(FLERR, "Bond rheo/shell requires ghost atoms store velocity"); + + auto fixes = modify->get_fix_by_style("^rheo$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use bond rheo/shell"); + class FixRHEO *fix_rheo = dynamic_cast(fixes[0]); + + if (!fix_rheo->surface_flag) error->all(FLERR, + "Bond rheo/shell requires surface calculation in fix rheo"); + compute_surface = fix_rheo->compute_surface; + + fixes = modify->get_fix_by_style("^rheo/oxidation$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo/oxidation to use bond rheo/shell"); + class FixRHEOOxidation *fix_rheo_oxidation = dynamic_cast(fixes[0]); + + rsurf = fix_rheo_oxidation->rsurf; + rmax = fix_rheo_oxidation->cut; +} + +/* ---------------------------------------------------------------------- */ + +void BondRHEOShell::settings(int narg, char **arg) +{ + BondBPM::settings(narg, arg); + + int iarg; + for (std::size_t i = 0; i < leftover_iarg.size(); i++) { + iarg = leftover_iarg[i]; + if (strcmp(arg[iarg], "t/form") == 0) { + if (iarg + 1 > narg) utils::missing_cmd_args(FLERR, "bond rheo/shell t/form", error); + tform = utils::numeric(FLERR, arg[iarg + 1], false, lmp); + i += 1; + } else { + error->all(FLERR, "Illegal bond rheo/shell command, invalid argument {}", arg[iarg]); + } + } + + if (tform < 0.0) + error->all(FLERR, "Illegal bond rheo/shell command, must specify positive formation time"); +} + + +/* ---------------------------------------------------------------------- + used to check bond communiction cutoff - not perfect, estimates based on local-local only +------------------------------------------------------------------------- */ + +double BondRHEOShell::equilibrium_distance(int /*i*/) +{ + // Divide out heuristic prefactor added in comm class + return max_stretch * rmax / 1.5; +} + +/* ---------------------------------------------------------------------- + proc 0 writes out coeffs to restart file +------------------------------------------------------------------------- */ + +void BondRHEOShell::write_restart(FILE *fp) +{ + BondBPM::write_restart(fp); + write_restart_settings(fp); + + fwrite(&k[1], sizeof(double), atom->nbondtypes, fp); + fwrite(&ecrit[1], sizeof(double), atom->nbondtypes, fp); + fwrite(&gamma[1], sizeof(double), atom->nbondtypes, fp); +} + +/* ---------------------------------------------------------------------- + proc 0 reads coeffs from restart file, bcasts them +------------------------------------------------------------------------- */ + +void BondRHEOShell::read_restart(FILE *fp) +{ + BondBPM::read_restart(fp); + read_restart_settings(fp); + allocate(); + + if (comm->me == 0) { + utils::sfread(FLERR, &k[1], sizeof(double), atom->nbondtypes, fp, nullptr, error); + utils::sfread(FLERR, &ecrit[1], sizeof(double), atom->nbondtypes, fp, nullptr, error); + utils::sfread(FLERR, &gamma[1], sizeof(double), atom->nbondtypes, fp, nullptr, error); + } + MPI_Bcast(&k[1], atom->nbondtypes, MPI_DOUBLE, 0, world); + MPI_Bcast(&ecrit[1], atom->nbondtypes, MPI_DOUBLE, 0, world); + MPI_Bcast(&gamma[1], atom->nbondtypes, MPI_DOUBLE, 0, world); + + for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1; +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file + ------------------------------------------------------------------------- */ + +void BondRHEOShell::write_restart_settings(FILE *fp) +{ + fwrite(&tform, sizeof(double), 1, fp); +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts + ------------------------------------------------------------------------- */ + +void BondRHEOShell::read_restart_settings(FILE *fp) +{ + if (comm->me == 0) { + utils::sfread(FLERR, &tform, sizeof(double), 1, fp, nullptr, error); + } + MPI_Bcast(&tform, 1, MPI_DOUBLE, 0, world); +} + + +/* ---------------------------------------------------------------------- */ + +int BondRHEOShell::pack_reverse_comm(int n, int first, double *buf) +{ + int i, m, last; + m = 0; + last = first + n; + + for (i = first; i < last; i++) { + buf[m++] = dbond[i]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void BondRHEOShell::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i, j, m; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + dbond[j] += buf[m++]; + } +} + +/* ---------------------------------------------------------------------- */ + +double BondRHEOShell::single(int type, double rsq, int i, int j, double &fforce) +{ + if (type <= 0) return 0.0; + + double r0, t; + for (int n = 0; n < atom->num_bond[i]; n++) { + if (atom->bond_atom[i][n] == atom->tag[j]) { + r0 = fix_bond_history->get_atom_value(i, n, 0); + t = fix_bond_history->get_atom_value(i, n, 1); + } + } + + svector[1] = t; + if (t < tform) return 0.0; + + double r = sqrt(rsq); + double rinv = 1.0 / r; + double dr = r0 - r; + fforce = 2 * k[type] * (dr + dr * dr * dr / (r0 * r0 * ecrit[type] * ecrit[type])); + + double **x = atom->x; + double **v = atom->v; + double delx = x[i][0] - x[j][0]; + double dely = x[i][1] - x[j][1]; + double delz = x[i][2] - x[j][2]; + double delvx = v[i][0] - v[j][0]; + double delvy = v[i][1] - v[j][1]; + double delvz = v[i][2] - v[j][2]; + double dot = delx * delvx + dely * delvy + delz * delvz; + fforce -= gamma[type] * dot * rinv; + fforce *= rinv; + + // set single_extra quantities + + svector[0] = r0; + + return 0.0; +} + +/* ---------------------------------------------------------------------- + Similar to BondBPM->process_broken(), but don't send to FixStoreLocal + ------------------------------------------------------------------------- */ + +void BondRHEOShell::process_ineligibility(int i, int j) +{ + // Manually search and remove from atom arrays + int m, n; + int nlocal = atom->nlocal; + + tagint *tag = atom->tag; + tagint **bond_atom = atom->bond_atom; + int **bond_type = atom->bond_type; + int *num_bond = atom->num_bond; + + if (i < nlocal) { + for (m = 0; m < num_bond[i]; m++) { + if (bond_atom[i][m] == tag[j] && setflag[bond_type[i][m]]) { + bond_type[i][m] = 0; + n = num_bond[i]; + bond_type[i][m] = bond_type[i][n - 1]; + bond_atom[i][m] = bond_atom[i][n - 1]; + for (auto &ihistory: histories) { + auto fix_bond_history2 = dynamic_cast (ihistory); + fix_bond_history2->shift_history(i, m, n - 1); + fix_bond_history2->delete_history(i, n - 1); + } + num_bond[i]--; + break; + } + } + } + + if (j < nlocal) { + for (m = 0; m < num_bond[j]; m++) { + if (bond_atom[j][m] == tag[i] && setflag[bond_type[j][m]]) { + bond_type[j][m] = 0; + n = num_bond[j]; + bond_type[j][m] = bond_type[j][n - 1]; + bond_atom[j][m] = bond_atom[j][n - 1]; + for (auto &ihistory: histories) { + auto fix_bond_history2 = dynamic_cast (ihistory); + fix_bond_history2->shift_history(j, m, n - 1); + fix_bond_history2->delete_history(j, n - 1); + } + num_bond[j]--; + break; + } + } + } +} diff --git a/src/RHEO/bond_rheo_shell.h b/src/RHEO/bond_rheo_shell.h new file mode 100644 index 0000000000..828f693ea3 --- /dev/null +++ b/src/RHEO/bond_rheo_shell.h @@ -0,0 +1,63 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef BOND_CLASS +// clang-format off +BondStyle(rheo/shell,BondRHEOShell); +// clang-format on +#else + +#ifndef LMP_BOND_RHEO_SHELL_H +#define LMP_BOND_RHEO_SHELL_H + +#include "bond_bpm.h" + +namespace LAMMPS_NS { + +class BondRHEOShell : public BondBPM { + public: + BondRHEOShell(class LAMMPS *); + ~BondRHEOShell() override; + void compute(int, int) override; + void coeff(int, char **) override; + void init_style() override; + void settings(int, char **) override; + double equilibrium_distance(int) override; + void write_restart(FILE *) override; + void read_restart(FILE *) override; + void write_restart_settings(FILE *) override; + void read_restart_settings(FILE *) override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + double single(int, double, int, int, double &) override; + + protected: + double *k, *ecrit, *gamma; + double tform, rmax, rsurf; + + int *dbond, *nbond; + int index_nb, nmax_store; + char *id_fix; + + class ComputeRHEOSurface *compute_surface; + + void process_ineligibility(int, int); + void allocate(); + void store_data(); + double store_bond(int, int, int); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/compute_rheo_grad.cpp b/src/RHEO/compute_rheo_grad.cpp new file mode 100644 index 0000000000..cdf90e1dc5 --- /dev/null +++ b/src/RHEO/compute_rheo_grad.cpp @@ -0,0 +1,506 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU) +----------------------------------------------------------------------- */ + +#include "compute_rheo_grad.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_kernel.h" +#include "compute_rheo_interface.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "memory.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "update.h" + +#include + +using namespace LAMMPS_NS; +using namespace RHEO_NS; + +enum{COMMGRAD, COMMFIELD}; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOGrad::ComputeRHEOGrad(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), fix_rheo(nullptr), list(nullptr), rho0(nullptr), compute_interface(nullptr), compute_kernel(nullptr), + gradv(nullptr), gradr(nullptr), grade(nullptr), gradn(nullptr) +{ + if (narg < 4) error->all(FLERR,"Illegal compute rheo/grad command"); + + velocity_flag = energy_flag = rho_flag = eta_flag = 0; + for (int iarg = 3; iarg < narg; iarg++) { + if (strcmp(arg[iarg], "velocity") == 0) velocity_flag = 1; + else if (strcmp(arg[iarg], "rho") == 0) rho_flag = 1; + else if (strcmp(arg[iarg], "energy") == 0) energy_flag = 1; + else if (strcmp(arg[iarg], "viscosity") == 0) eta_flag = 1; + else error->all(FLERR, "Illegal compute rheo/grad command, {}", arg[iarg]); + } + + ncomm_grad = 0; + ncomm_field = 0; + comm_reverse = 0; + + int dim = domain->dimension; + if (velocity_flag) { + ncomm_grad += dim * dim; + ncomm_field += dim; + comm_reverse += dim * dim; + } + + if (rho_flag) { + ncomm_grad += dim; + ncomm_field += 1; + comm_reverse += dim; + } + + if (energy_flag) { + ncomm_grad += dim; + ncomm_field += 1; + comm_reverse += dim; + } + + if (eta_flag) { + ncomm_grad += dim; + comm_reverse += dim; + } + + comm_forward = ncomm_grad; + + nmax_store = 0; + grow_arrays(atom->nmax); + +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOGrad::~ComputeRHEOGrad() +{ + memory->destroy(gradv); + memory->destroy(gradr); + memory->destroy(grade); + memory->destroy(gradn); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::init() +{ + cut = fix_rheo->cut; + cutsq = cut * cut; + rho0 = fix_rheo->rho0; + interface_flag = fix_rheo->interface_flag; + compute_kernel = fix_rheo->compute_kernel; + compute_interface = fix_rheo->compute_interface; + + remap_v_flag = domain->deform_vremap; + + neighbor->add_request(this, NeighConst::REQ_DEFAULT); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::compute_peratom() +{ + int i, j, k, ii, jj, jnum, itype, jtype, a, b, fluidi, fluidj; + double xtmp, ytmp, ztmp, delx, dely, delz; + double rsq, imass, jmass; + double rhoi, rhoj, Voli, Volj, drho, de, deta; + double vi[3], vj[3], vij[3]; + double wp, *dWij, *dWji; + + int inum, *ilist, *numneigh, **firstneigh; + int *jlist; + int nlocal = atom->nlocal; + + double **x = atom->x; + double **v = atom->v; + double *rho = atom->rho; + double *energy = atom->esph; + double *viscosity = atom->viscosity; + int *status = atom->rheo_status; + int *type = atom->type; + double *mass = atom->mass; + int newton = force->newton; + int dim = domain->dimension; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // initialize arrays + if (atom->nmax > nmax_store) grow_arrays(atom->nmax); + + for (i = 0; i < nmax_store; i++) { + if (velocity_flag) { + for (k = 0; k < dim * dim; k++) + gradv[i][k] = 0.0; + } + if (rho_flag) { + for (k = 0; k < dim; k++) + gradr[i][k] = 0.0; + } + if (energy_flag) { + for (k = 0; k < dim; k++) + grade[i][k] = 0.0; + } + if (eta_flag) { + for (k = 0; k < dim; k++) + gradn[i][k] = 0.0; + } + } + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + fluidi = !(status[i] & PHASECHECK); + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + jtype = type[j]; + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + + if (rsq < cutsq) { + fluidj = !(status[j] & PHASECHECK); + + rhoi = rho[i]; + rhoj = rho[j]; + + vi[0] = v[i][0]; + vi[1] = v[i][1]; + vi[2] = v[i][2]; + + vj[0] = v[j][0]; + vj[1] = v[j][1]; + vj[2] = v[j][2]; + + // Add corrections for walls + if (interface_flag) { + if (fluidi && (!fluidj)) { + compute_interface->correct_v(vj, vi, j, i); + rhoj = compute_interface->correct_rho(j, i); + } else if ((!fluidi) && fluidj) { + compute_interface->correct_v(vi, vj, i, j); + rhoi = compute_interface->correct_rho(i, j); + } else if ((!fluidi) && (!fluidj)) { + rhoi = rho0[itype]; + rhoj = rho0[jtype]; + } + } + + Voli = mass[itype] / rhoi; + Volj = mass[jtype] / rhoj; + + vij[0] = vi[0] - vj[0]; + vij[1] = vi[1] - vj[1]; + vij[2] = vi[2] - vj[2]; + + if (rho_flag) drho = rhoi - rhoj; + if (energy_flag) de = energy[i] - energy[j]; + if (eta_flag) deta = viscosity[i] - viscosity[j]; + + wp = compute_kernel->calc_dw(i, j, delx, dely, delz, sqrt(rsq)); + dWij = compute_kernel->dWij; + dWji = compute_kernel->dWji; + + for (a = 0; a < dim; a++) { + for (b = 0; b < dim; b++) { + if (velocity_flag) // uxx uxy uxz uyx uyy uyz uzx uzy uzz + gradv[i][a * dim + b] -= vij[a] * Volj * dWij[b]; + } + + if (rho_flag) // P,x P,y P,z + gradr[i][a] -= drho * Volj * dWij[a]; + + if (energy_flag) // e,x e,y e,z + grade[i][a] -= de * Volj * dWij[a]; + + if (eta_flag) // n,x n,y n,z + gradn[i][a] -= deta * Volj * dWij[a]; + } + + if (newton || j < nlocal) { + for (a = 0; a < dim; a++) { + for (b = 0; b < dim; b++) { + if (velocity_flag) // uxx uxy uxz uyx uyy uyz uzx uzy uzz + gradv[j][a * dim + b] += vij[a] * Voli * dWji[b]; + } + + if (rho_flag) // P,x P,y P,z + gradr[j][a] += drho * Voli * dWji[a]; + + if (energy_flag) // e,x e,y e,z + grade[j][a] += de * Voli * dWji[a]; + + if (eta_flag) // n,x n,y n,z + gradn[j][a] += deta * Voli * dWji[a]; + } + } + } + } + } + + if (newton) comm->reverse_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::forward_gradients() +{ + comm_stage = COMMGRAD; + comm_forward = ncomm_grad; + comm->forward_comm(this); +} + + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::forward_fields() +{ + comm_stage = COMMFIELD; + comm_forward = ncomm_field; + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOGrad::pack_forward_comm(int n, int *list, double *buf, + int pbc_flag, int *pbc) +{ + int i,j,k,m; + int *mask = atom->mask; + double *rho = atom->rho; + double *energy = atom->esph; + double **v = atom->v; + int dim = domain->dimension; + double *h_rate = domain->h_rate; + int deform_groupbit = domain->deform_groupbit; + double dv[3]; + + if (remap_v_flag) { + dv[0] = pbc[0] * h_rate[0] + pbc[5] * h_rate[5] + pbc[4] * h_rate[4]; + dv[1] = pbc[1] * h_rate[1] + pbc[3] * h_rate[3]; + dv[2] = pbc[2] * h_rate[2]; + } + + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + if (comm_stage == COMMGRAD) { + + if (velocity_flag) + for (k = 0; k < dim * dim; k++) + buf[m++] = gradv[j][k]; + + if (rho_flag) + for (k = 0; k < dim; k++) + buf[m++] = gradr[j][k]; + + if (energy_flag) + for (k = 0; k < dim; k++) + buf[m++] = grade[j][k]; + + if (eta_flag) + for (k = 0; k < dim; k++) + buf[m++] = gradn[j][k]; + + } else if (comm_stage == COMMFIELD) { + + if (velocity_flag) { + if (remap_v_flag && pbc_flag && (mask[j] & deform_groupbit)) { + for (k = 0; k < dim; k++) + buf[m++] = v[j][k] + dv[k]; + } else { + for (k = 0; k < dim; k++) + buf[m++] = v[j][k]; + } + } + + if (rho_flag) + buf[m++] = rho[j]; + + if (energy_flag) + buf[m++] = energy[j]; + } + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *rho = atom->rho; + double *energy = atom->esph; double **v = atom->v; + int dim = domain->dimension; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + if (comm_stage == COMMGRAD) { + if (velocity_flag) + for (k = 0; k < dim * dim; k++) + gradv[i][k] = buf[m++]; + + if (rho_flag) + for (k = 0; k < dim; k++) + gradr[i][k] = buf[m++]; + + if (energy_flag) + for (k = 0; k < dim; k++) + grade[i][k] = buf[m++]; + + if (eta_flag) + for (k = 0; k < dim; k++) + gradn[i][k] = buf[m++]; + + } else if (comm_stage == COMMFIELD) { + if (velocity_flag) + for (k = 0; k < dim; k++) + v[i][k] = buf[m++]; + + if (rho_flag) + rho[i] = buf[m++]; + + if (energy_flag) + energy[i] = buf[m++]; + } + } +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOGrad::pack_reverse_comm(int n, int first, double *buf) +{ + int i,k,m,last; + int dim = domain->dimension; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + if (velocity_flag) + for (k = 0; k < dim * dim; k++) + buf[m++] = gradv[i][k]; + + if (rho_flag) + for (k = 0; k < dim; k++) + buf[m++] = gradr[i][k]; + + if (energy_flag) + for (k = 0; k < dim; k++) + buf[m++] = grade[i][k]; + + if (eta_flag) + for (k = 0; k < dim; k++) + buf[m++] = gradn[i][k]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i,k,j,m; + int dim = domain->dimension; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + if (velocity_flag) + for (k = 0; k < dim * dim; k++) + gradv[j][k] += buf[m++]; + + if (rho_flag) + for (k = 0; k < dim; k++) + gradr[j][k] += buf[m++]; + + if (energy_flag) + for (k = 0; k < dim; k++) + grade[j][k] += buf[m++]; + + if (eta_flag) + for (k = 0; k < dim; k++) + gradn[j][k] += buf[m++]; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOGrad::grow_arrays(int nmax) +{ + int dim = domain->dimension; + if (velocity_flag) + memory->grow(gradv, nmax, dim * dim, "rheo:grad_v"); + + if (rho_flag) + memory->grow(gradr, nmax, dim, "rheo:grad_rho"); + + if (energy_flag) + memory->grow(grade, nmax, dim, "rheo:grad_energy"); + + if (eta_flag) + memory->grow(gradn, nmax, dim, "rheo:grad_eta"); + nmax_store = nmax; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOGrad::memory_usage() +{ + double bytes = 0.0; + int dim = domain->dimension; + + if (velocity_flag) + bytes = (size_t) nmax_store * dim * dim * sizeof(double); + + if (rho_flag) + bytes = (size_t) nmax_store * dim * sizeof(double); + + if (energy_flag) + bytes = (size_t) nmax_store * dim * sizeof(double); + + if (eta_flag) + bytes = (size_t) nmax_store * dim * sizeof(double); + + return bytes; +} diff --git a/src/RHEO/compute_rheo_grad.h b/src/RHEO/compute_rheo_grad.h new file mode 100644 index 0000000000..2d663a5b07 --- /dev/null +++ b/src/RHEO/compute_rheo_grad.h @@ -0,0 +1,64 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(RHEO/GRAD,ComputeRHEOGrad) +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_GRAD_H +#define LMP_COMPUTE_RHEO_GRAD_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputeRHEOGrad : public Compute { + public: + ComputeRHEOGrad(class LAMMPS *, int, char **); + ~ComputeRHEOGrad() override; + void init() override; + void init_list(int, class NeighList *) override; + void compute_peratom() override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + double memory_usage() override; + void forward_gradients(); + void forward_fields(); + double **gradv; + double **gradr; + double **grade; + double **gradn; + class FixRHEO *fix_rheo; + + private: + int comm_stage, ncomm_grad, ncomm_field, nmax_store; + double cut, cutsq, *rho0; + + int velocity_flag, energy_flag, rho_flag, eta_flag; + int interface_flag, remap_v_flag; + + class ComputeRHEOKernel *compute_kernel; + class ComputeRHEOInterface *compute_interface; + class NeighList *list; + + void grow_arrays(int); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/compute_rheo_interface.cpp b/src/RHEO/compute_rheo_interface.cpp new file mode 100644 index 0000000000..8ccd4e6a3b --- /dev/null +++ b/src/RHEO/compute_rheo_interface.cpp @@ -0,0 +1,384 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU), Eric Palermo (CMU) +----------------------------------------------------------------------- */ + +#include "compute_rheo_interface.h" + +#include "atom.h" +#include "comm.h" +#include "domain.h" +#include "compute_rheo_kernel.h" +#include "error.h" +#include "force.h" +#include "fix_rheo.h" +#include "fix_rheo_pressure.h" +#include "math_extra.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" + +#include + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace MathExtra; + +static constexpr double EPSILON = 1e-1; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOInterface::ComputeRHEOInterface(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), fix_rheo(nullptr), compute_kernel(nullptr), fp_store(nullptr), + rho0(nullptr), norm(nullptr), normwf(nullptr), chi(nullptr), id_fix_pa(nullptr) +{ + if (narg != 3) error->all(FLERR,"Illegal compute rheo/interface command"); + + comm_forward = 3; + comm_reverse = 4; + + nmax_store = atom->nmax; + memory->create(chi, nmax_store, "rheo:chi"); + memory->create(norm, nmax_store, "rheo/interface:norm"); + memory->create(normwf, nmax_store, "rheo/interface:normwf"); + + // For fp_store, create an instance of fix property atom + // Need restarts + exchanging with neighbors since it needs to persist + // between timesteps (fix property atom will handle callbacks) + + int tmp1, tmp2; + int index = atom->find_custom("fp_store", tmp1, tmp2); + if (index == -1) { + id_fix_pa = utils::strdup(id + std::string("_fix_property_atom")); + modify->add_fix(fmt::format("{} all property/atom d2_fp_store 3", id_fix_pa)); + index = atom->find_custom("fp_store", tmp1, tmp2); + } + fp_store = atom->darray[index]; +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOInterface::~ComputeRHEOInterface() +{ + if (id_fix_pa && modify->nfix) modify->delete_fix(id_fix_pa); + delete[] id_fix_pa; + memory->destroy(chi); + memory->destroy(norm); + memory->destroy(normwf); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::init() +{ + compute_kernel = fix_rheo->compute_kernel; + rho0 = fix_rheo->rho0; + cut = fix_rheo->cut; + cutsq = cut * cut; + wall_max = sqrt(3.0) / 12.0 * cut; + + auto fixes = modify->get_fix_by_style("rheo/pressure"); + fix_pressure = dynamic_cast(fixes[0]); + + neighbor->add_request(this, NeighConst::REQ_DEFAULT); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::compute_peratom() +{ + int a, i, j, ii, jj, jnum, itype, jtype, fluidi, fluidj, status_match; + double xtmp, ytmp, ztmp, rsq, w, dot, dx[3]; + + int inum, *ilist, *jlist, *numneigh, **firstneigh; + int nlocal = atom->nlocal; + int nall = nlocal + atom->nghost; + + double **x = atom->x; + int *type = atom->type; + int newton = force->newton; + int *status = atom->rheo_status; + double *rho = atom->rho; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + if (atom->nmax > nmax_store) { + nmax_store = atom->nmax; + memory->grow(norm, nmax_store, "rheo/interface:norm"); + memory->grow(normwf, nmax_store, "rheo/interface:normwf"); + memory->grow(chi, nmax_store, "rheo:chi"); + } + + for (i = 0; i < nall; i++) { + if (status[i] & PHASECHECK) rho[i] = 0.0; + normwf[i] = 0.0; + norm[i] = 0.0; + chi[i] = 0.0; + } + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + fluidi = !(status[i] & PHASECHECK); + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + rsq = lensq3(dx); + + if (rsq < cutsq) { + jtype = type[j]; + fluidj = !(status[j] & PHASECHECK); + w = compute_kernel->calc_w_quintic(i, j, dx[0], dx[1], dx[2], sqrt(rsq)); + + norm[i] += w; + + status_match = 0; + if ((fluidi && fluidj) || ((!fluidi) && (!fluidj))) + status_match = 1; + if (status_match) { + chi[i] += w; + } else { + if (!fluidi) { + dot = 0; + for (a = 0; a < 3; a++) + dot += (-fp_store[j][a] + fp_store[i][a]) * dx[a]; + + rho[i] += w * (fix_pressure->calc_pressure(rho[j], jtype) - rho[j] * dot); + normwf[i] += w; + } + } + + if (newton || j < nlocal) { + norm[j] += w; + if (status_match) { + chi[j] += w; + } else { + if (!fluidj) { + dot = 0; + for (a = 0; a < 3; a++) + dot += (-fp_store[i][a] + fp_store[j][a]) * dx[a]; + + rho[j] += w * (fix_pressure->calc_pressure(rho[i], itype) + rho[i] * dot); + normwf[j] += w; + } + } + } + } + } + } + + if (newton) comm->reverse_comm(this); + + for (i = 0; i < nlocal; i++) { + if (norm[i] != 0.0) chi[i] /= norm[i]; + + // Recalculate rho for non-fluid particles + if (status[i] & PHASECHECK) { + if (normwf[i] != 0.0) { + // Stores rho for solid particles 1+Pw in Adami Adams 2012 + rho[i] = MAX(EPSILON, fix_pressure->calc_rho(rho[i] / normwf[i], type[i])); + } else { + rho[i] = rho0[itype]; + } + } + } + + comm_stage = 1; + comm_forward = 2; + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOInterface::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/) +{ + int i, j, k, m; + m = 0; + double *rho = atom->rho; + + for (i = 0; i < n; i++) { + j = list[i]; + if (comm_stage == 0) { + buf[m++] = fp_store[j][0]; + buf[m++] = fp_store[j][1]; + buf[m++] = fp_store[j][2]; + } else { + buf[m++] = chi[j]; + buf[m++] = rho[j]; + } + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *rho = atom->rho; + m = 0; + last = first + n; + for (i = first; i < last; i++) { + if (comm_stage == 0) { + fp_store[i][0] = buf[m++]; + fp_store[i][1] = buf[m++]; + fp_store[i][2] = buf[m++]; + } else { + chi[i] = buf[m++]; + rho[i] = buf[m++]; + } + } +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOInterface::pack_reverse_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *rho = atom->rho; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + buf[m++] = norm[i]; + buf[m++] = chi[i]; + buf[m++] = normwf[i]; + buf[m++] = rho[i]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i, k, j, m; + double *rho = atom->rho; + int *status = atom->rheo_status; + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + norm[j] += buf[m++]; + chi[j] += buf[m++]; + if (status[j] & PHASECHECK){ + normwf[j] += buf[m++]; + rho[j] += buf[m++]; + } else { + m++; + m++; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::correct_v(double *v_solid, double *v_fluid, int i_solid, int i_fluid) +{ + double wall_prefactor, wall_denom, wall_numer; + + wall_numer = MAX(2.0 * cut * (chi[i_solid] - 0.5), 0.0); + wall_denom = MAX(2.0 * cut * (chi[i_fluid] - 0.5), wall_max); + + wall_prefactor = wall_numer / wall_denom; + + v_solid[0] = (v_solid[0] - v_fluid[0]) * wall_prefactor; + v_solid[1] = (v_solid[1] - v_fluid[1]) * wall_prefactor; + v_solid[2] = (v_solid[2] - v_fluid[2]) * wall_prefactor; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOInterface::correct_rho(int i_solid, int i_fluid) +{ + int itype = atom->type[i_solid]; + return MAX(rho0[itype], atom->rho[i_solid]); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOInterface::store_forces() +{ + double minv; + int *type = atom->type; + int *mask = atom->mask; + double *mass = atom->mass; + double **f = atom->f; + + // When this is called, fp_store stores the pressure force + // After this method, fp_store instead stores non-pressure forces + // and is also normalized by the particles mass + // If forces are overwritten by a fix, there are no pressure forces + // so just normalize + auto fixlist = modify->get_fix_by_style("setforce"); + if (fixlist.size() != 0) { + for (const auto &fix : fixlist) { + for (int i = 0; i < atom->nlocal; i++) { + minv = 1.0 / mass[type[i]]; + if (mask[i] & fix->groupbit) + for (int a = 0; a < 3; a++) + fp_store[i][a] = f[i][a] * minv; + else + for (int a = 0; a < 3; a++) + fp_store[i][a] = (f[i][a] - fp_store[i][a]) * minv; + } + } + } else { + for (int i = 0; i < atom->nlocal; i++) { + minv = 1.0 / mass[type[i]]; + for (int a = 0; a < 3; a++) + fp_store[i][a] = (f[i][a] - fp_store[i][a]) * minv; + } + } + + // Forward comm forces + comm_forward = 3; + comm_stage = 0; + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based array +------------------------------------------------------------------------- */ + +double ComputeRHEOInterface::memory_usage() +{ + double bytes = 3 * nmax_store * sizeof(double); + return bytes; +} + diff --git a/src/RHEO/compute_rheo_interface.h b/src/RHEO/compute_rheo_interface.h new file mode 100644 index 0000000000..a8cd448822 --- /dev/null +++ b/src/RHEO/compute_rheo_interface.h @@ -0,0 +1,61 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(RHEO/INTERFACE,ComputeRHEOInterface) +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_INTERFACE_H +#define LMP_COMPUTE_RHEO_INTERFACE_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputeRHEOInterface : public Compute { + public: + ComputeRHEOInterface(class LAMMPS *, int, char **); + ~ComputeRHEOInterface() override; + void init() override; + void init_list(int, class NeighList *) override; + void compute_peratom() override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + double memory_usage() override; + void correct_v(double *, double *, int, int); + double correct_rho(int, int); + void store_forces(); + + double *chi, **fp_store; + class FixRHEO *fix_rheo; + + private: + int nmax_store, comm_stage; + double *rho0, cut, cutsq, wall_max; + double *norm, *normwf; + + char *id_fix_pa; + + class NeighList *list; + class ComputeRHEOKernel *compute_kernel; + class FixRHEOPressure *fix_pressure; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/compute_rheo_kernel.cpp b/src/RHEO/compute_rheo_kernel.cpp new file mode 100644 index 0000000000..4558ddccc8 --- /dev/null +++ b/src/RHEO/compute_rheo_kernel.cpp @@ -0,0 +1,913 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU) +----------------------------------------------------------------------- */ + +#include "compute_rheo_kernel.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_interface.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "math_const.h" +#include "math_extra.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "pair.h" +#include "update.h" +#include "utils.h" + +#include +#include +#include +#include +#include + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace MathConst; +using namespace MathExtra; + +static constexpr int DELTA = 2000; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOKernel::ComputeRHEOKernel(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), + list(nullptr), C(nullptr), C0(nullptr), coordination(nullptr), compute_interface(nullptr) +{ + if (narg != 4) error->all(FLERR,"Illegal compute rheo/kernel command"); + + kernel_style = utils::inumeric(FLERR, arg[3], false, lmp); + + if (kernel_style == QUINTIC || kernel_style == WENDLANDC4) { + correction_order = -1; + } else if (kernel_style == RK0) { + correction_order = 0; + } else if (kernel_style == RK1) { + correction_order = 1; + } else if (kernel_style == RK2) { + correction_order = 2; + } + + dim = domain->dimension; + + comm_forward = 1; + ncor = 0; + Mdim = 0; + if (kernel_style == RK1) { + Mdim = 1 + dim; + ncor = 1 + dim; + comm_forward = ncor * Mdim; + } else if (kernel_style == RK2) { + //Polynomial basis size (up to quadratic order) + Mdim = 1 + dim + dim * (dim + 1) / 2; + //Number of sets of correction coefficients (1 x y xx yy) + z zz (3D) + ncor = 1 + 2 * dim; + comm_forward = ncor * Mdim; + } + + comm_forward_save = comm_forward; + corrections_calculated = 0; + gsl_error_flag = 0; +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOKernel::~ComputeRHEOKernel() +{ + memory->destroy(coordination); + memory->destroy(C); + memory->destroy(C0); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::init() +{ + neighbor->add_request(this, NeighConst::REQ_FULL); + + interface_flag = fix_rheo->interface_flag; + compute_interface = fix_rheo->compute_interface; + + zmin = fix_rheo->zmin_kernel; + cut = fix_rheo->cut; + cutsq = cut * cut; + cutinv = 1.0 / cut; + cutsqinv = cutinv * cutinv; + + + if (kernel_style != WENDLANDC4) { + if (dim == 3) { + pre_w = 1.0 / (120.0 * MY_PI) * 27.0 * cutsqinv * cutinv; + pre_wp = pre_w * 3.0 * cutinv; + } else { + pre_w = 7.0 / (478.0 * MY_PI) * 9 * cutsqinv; + pre_wp = pre_w * 3.0 * cutinv; + } + } else { + if (dim == 3) { + pre_w = 495.0 / (32.0 * MY_PI * cutsq * cut); + pre_wp = pre_w * cutinv; + } else { + pre_w = 9.0 / (MY_PI * cutsq); + pre_wp = pre_w * cutinv; + } + } + + nmax_store = atom->nmax; + memory->create(coordination, nmax_store, "rheo:coordination"); + if (kernel_style == RK0) { + memory->create(C0, nmax_store, "rheo/kernel:C0"); + } else if (kernel_style == RK1) { + memory->create(C, nmax_store, ncor, Mdim, "rheo/kernel:C"); + } else if (kernel_style == RK2) { + memory->create(C, nmax_store, ncor, Mdim, "rheo/kernel:C"); + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOKernel::check_corrections(int i) +{ + // Skip if there were gsl errors for this atom + if (gsl_error_flag) + if (gsl_error_tags.find(atom->tag[i]) != gsl_error_tags.end()) + return 0; + + // Skip if undercoordinated + if (coordination[i] < zmin) + return 0; + + // Skip if corrections not yet calculated + if (!corrections_calculated) + return 0; + + return 1; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w_self(int i, int j) +{ + double w; + if (kernel_style == WENDLANDC4) + w = calc_w_wendlandc4(i, j, 0.0, 0.0, 0.0, 0.0); + else + w = calc_w_quintic(i, j, 0.0, 0.0, 0.0, 0.0); + + return w; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w(int i, int j, double delx, double dely, double delz, double r) +{ + double w; + int corrections_i, corrections_j, corrections; + + if (kernel_style == WENDLANDC4) + return calc_w_wendlandc4(i, j, delx, dely, delz, r); + + if (kernel_style != QUINTIC) { + corrections_i = check_corrections(i); + corrections_j = check_corrections(j); + corrections = corrections_i & corrections_j; + } else { + corrections = 0; + } + + if (!corrections) w = calc_w_quintic(i, j, delx, dely, delz, r); + else if (kernel_style == RK0) w = calc_w_rk0(i, j, delx, dely, delz, r); + else if (kernel_style == RK1) w = calc_w_rk1(i, j, delx, dely, delz, r); + else if (kernel_style == RK2) w = calc_w_rk2(i, j, delx, dely, delz, r); + + return w; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_dw(int i, int j, double delx, double dely, double delz, double r) +{ + double wp; + int corrections_i, corrections_j; + + if (kernel_style == WENDLANDC4) + return calc_dw_wendlandc4(i, j, delx, dely, delz, r, dWij, dWji); + + if (kernel_style != QUINTIC) { + corrections_i = check_corrections(i); + corrections_j = check_corrections(j); + } + + // Calc wp and default dW's, a bit inefficient but can redo later + wp = calc_dw_quintic(i, j, delx, dely, delz, r, dWij, dWji); + + // Overwrite if there are corrections + if (kernel_style == RK1) { + if (corrections_i) calc_dw_rk1(i, j, delx, dely, delz, r, dWij); + if (corrections_j) calc_dw_rk1(j, i, -delx, -dely, -delz, r, dWji); + } else if (kernel_style == RK2) { + if (corrections_i) calc_dw_rk2(i, j, delx, dely, delz, r, dWij); + if (corrections_j) calc_dw_rk2(j, i, -delx, -dely, -delz, r, dWji); + } + + return wp; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w_quintic(int i, int j, double delx, double dely, double delz, double r) +{ + double w, tmp1, tmp2, tmp3, tmp1sq, tmp2sq, tmp3sq, s; + s = r * 3.0 * cutinv; + + if (s > 3.0) { + w = 0.0; + } + + if (s <= 3.0) { + tmp3 = 3.0 - s; + tmp3sq = tmp3 * tmp3; + w = tmp3sq * tmp3sq * tmp3; + } + if (s <= 2.0) { + tmp2 = 2.0 - s; + tmp2sq = tmp2 * tmp2; + w -= 6.0 * tmp2sq * tmp2sq * tmp2; + } + if (s <= 1.0) { + tmp1 = 1.0 - s; + tmp1sq = tmp1 * tmp1; + w += 15.0 * tmp1sq * tmp1sq * tmp1; + } + + w *= pre_w; + + Wij = w; + Wji = w; + + return w; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_dw_quintic(int i, int j, double delx, double dely, double delz, double r, double *dW1, double *dW2) +{ + double wp, tmp1, tmp2, tmp3, tmp1sq, tmp2sq, tmp3sq, s, wprinv; + double *mass = atom->mass; + int *type = atom->type; + + s = r * 3.0 * cutinv; + + if (s > 3.0) { + wp = 0.0; + } + if (s <= 3.0) { + tmp3 = 3.0 - s; + tmp3sq = tmp3 * tmp3; + wp = -5.0 * tmp3sq * tmp3sq; + } + if (s <= 2.0) { + tmp2 = 2.0 - s; + tmp2sq = tmp2 * tmp2; + wp += 30.0 * tmp2sq * tmp2sq; + } + if (s <= 1.0) { + tmp1 = 1.0 - s; + tmp1sq = tmp1 * tmp1; + wp -= 75.0 * tmp1sq * tmp1sq; + } + + wp *= pre_wp; + wprinv = wp / r; + dW1[0] = delx * wprinv; + dW1[1] = dely * wprinv; + dW1[2] = delz * wprinv; + + dW2[0] = -delx * wprinv; + dW2[1] = -dely * wprinv; + dW2[2] = -delz * wprinv; + + return wp; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w_wendlandc4(int i, int j, double delx, double dely, double delz, double r) +{ + double w, tmp6, s; + s = r * cutinv; + + if (s > 1.0) { + w = 0.0; + } else { + tmp6 = (1.0 - s) * (1.0 - s); + tmp6 *= tmp6 * tmp6; + w = tmp6 * (1.0 + 6.0 * s + 35.0 * THIRD * s * s); + } + + w *= pre_w; + + Wij = w; + Wji = w; + + return w; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_dw_wendlandc4(int i, int j, double delx, double dely, double delz, double r, double *dW1, double *dW2) +{ + double wp, tmp1, tmp5, tmp6, s, wprinv; + double *mass = atom->mass; + int *type = atom->type; + + s = r * cutinv; + + if (s > 1.0) { + wp = 0.0; + } else { + tmp1 = 1.0 - s; + tmp5 = tmp1 * tmp1; + tmp5 = tmp5 * tmp5 * tmp1; + tmp6 = tmp5 * tmp1; + wp = tmp6 * (6.0 + 70.0 * THIRD * s); + wp -= 6 * tmp5 * (1.0 + 6.0 * s + 35.0 * THIRD * s * s); + } + + wp *= pre_wp; + wprinv = wp / r; + dW1[0] = delx * wprinv; + dW1[1] = dely * wprinv; + dW1[2] = delz * wprinv; + + dW2[0] = -delx * wprinv; + dW2[1] = -dely * wprinv; + dW2[2] = -delz * wprinv; + + return wp; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w_rk0(int i, int j, double delx, double dely, double delz, double r) +{ + double w; + + w = calc_w_quintic(i, j, delx, dely, delz, r); + + Wij = C0[i] * w; + Wji = C0[j] * w; + + return w; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w_rk1(int i, int j, double delx, double dely, double delz, double r) +{ + int b; + double w, wR, dx[3], H[Mdim]; + + dx[0] = delx; + dx[1] = dely; + dx[2] = delz; + w = calc_w_quintic(i, j, delx, dely, delz, r); + + if (dim == 2) { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + } else { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = dx[2] * cutinv; + } + Wij = 0; + for (b = 0; b < Mdim; b++) { + Wij += C[i][0][b] * H[b]; // C columns: 1 x y (z) xx yy (zz) + } + Wij *= w; + + //Now compute Wji + H[1] *= -1; + H[2] *= -1; + if (dim == 3) H[3] *= -1; + + Wji = 0; + for (b = 0; b < Mdim; b++) { + Wji += C[j][0][b] * H[b]; // C columns: 1 x y (z) xx yy (zz) + } + Wji *= w; + + return w; +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::calc_w_rk2(int i, int j, double delx, double dely, double delz, double r) +{ + int b; + double w, wR, dx[3], H[Mdim]; + dx[0] = delx; + dx[1] = dely; + dx[2] = delz; + w = calc_w_quintic(i, j, delx, dely, delz, r); + + if (dim == 2) { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = 0.5 * dx[0] * dx[0] * cutsqinv; + H[4] = 0.5 * dx[1] * dx[1] * cutsqinv; + H[5] = dx[0] * dx[1] * cutsqinv; + } else { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = dx[2] * cutinv; + H[4] = 0.5 * dx[0] * dx[0] * cutsqinv; + H[5] = 0.5 * dx[1] * dx[1] * cutsqinv; + H[6] = 0.5 * dx[2] * dx[2] * cutsqinv; + H[7] = dx[0] * dx[1] * cutsqinv; + H[8] = dx[0] * dx[2] * cutsqinv; + H[9] = dx[1] * dx[2] * cutsqinv; + } + Wij = 0; + for (b = 0; b < Mdim; b++) { + Wij += C[i][0][b] * H[b]; // C columns: 1 x y (z) xx yy (zz) + } + Wij *= w; + + //Now compute Wji + H[1] *= -1; + H[2] *= -1; + if (dim == 3) H[3] *= -1; + + Wji = 0; + for (b = 0; b < Mdim; b++) { + Wji += C[j][0][b] * H[b]; // C columns: 1 x y (z) xx yy (zz) + } + Wji *= w; + + return w; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::calc_dw_rk1(int i, int j, double delx, double dely, double delz, double r, double *dW) +{ + int a, b; + double w, dx[3], H[Mdim]; + dx[0] = delx; + dx[1] = dely; + dx[2] = delz; + + w = calc_w_quintic(i, j, delx, dely, delz, r); + + //Populate correction basis + if (dim == 2) { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + } else { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = dx[2] * cutinv; + } + + // dWij[] = dWx dWy (dWz) + //compute derivative operators + for (a = 0; a < dim; a++) { + dW[a] = 0.0; + for (b = 0; b < Mdim; b++) { + //First derivative kernels + dW[a] += C[i][1 + a][b] * H[b]; // C columns: 1 x y (z) + } + dW[a] *= w; + } +} + + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::calc_dw_rk2(int i, int j, double delx, double dely, double delz, double r, double *dW) +{ + int a, b; + double w, dx[3], H[Mdim]; + dx[0] = delx; + dx[1] = dely; + dx[2] = delz; + + w = calc_w_quintic(i, j, delx, dely, delz, r); + + //Populate correction basis + if (dim == 2) { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = 0.5 * dx[0] * dx[0] * cutsqinv; + H[4] = 0.5 * dx[1] * dx[1] * cutsqinv; + H[5] = dx[0] * dx[1] * cutsqinv; + } else { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = dx[2] * cutinv; + H[4] = 0.5 * dx[0] * dx[0] * cutsqinv; + H[5] = 0.5 * dx[1] * dx[1] * cutsqinv; + H[6] = 0.5 * dx[2] * dx[2] * cutsqinv; + H[7] = dx[0] * dx[1] * cutsqinv; + H[8] = dx[0] * dx[2] * cutsqinv; + H[9] = dx[1] * dx[2] * cutsqinv; + } + + // dWij[] = dWx dWy (dWz) + //compute derivative operators + for (a = 0; a < dim; a++) { + dW[a] = 0.0; + for (b = 0; b < Mdim; b++) { + //First derivative kernels + dW[a] += C[i][1 + a][b] * H[b]; // C columns: 1 x y (z) xx yy (zz) + } + dW[a] *= w; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::compute_peratom() +{ + gsl_error_flag = 0; + gsl_error_tags.clear(); + + if (kernel_style == QUINTIC) return; + corrections_calculated = 1; + + int i, j, ii, jj, inum, jnum, itype, g, a, b, gsl_error; + double xtmp, ytmp, ztmp, r, rsq, w, vj, rhoj; + double dx[3]; + gsl_matrix_view gM; + + // Turn off GSL error handler, revert RK to Quintic when insufficient neighbors + gsl_set_error_handler_off(); + + double **x = atom->x; + int *type = atom->type; + double *mass = atom->mass; + double *rho = atom->rho; + int *status = atom->rheo_status; + tagint *tag = atom->tag; + + int *ilist, *jlist, *numneigh, **firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // Grow arrays if necessary + if (nmax_store < atom->nmax) grow_arrays(atom->nmax); + + if (kernel_style == RK0) { + + double M; + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + + jlist = firstneigh[i]; + jnum = numneigh[i]; + + //Initialize M to zero: + M = 0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + rsq = lensq3(dx); + + if (rsq < cutsq) { + r = sqrt(rsq); + w = calc_w_quintic(i, j, dx[0], dx[1], dx[2], r); + rhoj = rho[j]; + if (interface_flag) + if (status[j] & PHASECHECK) + rhoj = compute_interface->correct_rho(j, i); + + vj = mass[type[j]] / rhoj; + M += w * vj; + } + } + + // Inverse of 1x1 matrix + if (coordination[i] >= zmin) C0[i] = 1.0 / M; + } + } else if (correction_order > 0) { + + // Moment matrix M and polynomial basis vector cut (1d for gsl compatibility) + double H[Mdim], M[Mdim * Mdim]; + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + + jlist = firstneigh[i]; + jnum = numneigh[i]; + itype = type[i]; + + // Zero upper-triangle M and cut (will be symmetric): + for (a = 0; a < Mdim; a++) { + for (b = a; b < Mdim; b++) { + M[a * Mdim + b] = 0; + } + } + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + + rsq = lensq3(dx); + + if (rsq < cutsq) { + r = sqrt(rsq); + w = calc_w_quintic(i, j, dx[0], dx[1], dx[2], r); + + rhoj = rho[j]; + if (interface_flag) + if (status[j] & PHASECHECK) + rhoj = compute_interface->correct_rho(j, i); + + vj = mass[type[j]] / rhoj; + + //Populate the H-vector of polynomials (2D) + if (dim == 2) { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + if (kernel_style == RK2) { + H[3] = 0.5 * dx[0] * dx[0] * cutsqinv; + H[4] = 0.5 * dx[1] * dx[1] * cutsqinv; + H[5] = dx[0] * dx[1] * cutsqinv; + } + } else { + H[0] = 1.0; + H[1] = dx[0] * cutinv; + H[2] = dx[1] * cutinv; + H[3] = dx[2] * cutinv; + if (kernel_style == RK2) { + H[4] = 0.5 * dx[0] * dx[0] * cutsqinv; + H[5] = 0.5 * dx[1] * dx[1] * cutsqinv; + H[6] = 0.5 * dx[2] * dx[2] * cutsqinv; + H[7] = dx[0] * dx[1] * cutsqinv; + H[8] = dx[0] * dx[2] * cutsqinv; + H[9] = dx[1] * dx[2] * cutsqinv; + } + } + + // Populate the upper triangle + for (a = 0; a < Mdim; a++) { + for (b = a; b < Mdim; b++) { + M[a * Mdim + b] += H[a] * H[b] * w * vj; + } + } + } + } + + // Populate the lower triangle from the symmetric entries of M: + for (a = 0; a < Mdim; a++) { + for (b = a; b < Mdim; b++) { + M[b * Mdim + a] = M[a * Mdim + b]; + } + } + + // Skip if undercoordinated + if (coordination[i] < zmin) continue; + + // Use gsl to get Minv, use Cholesky decomposition since the + // polynomials are independent, M is symmetrix & positive-definite + gM = gsl_matrix_view_array(M,Mdim,Mdim); + gsl_error = gsl_linalg_cholesky_decomp1(&gM.matrix); + + if (gsl_error) { + //Revert to uncorrected SPH for this particle + gsl_error_flag = 1; + gsl_error_tags.insert(tag[i]); + + //check if not positive-definite + if (gsl_error != GSL_EDOM) + error->warning(FLERR, "Failed decomposition in rheo/kernel, gsl_error = {}", gsl_error); + + continue; + } + + gsl_linalg_cholesky_invert(&gM.matrix); //M is now M^-1 + + // Correction coefficients are columns of M^-1 multiplied by an appropriate coefficient + // Solve the linear system several times to get coefficientns + // M: 1 x y (z) x^2 y^2 (z^2) xy (xz) (yz) + // ---------------------------------------------------------- + // 0 1 2 3 4 5 || 2D indexing + // 0 1 2 3 4 5 6 7 8 9 || 3D indexing + // W 1 . . . . . . . . . + // dWx . -1 . . . . . . . . + // dWy . . -1 . . . . . . . + // dWz . . . (-1) . . . . . . + // d2Wx . . . . 2 . . . . . + // d2Wy . . . . . 2 . . . . + // d2Wz . . . . . . (2) . . . + + //0 1 2 3 4 + //0 1 2 3 4 5 6 + + // Pack coefficients into C + for (a = 0; a < Mdim; a++) { + C[i][0][a] = M[a * Mdim + 0]; // all rows of column 0 + for (b = 0; b < dim; b++) { + //First derivatives + C[i][1 + b][a] = -M[a * Mdim + b + 1] * cutinv; + // columns 1-2 (2D) or 1-3 (3D) + + //Second derivatives + if (kernel_style == RK2) + C[i][1 + dim + b][a] = M[a * Mdim + b + 1 + dim] * cutsqinv; + // columns 3-4 (2D) or 4-6 (3D) + } + } + } + } + + // communicate calculated quantities + comm_stage = 1; + comm_forward = comm_forward_save; + comm->forward_comm(this); +} + + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::compute_coordination() +{ + int i, j, ii, jj, inum, jnum; + double xtmp, ytmp, ztmp, rsq; + double dx[3]; + + double **x = atom->x; + + int *ilist, *jlist, *numneigh, **firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // Grow arrays if necessary + if (nmax_store < atom->nmax) grow_arrays(atom->nmax); + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + + jlist = firstneigh[i]; + jnum = numneigh[i]; + coordination[i] = 0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + rsq = lensq3(dx); + + if (rsq < cutsq) + coordination[i] += 1; + } + } + + // communicate calculated quantities + comm_stage = 0; + comm_forward = 1; + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::grow_arrays(int nmax) +{ + memory->grow(coordination, nmax, "rheo:coordination"); + + if (kernel_style == RK0) { + memory->grow(C0, nmax, "rheo/kernel:C0"); + } else if (correction_order > 0) { + memory->grow(C, nmax, ncor, Mdim, "rheo/kernel:C"); + } + + nmax_store = nmax; +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOKernel::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i,j,k,m,a,b; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + if (comm_stage == 0) { + buf[m++] = coordination[j]; + } else { + if (kernel_style == RK0) { + buf[m++] = C0[j]; + } else { + for (a = 0; a < ncor; a++) + for (b = 0; b < Mdim; b++) + buf[m++] = C[j][a][b]; + } + } + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOKernel::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last,a,b; + m = 0; + last = first + n; + + for (i = first; i < last; i++) { + if (comm_stage == 0) { + coordination[i] = buf[m++]; + } else { + if (kernel_style == RK0) { + C0[i] = buf[m++]; + } else { + for (a = 0; a < ncor; a++) + for (b = 0; b < Mdim; b++) + C[i][a][b] = buf[m++]; + } + } + } +} + +/* ---------------------------------------------------------------------- */ + +double ComputeRHEOKernel::memory_usage() +{ + double bytes = 0.0; + bytes = (size_t) nmax_store * sizeof(int); + + if (kernel_style == RK0) { + bytes += (size_t) nmax_store * sizeof(double); + } else if (correction_order > 0) { + bytes += (size_t) nmax_store * ncor * Mdim * sizeof(double); + } + return bytes; +} diff --git a/src/RHEO/compute_rheo_kernel.h b/src/RHEO/compute_rheo_kernel.h new file mode 100644 index 0000000000..d15e8e210a --- /dev/null +++ b/src/RHEO/compute_rheo_kernel.h @@ -0,0 +1,81 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(RHEO/KERNEL,ComputeRHEOKernel) +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_KERNEL_H +#define LMP_COMPUTE_RHEO_KERNEL_H + +#include "compute.h" +#include + +namespace LAMMPS_NS { + +class ComputeRHEOKernel : public Compute { + public: + ComputeRHEOKernel(class LAMMPS *, int, char **); + ~ComputeRHEOKernel() override; + void init() override; + void init_list(int, class NeighList *) override; + void compute_peratom() override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + double memory_usage() override; + void compute_coordination(); + double calc_w_self(int,int); + double calc_w(int,int,double,double,double,double); + double calc_dw(int,int,double,double,double,double); + double calc_w_quintic(int,int,double,double,double,double); + double calc_dw_quintic(int,int,double,double,double,double,double *,double *); + double calc_w_wendlandc4(int,int,double,double,double,double); + double calc_dw_wendlandc4(int,int,double,double,double,double,double *,double *); + void grow_arrays(int); + + double dWij[3], dWji[3], Wij, Wji; + int correction_order; + int *coordination; + class FixRHEO *fix_rheo; + + private: + int comm_stage, comm_forward_save; + int interface_flag; + int gsl_error_flag; + std::unordered_set gsl_error_tags; + + int corrections_calculated; + int kernel_style, zmin, dim, Mdim, ncor; + int nmax_store; + double cut, cutsq, cutinv, cutsqinv, pre_w, pre_wp; + double ***C; + double *C0; + + class NeighList *list; + class ComputeRHEOInterface *compute_interface; + + int check_corrections(int); + + double calc_w_rk0(int,int,double,double,double,double); + double calc_w_rk1(int,int,double,double,double,double); + double calc_w_rk2(int,int,double,double,double,double); + void calc_dw_rk1(int,int,double,double,double,double,double *); + void calc_dw_rk2(int,int,double,double,double,double,double *); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/compute_rheo_property_atom.cpp b/src/RHEO/compute_rheo_property_atom.cpp new file mode 100644 index 0000000000..7a450e7708 --- /dev/null +++ b/src/RHEO/compute_rheo_property_atom.cpp @@ -0,0 +1,614 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "compute_rheo_property_atom.h" + +#include "atom.h" +#include "atom_vec.h" +#include "compute_rheo_interface.h" +#include "compute_rheo_kernel.h" +#include "compute_rheo_surface.h" +#include "compute_rheo_vshift.h" +#include "compute_rheo_grad.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "fix_rheo_oxidation.h" +#include "fix_rheo_pressure.h" +#include "fix_rheo_thermal.h" +#include "memory.h" +#include "modify.h" +#include "update.h" +#include "utils.h" + +#include +#include + +using namespace LAMMPS_NS; +using namespace RHEO_NS; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOPropertyAtom::ComputeRHEOPropertyAtom(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), fix_rheo(nullptr), fix_pressure(nullptr), fix_thermal(nullptr), compute_interface(nullptr), + compute_kernel(nullptr), compute_surface(nullptr), compute_vshift(nullptr), compute_grad(nullptr), + avec_index(nullptr), pack_choice(nullptr), col_index(nullptr) +{ + if (narg < 4) utils::missing_cmd_args(FLERR, "compute property/atom", error); + + peratom_flag = 1; + int dim = domain->dimension; + + // Determine number of values + nvalues = 0; + for (int iarg = 3; iarg < narg; iarg++) { + if (strcmp(arg[iarg], "surface/n/*") == 0) { + nvalues += dim; + } else if (strcmp(arg[iarg], "shift/v/*") == 0) { + nvalues += dim; + } else if (strcmp(arg[iarg], "grad/v/*") == 0) { + nvalues += dim * dim; + } else if (strcmp(arg[iarg], "stress/v/*") == 0) { + nvalues += dim * dim; + } else if (strcmp(arg[iarg], "stress/t/*") == 0) { + nvalues += dim * dim; + } else { + nvalues += 1; + } + } + + if (nvalues == 1) size_peratom_cols = 0; + else size_peratom_cols = nvalues; + + pressure_flag = thermal_flag = interface_flag = 0; + surface_flag = shift_flag = shell_flag = 0; + + // parse input values + // customize a new keyword by adding to if statement + + pack_choice = new FnPtrPack[nvalues]; + avec_index = new int[nvalues]; + col_index = new int[nvalues]; + col_t_index = new int[nvalues]; + + int i = 0; + int index, a, b; + for (int iarg = 3; iarg < narg; iarg++) { + if (strcmp(arg[iarg], "phase") == 0) { + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_phase; + } else if (strcmp(arg[iarg], "status") == 0) { + // Short hand for "rheo_status" + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_status; + } else if (strcmp(arg[iarg], "chi") == 0) { + interface_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_chi; + } else if (strcmp(arg[iarg], "surface") == 0) { + surface_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_surface; + } else if (strcmp(arg[iarg], "surface/r") == 0) { + surface_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_surface_r; + } else if (strcmp(arg[iarg], "surface/divr") == 0) { + surface_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_surface_divr; + } else if (strcmp(arg[iarg], "coordination") == 0) { + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_coordination; + } else if (strcmp(arg[iarg], "pressure") == 0) { + pressure_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_pressure; + } else if (strcmp(arg[iarg], "cv") == 0) { + thermal_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_cv; + } else if (utils::strmatch(arg[iarg], "^surface/n/")) { + surface_flag = 1; + i += add_vector_component(arg[iarg], i, &ComputeRHEOPropertyAtom::pack_surface_n) - 1; + } else if (utils::strmatch(arg[iarg], "^shift/v/")) { + shift_flag = 1; + i += add_vector_component(arg[iarg], i, &ComputeRHEOPropertyAtom::pack_shift_v) - 1; + } else if (utils::strmatch(arg[iarg], "^grad/v/")) { + i += add_tensor_component(arg[iarg], i, &ComputeRHEOPropertyAtom::pack_gradv) - 1; + } else if (utils::strmatch(arg[iarg], "^stress/v/")) { + i += add_tensor_component(arg[iarg], i, &ComputeRHEOPropertyAtom::pack_viscous_stress) - 1; + } else if (utils::strmatch(arg[iarg], "^stress/t/")) { + i += add_tensor_component(arg[iarg], i, &ComputeRHEOPropertyAtom::pack_total_stress) - 1; + } else if (strcmp(arg[iarg], "energy") == 0) { + avec_index[i] = atom->avec->property_atom("esph"); + if (avec_index[i] < 0) + error->all(FLERR, + "Invalid keyword {} for atom style {} in compute rheo/property/atom command ", + arg[iarg], atom->get_style()); + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_atom_style; + thermal_flag = 1; + } else if (strcmp(arg[iarg], "nbond/shell") == 0) { + shell_flag = 1; + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_nbond_shell; + } else { + avec_index[i] = atom->avec->property_atom(arg[iarg]); + if (avec_index[i] < 0) + error->all(FLERR, + "Invalid keyword {} for atom style {} in compute rheo/property/atom command ", + arg[iarg], atom->get_style()); + pack_choice[i] = &ComputeRHEOPropertyAtom::pack_atom_style; + + if (strcmp(arg[iarg], "temperature") == 0) thermal_flag = 1; + if (strcmp(arg[iarg], "heatflow") == 0) thermal_flag = 1; + if (strcmp(arg[iarg], "conductivity") == 0) thermal_flag = 1; + } + i++; + } + + nmax = 0; +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOPropertyAtom::~ComputeRHEOPropertyAtom() +{ + delete[] pack_choice; + delete[] avec_index; + delete[] col_index; + delete[] col_t_index; + memory->destroy(vector_atom); + memory->destroy(array_atom); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::init() +{ + auto fixes = modify->get_fix_by_style("^rheo$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use compute rheo/property/atom"); + fix_rheo = dynamic_cast(fixes[0]); + + if (interface_flag && !(fix_rheo->interface_flag)) + error->all(FLERR, "Cannot request interfacial property without corresponding option in fix rheo"); + if (surface_flag && !(fix_rheo->surface_flag)) + error->all(FLERR, "Cannot request surface property without corresponding option in fix rheo"); + if (shift_flag && !(fix_rheo->shift_flag)) + error->all(FLERR, "Cannot request velocity shifting property without corresponding option in fix rheo"); + if (thermal_flag && !(fix_rheo->thermal_flag)) + error->all(FLERR, "Cannot request thermal property without fix rheo/thermal"); + + compute_interface = fix_rheo->compute_interface; + compute_kernel = fix_rheo->compute_kernel; + compute_surface = fix_rheo->compute_surface; + compute_vshift = fix_rheo->compute_vshift; + compute_grad = fix_rheo->compute_grad; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::setup() +{ + if (thermal_flag) { + auto fixes = modify->get_fix_by_style("rheo/thermal"); + fix_thermal = dynamic_cast(fixes[0]); + } + + if (pressure_flag) { + auto fixes = modify->get_fix_by_style("rheo/pressure"); + fix_pressure = dynamic_cast(fixes[0]); + } + + if (shell_flag) { + auto fixes = modify->get_fix_by_style("rheo/oxidation"); + fix_oxidation = dynamic_cast(fixes[0]); + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::compute_peratom() +{ + invoked_peratom = update->ntimestep; + + // grow vector or array if necessary + + if (atom->nmax > nmax) { + nmax = atom->nmax; + if (nvalues == 1) { + memory->destroy(vector_atom); + memory->create(vector_atom, nmax, "rheo/property/atom:vector"); + } else { + memory->destroy(array_atom); + memory->create(array_atom, nmax, nvalues, "rheo/property/atom:array"); + } + } + + // fill vector or array with per-atom values + + if (nvalues == 1) { + buf = vector_atom; + (this->*pack_choice[0])(0); + } else { + if (nmax) buf = &array_atom[0][0]; + else buf = nullptr; + for (int n = 0; n < nvalues; n++) + (this->*pack_choice[n])(n); + } +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based array +------------------------------------------------------------------------- */ + +double ComputeRHEOPropertyAtom::memory_usage() +{ + double bytes = (double)nmax * nvalues * sizeof(double); + return bytes; +} + +/* ---------------------------------------------------------------------- + one method for every keyword compute rheo/property/atom can output + the atom property is packed into buf starting at n with stride nvalues + customize a new keyword by adding a method +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_phase(int n) +{ + int *status = atom->rheo_status; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = (status[i] & PHASECHECK); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_status(int n) +{ + int *status = atom->rheo_status; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = status[i]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_chi(int n) +{ + double *chi = compute_interface->chi; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = chi[i]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_surface(int n) +{ + int *status = atom->rheo_status; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double label; + for (int i = 0; i < nlocal; i++) { + label = 0; + if (mask[i] & groupbit) { + if (status[i] & STATUS_SURFACE) label = 1.0; + if (status[i] & STATUS_SPLASH) label = 2.0; + } + buf[n] = label; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_surface_r(int n) +{ + double *rsurface = compute_surface->rsurface; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = rsurface[i]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_surface_divr(int n) +{ + double *divr = compute_surface->divr; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = divr[i]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_surface_n(int n) +{ + double **nsurface = compute_surface->nsurface; + int *mask = atom->mask; + int nlocal = atom->nlocal; + int index = col_index[n]; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = nsurface[i][index]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_coordination(int n) +{ + int *coordination = compute_kernel->coordination; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = coordination[i]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_cv(int n) +{ + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = fix_thermal->calc_cv(i, type[i]); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_pressure(int n) +{ + int *type = atom->type; + int *mask = atom->mask; + double *rho = atom->rho; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = fix_pressure->calc_pressure(rho[i], type[i]); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_viscous_stress(int n) +{ + double **gradv = compute_grad->gradv; + double *viscosity = atom->viscosity; + int *mask = atom->mask; + int nlocal = atom->nlocal; + int index = col_index[n]; + int dim = domain->dimension; + int a = index / dim; + int b = index % dim; + int index_transpose = b * dim + a; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = viscosity[i] * (gradv[i][index] + gradv[i][index_transpose]); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_total_stress(int n) +{ + double **gradv = compute_grad->gradv; + double *viscosity = atom->viscosity; + double *rho = atom->rho; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + int index = col_index[n]; + int dim = domain->dimension; + int a = index / dim; + int b = index % dim; + int index_transpose = b * dim + a; + double p; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (index == index_transpose) + p = fix_pressure->calc_pressure(rho[i], type[i]); + else + p = 0.0; + buf[n] = viscosity[i] * (gradv[i][index] + gradv[i][index_transpose]) + p; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_nbond_shell(int n) +{ + int *nbond = fix_oxidation->nbond; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = nbond[i]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_shift_v(int n) +{ + double **vshift = compute_vshift->vshift; + int *mask = atom->mask; + int nlocal = atom->nlocal; + int index = col_index[n]; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = vshift[i][index]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_gradv(int n) +{ + double **gradv = compute_grad->gradv; + int *mask = atom->mask; + int nlocal = atom->nlocal; + int index = col_index[n]; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = gradv[i][index]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOPropertyAtom::pack_atom_style(int n) +{ + atom->avec->pack_property_atom(avec_index[n], &buf[n], nvalues, groupbit); +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOPropertyAtom::add_tensor_component(char* option, int i, FnPtrPack pack_function) +{ + int shift; + int dim = domain->dimension; + if (((std::string) option).back() == '*') { + for (int a = 0; a < dim; a++) { + for (int b = 0; b < dim; b++) { + pack_choice[i + a * dim + b] = pack_function; + col_index[i + a * dim + b] = a * dim + b; + } + } + shift = dim * dim; + } else { + int index; + int dim_error = 0; + + if (utils::strmatch(option, "xx$")) { + index = 0; + } else if (utils::strmatch(option, "xy$")) { + index = 1; + } else if (utils::strmatch(option, "xz$")) { + index = 2; + if (dim == 2) dim_error = 1; + } else if (utils::strmatch(option, "yx$")) { + if (dim == 2) index = 2; + else index = 3; + } else if (utils::strmatch(option, "yy$")) { + if (dim == 2) index = 3; + else index = 4; + } else if (utils::strmatch(option, "yz$")) { + index = 5; + if (dim == 2) dim_error = 1; + } else if (utils::strmatch(option, "zx$")) { + index = 6; + if (dim == 2) dim_error = 1; + } else if (utils::strmatch(option, "zy$")) { + index = 7; + if (dim == 2) dim_error = 1; + } else if (utils::strmatch(option, "zz$")) { + index = 8; + if (dim == 2) dim_error = 1; + } else { + error->all(FLERR, "Invalid compute rheo/property/atom property {}", option); + } + + if (dim_error) + error->all(FLERR, "Invalid compute rheo/property/atom property {} in 2D", option); + + pack_choice[i] = pack_function; + col_index[i] = index; + shift = 1; + } + + return shift; +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOPropertyAtom::add_vector_component(char* option, int i, FnPtrPack pack_function) +{ + int shift; + int dim = domain->dimension; + if (((std::string) option).back() == '*') { + for (int a = 0; a < dim; a++) { + pack_choice[i + a] = pack_function; + col_index[i + a] = a; + } + shift = dim; + } else { + int index; + if (utils::strmatch(option, "x$")) { + index = 0; + } else if (utils::strmatch(option, "y$")) { + index = 1; + } else if (utils::strmatch(option, "z$")) { + if (dim == 2) + error->all(FLERR, "Invalid compute rheo/property/atom property {} in 2D", option); + index = 2; + } else { + error->all(FLERR, "Invalid compute rheo/property/atom property {}", option); + } + + pack_choice[i] = pack_function; + col_index[i] = index; + shift = 1; + } + + return shift; +} diff --git a/src/RHEO/compute_rheo_property_atom.h b/src/RHEO/compute_rheo_property_atom.h new file mode 100644 index 0000000000..4b1ebf2313 --- /dev/null +++ b/src/RHEO/compute_rheo_property_atom.h @@ -0,0 +1,83 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(rheo/property/atom,ComputeRHEOPropertyAtom); +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_PROPERTY_ATOM_H +#define LMP_COMPUTE_RHEO_PROPERTY_ATOM_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputeRHEOPropertyAtom : public Compute { + public: + ComputeRHEOPropertyAtom(class LAMMPS *, int, char **); + ~ComputeRHEOPropertyAtom() override; + void init() override; + void setup() override; + void compute_peratom() override; + double memory_usage() override; + + private: + int nvalues, nmax; + int pressure_flag, thermal_flag, interface_flag; + int surface_flag, shift_flag, shell_flag; + int *avec_index; + int *col_index, *col_t_index; + double *buf; + + typedef void (ComputeRHEOPropertyAtom::*FnPtrPack)(int); + FnPtrPack *pack_choice; // ptrs to pack functions + + void pack_phase(int); + void pack_status(int); + void pack_chi(int); + void pack_surface(int); + void pack_surface_r(int); + void pack_surface_divr(int); + void pack_surface_n(int); + void pack_coordination(int); + void pack_cv(int); + void pack_shift_v(int); + void pack_gradv(int); + void pack_pressure(int); + void pack_viscous_stress(int); + void pack_total_stress(int); + void pack_nbond_shell(int); + void pack_atom_style(int); + + int add_vector_component(char*, int, FnPtrPack); + int add_tensor_component(char*, int, FnPtrPack); + + class FixRHEO *fix_rheo; + class FixRHEOPressure *fix_pressure; + class FixRHEOThermal *fix_thermal; + class FixRHEOOxidation *fix_oxidation; + class ComputeRHEOInterface *compute_interface; + class ComputeRHEOKernel *compute_kernel; + class ComputeRHEOSurface *compute_surface; + class ComputeRHEOVShift *compute_vshift; + class ComputeRHEOGrad *compute_grad; + +}; + +} // namespace LAMMPS_NS + +#endif +#endif + diff --git a/src/RHEO/compute_rheo_rho_sum.cpp b/src/RHEO/compute_rheo_rho_sum.cpp new file mode 100644 index 0000000000..6e25b35374 --- /dev/null +++ b/src/RHEO/compute_rheo_rho_sum.cpp @@ -0,0 +1,197 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "compute_rheo_rho_sum.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_kernel.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEORhoSum::ComputeRHEORhoSum(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), fix_rheo(nullptr), compute_kernel(nullptr) +{ + if (narg != 4) error->all(FLERR,"Illegal compute RHEO/rho command"); + + self_mass_flag = utils::bnumeric(FLERR, arg[3], false, lmp); + + comm_forward = 1; + comm_reverse = 1; +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEORhoSum::~ComputeRHEORhoSum() {} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEORhoSum::init() +{ + compute_kernel = fix_rheo->compute_kernel; + cut = fix_rheo->cut; + cutsq = cut * cut; + + // need an occasional half neighbor list + neighbor->add_request(this, NeighConst::REQ_DEFAULT); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEORhoSum::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + + +void ComputeRHEORhoSum::compute_peratom() +{ + int i, j, ii, jj, inum, jnum, itype, jtype; + double xtmp, ytmp, ztmp, delx, dely, delz; + int *ilist, *jlist, *numneigh, **firstneigh; + double rsq, w; + + int nlocal = atom->nlocal; + + double **x = atom->x; + double *rho = atom->rho; + int *type = atom->type; + double *mass = atom->mass; + int newton = force->newton; + + double jmass; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + int nall = nlocal + atom->nghost; + + // initialize arrays, local with quintic self-contribution, ghosts are zeroed + for (i = 0; i < nlocal; i++) { + w = compute_kernel->calc_w_self(i, i); + rho[i] = w * mass[type[i]]; + } + + for (i = nlocal; i < nall; i++) rho[i] = 0.0; + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + if (rsq < cutsq) { + w = compute_kernel->calc_w(i, j, delx, dely, delz, sqrt(rsq)); + + if (self_mass_flag) { + rho[i] += w * mass[type[i]]; + if (newton || j < nlocal) + rho[j] += w * mass[type[j]]; + } else { + rho[i] += w * mass[type[j]]; + if (newton || j < nlocal) + rho[j] += w * mass[type[i]]; + } + } + } + } + + if (newton) comm->reverse_comm(this); + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEORhoSum::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i, j, k, m; + double *rho = atom->rho; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = rho[j]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ +void ComputeRHEORhoSum::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *rho = atom->rho; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + rho[i] = buf[m++]; + } +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEORhoSum::pack_reverse_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *rho = atom->rho; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + buf[m++] = rho[i]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEORhoSum::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i, k, j, m; + double *rho = atom->rho; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + rho[j] += buf[m++]; + } +} diff --git a/src/RHEO/compute_rheo_rho_sum.h b/src/RHEO/compute_rheo_rho_sum.h new file mode 100644 index 0000000000..491e61ea81 --- /dev/null +++ b/src/RHEO/compute_rheo_rho_sum.h @@ -0,0 +1,52 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(RHEO/RHO/SUM,ComputeRHEORhoSum) +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_RHO_SUM_H +#define LMP_COMPUTE_RHEO_RHO_SUM_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputeRHEORhoSum : public Compute { + public: + ComputeRHEORhoSum(class LAMMPS *, int, char **); + ~ComputeRHEORhoSum() override; + void init() override; + void init_list(int, class NeighList *) override; + void compute_peratom() override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + + class FixRHEO *fix_rheo; + + private: + int self_mass_flag; + double cut, cutsq; + + class NeighList *list; + class ComputeRHEOKernel *compute_kernel; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/compute_rheo_surface.cpp b/src/RHEO/compute_rheo_surface.cpp new file mode 100644 index 0000000000..c3a3774cdc --- /dev/null +++ b/src/RHEO/compute_rheo_surface.cpp @@ -0,0 +1,417 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU), Eric Palermo (CMU) +----------------------------------------------------------------------- */ + +#include "compute_rheo_surface.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_interface.h" +#include "compute_rheo_kernel.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "math_extra.h" +#include "memory.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace FixConst; +using namespace MathExtra; + +static constexpr double EPSILON = 1e-10; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOSurface::ComputeRHEOSurface(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), fix_rheo(nullptr), list(nullptr), rho0(nullptr), compute_kernel(nullptr), compute_interface(nullptr), + B(nullptr), gradC(nullptr), nsurface(nullptr), divr(nullptr), rsurface(nullptr) +{ + if (narg != 3) error->all(FLERR,"Illegal compute RHEO/SURFACE command"); + + int dim = domain->dimension; + comm_forward = 2; + comm_reverse = dim * dim + 1; + + nmax_store = 0; + grow_arrays(atom->nmax); +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOSurface::~ComputeRHEOSurface() +{ + memory->destroy(divr); + memory->destroy(rsurface); + memory->destroy(nsurface); + memory->destroy(B); + memory->destroy(gradC); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOSurface::init() +{ + compute_kernel = fix_rheo->compute_kernel; + compute_interface = fix_rheo->compute_interface; + cut = fix_rheo->cut; + rho0 = fix_rheo->rho0; + threshold_style = fix_rheo->surface_style; + threshold_divr = fix_rheo->divr_surface; + threshold_z = fix_rheo->zmin_surface; + threshold_splash = fix_rheo->zmin_splash; + interface_flag = fix_rheo->interface_flag; + + cutsq = cut * cut; + + // need an occasional half neighbor list + neighbor->add_request(this, NeighConst::REQ_DEFAULT); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOSurface::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOSurface::compute_peratom() +{ + int i, j, ii, jj, inum, jnum, a, b, itype, jtype, fluidi, fluidj; + double xtmp, ytmp, ztmp, rsq, Voli, Volj, rhoi, rhoj, wp; + double dWij[3], dWji[3], dx[3]; + int *ilist, *jlist, *numneigh, **firstneigh; + + int nlocal = atom->nlocal; + + double **x = atom->x; + int *status = atom->rheo_status; + int newton = force->newton; + int dim = domain->dimension; + int *mask = atom->mask; + int *type = atom->type; + double *mass = atom->mass; + double *rho = atom->rho; + int *coordination = compute_kernel->coordination; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // Grow and zero arrays + if (nmax_store < atom->nmax) + grow_arrays(atom->nmax); + + size_t nbytes = nmax_store * sizeof(double); + memset(&divr[0], 0, nbytes); + memset(&rsurface[0], 0, nbytes); + memset(&nsurface[0][0], 0, dim * nbytes); + memset(&gradC[0][0], 0, dim * dim * nbytes); + memset(&B[0][0], 0, dim * dim * nbytes); + + + // loop over neighbors to calculate the average orientation of neighbors + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + + jlist = firstneigh[i]; + jnum = numneigh[i]; + itype = type[i]; + fluidi = !(status[i] & PHASECHECK); + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + + rsq = lensq3(dx); + if (rsq < cutsq) { + jtype = type[j]; + fluidj = !(status[j] & PHASECHECK); + + rhoi = rho[i]; + rhoj = rho[j]; + + // Add corrections for walls + if (interface_flag) { + if (fluidi && (!fluidj)) { + rhoj = compute_interface->correct_rho(j, i); + } else if ((!fluidi) && fluidj) { + rhoi = compute_interface->correct_rho(i, j); + } else if ((!fluidi) && (!fluidj)) { + rhoi = rho0[itype]; + rhoj = rho0[jtype]; + } + } + + Voli = mass[itype] / rhoi; + Volj = mass[jtype] / rhoj; + + wp = compute_kernel->calc_dw_quintic(i, j, dx[0], dx[1], dx[2], sqrt(rsq), dWij, dWji); + + for (a = 0; a < dim; a++) { + divr[i] -= dWij[a] * dx[a] * Volj; + gradC[i][a] += dWij[a] * Volj; + } + + if ((j < nlocal) || newton) { + for (a = 0; a < dim; a++){ + divr[j] += dWji[a] * dx[a] * Voli; + gradC[j][a] += dWji[a] * Voli; + } + } + } + } + } + + // reverse gradC and divr, forward divr + comm_stage = 0; + comm_reverse = dim * dim + 1; + comm_forward = 1; + if (newton) comm->reverse_comm(this); + comm->forward_comm(this); + + // calculate nsurface for local atoms + // Note, this isn't forwarded to ghosts + double maggC; + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + maggC = 0.0; + for (a = 0;a < dim; a++) + maggC += gradC[i][a] * gradC[i][a]; + maggC = sqrt(maggC) + EPSILON; + maggC = 1.0 / maggC; + for (a = 0; a < dim; a++) + nsurface[i][a] = -gradC[i][a] * maggC; + } + } + + // Remove surface settings and assign new values + int nall = nlocal + atom->nghost; + int test; + + for (i = 0; i < nall; i++) { + status[i] &= SURFACEMASK; + if (mask[i] & groupbit) { + if (threshold_style == DIVR) + test = divr[i] < threshold_divr; + else + test = coordination[i] < threshold_z; + + // Treat nonfluid particles as bulk + if (status[i] & PHASECHECK) + test = 0; + + if (test) { + if (coordination[i] < threshold_splash) + status[i] |= STATUS_SPLASH; + else + status[i] |= STATUS_SURFACE; + rsurface[i] = 0.0; + } else { + status[i] |= STATUS_BULK; + rsurface[i] = cut; + } + } + } + + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + fluidi = !(status[i] & PHASECHECK); + + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + fluidj = !(status[j] & PHASECHECK); + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + rsq = lensq3(dx); + if (rsq < cutsq) { + if (fluidi) { + if ((status[i] & STATUS_BULK) && (status[j] & STATUS_SURFACE)) { + status[i] &= SURFACEMASK; + status[i] |= STATUS_LAYER; + } + + if (status[j] & STATUS_SURFACE) + rsurface[i] = MIN(rsurface[i], sqrt(rsq)); + } + + if (fluidj && (j < nlocal || newton)) { + if ((status[j] & STATUS_BULK) && (status[j] & PHASECHECK) && (status[i] & STATUS_SURFACE)) { + status[j] &= SURFACEMASK; + status[j] |= STATUS_LAYER; + } + + if (status[i] & STATUS_SURFACE) + rsurface[j] = MIN(rsurface[j], sqrt(rsq)); + } + } + } + } + + // clear normal vectors for non-surface particles + + for (i = 0; i < nall; i++) { + if (mask[i] & groupbit) { + if (!(status[i] & STATUS_SURFACE)) + for (a = 0; a < dim; a++) + nsurface[i][a] = 0.0; + } + } + + // forward/reverse status and rsurface + comm_stage = 1; + comm_reverse = 2; + comm_forward = 2; + if (newton) comm->reverse_comm(this); + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOSurface::pack_reverse_comm(int n, int first, double *buf) +{ + int i,a,b,k,m,last; + int dim = domain->dimension; + int *status = atom->rheo_status; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + if (comm_stage == 0) { + buf[m++] = divr[i]; + for (a = 0; a < dim; a ++ ) + for (b = 0; b < dim; b ++) + buf[m++] = gradC[i][a * dim + b]; + } else if (comm_stage == 1) { + buf[m++] = (double) status[i]; + buf[m++] = rsurface[i]; + } + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOSurface::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i,a,b,k,j,m; + int dim = domain->dimension; + int *status = atom->rheo_status; + int tmp1; + double tmp2; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + if (comm_stage == 0) { + divr[j] += buf[m++]; + for (a = 0; a < dim; a ++ ) + for (b = 0; b < dim; b ++) + gradC[j][a * dim + b] += buf[m++]; + } else if (comm_stage == 1) { + tmp1 = (int) buf[m++]; + if ((status[j] & STATUS_BULK) && (tmp1 & STATUS_LAYER)) { + status[j] &= SURFACEMASK; + status[j] |= STATUS_LAYER; + } + tmp2 = buf[m++]; + rsurface[j] = MIN(rsurface[j], tmp2); + } + } +} + + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOSurface::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i,j,a,b,k,m; + int *status = atom->rheo_status; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + if (comm_stage == 0) { + buf[m++] = divr[j]; + } else if (comm_stage == 1) { + buf[m++] = (double) status[j]; + buf[m++] = rsurface[j]; + } + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOSurface::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, a, b, m, last; + int *status = atom->rheo_status; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + if (comm_stage == 0) { + divr[i] = buf[m++]; + } else if (comm_stage == 1) { + status[i] = (int) buf[m++]; + rsurface[i] = buf[m++]; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOSurface::grow_arrays(int nmax) +{ + int dim = domain->dimension; + + memory->grow(divr, nmax, "rheo/surface:divr"); + memory->grow(rsurface, nmax, "rheo/surface:rsurface"); + memory->grow(nsurface, nmax, dim, "rheo/surface:nsurface"); + memory->grow(B, nmax, dim * dim, "rheo/surface:B"); + memory->grow(gradC, nmax, dim * dim, "rheo/surface:gradC"); + + nmax_store = nmax; +} diff --git a/src/RHEO/compute_rheo_surface.h b/src/RHEO/compute_rheo_surface.h new file mode 100644 index 0000000000..044ff470c6 --- /dev/null +++ b/src/RHEO/compute_rheo_surface.h @@ -0,0 +1,59 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(RHEO/SURFACE,ComputeRHEOSurface) +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_SURFACE_H +#define LMP_COMPUTE_RHEO_SURFACE_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputeRHEOSurface : public Compute { + public: + ComputeRHEOSurface(class LAMMPS *, int, char **); + ~ComputeRHEOSurface() override; + void init() override; + void init_list(int, class NeighList *) override; + void compute_peratom() override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + + double **nsurface, *rsurface, *divr; + class FixRHEO *fix_rheo; + + private: + int surface_style, nmax_store, threshold_z, threshold_splash, interface_flag; + int threshold_style, comm_stage; + + double cut, cutsq, *rho0, threshold_divr; + double **B, **gradC; + + class NeighList *list; + class ComputeRHEOKernel *compute_kernel; + class ComputeRHEOInterface *compute_interface; + + void grow_arrays(int); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/compute_rheo_vshift.cpp b/src/RHEO/compute_rheo_vshift.cpp new file mode 100644 index 0000000000..c06ef533ac --- /dev/null +++ b/src/RHEO/compute_rheo_vshift.cpp @@ -0,0 +1,321 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU), Eric Palermo (CMU) +----------------------------------------------------------------------- */ + +#include "compute_rheo_vshift.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_interface.h" +#include "compute_rheo_kernel.h" +#include "compute_rheo_surface.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "memory.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" + +#include "update.h" + +using namespace LAMMPS_NS; +using namespace RHEO_NS; + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOVShift::ComputeRHEOVShift(LAMMPS *lmp, int narg, char **arg) : + Compute(lmp, narg, arg), list(nullptr), vshift(nullptr), fix_rheo(nullptr), + compute_kernel(nullptr), compute_interface(nullptr), compute_surface(nullptr) +{ + if (narg != 3) error->all(FLERR,"Illegal compute RHEO/VShift command"); + + comm_reverse = 3; + surface_flag = 0; + + nmax_store = atom->nmax; + memory->create(vshift, nmax_store, 3, "rheo:vshift"); +} + +/* ---------------------------------------------------------------------- */ + +ComputeRHEOVShift::~ComputeRHEOVShift() +{ + memory->destroy(vshift); +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOVShift::init() +{ + neighbor->add_request(this, NeighConst::REQ_DEFAULT); + + surface_flag = fix_rheo->surface_flag; + interface_flag = fix_rheo->interface_flag; + + compute_kernel = fix_rheo->compute_kernel; + compute_interface = fix_rheo->compute_interface; + compute_surface = fix_rheo->compute_surface; + + rho0 = fix_rheo->rho0; + cut = fix_rheo->cut; + cutsq = cut * cut; + cutthird = cut / 3.0; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOVShift::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOVShift::compute_peratom() +{ + int i, j, a, b, ii, jj, jnum, itype, jtype; + int fluidi, fluidj; + double xtmp, ytmp, ztmp, rsq, r, rinv; + double w, wp, dr, w0, w4, vmag, prefactor; + double imass, jmass, voli, volj, rhoi, rhoj; + double dx[3], vi[3], vj[3]; + int dim = domain->dimension; + + int *jlist; + int inum, *ilist, *numneigh, **firstneigh; + + int *type = atom->type; + int *status = atom->rheo_status; + int *mask = atom->mask; + double **x = atom->x; + double **v = atom->v; + double *rho = atom->rho; + double *mass = atom->mass; + + int nlocal = atom->nlocal; + int nall = nlocal + atom->nghost; + int newton_pair = force->newton_pair; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + if (nmax_store < atom->nmax) { + memory->grow(vshift, atom->nmax, 3, "rheo:vshift"); + nmax_store = atom->nmax; + } + + for (i = 0; i < nall; i++) + for (a = 0; a < dim; a++) + vshift[i][a] = 0.0; + + for (a = 0; a < 3; a++) { + vi[a] = 0.0; + vj[a] = 0.0; + } + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + imass = mass[itype]; + fluidi = !(status[i] & PHASECHECK); + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + fluidj = !(status[j] & PHASECHECK); + if ((!fluidi) && (!fluidj)) continue; + + // Will skip shifting in FixRHEO initial integrate, but also skip here to save time + if ((status[i] & STATUS_NO_SHIFT) && (status[j] & STATUS_NO_SHIFT)) continue; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + rsq = dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]; + + if (rsq < cutsq) { + jtype = type[j]; + jmass = mass[jtype]; + + r = sqrt(rsq); + rinv = 1 / r; + + for (a = 0; a < dim; a++) { + vi[a] = v[i][a]; + vj[a] = v[j][a]; + } + + rhoi = rho[i]; + rhoj = rho[j]; + + // Add corrections for walls + if (interface_flag) { + if (fluidi && (!fluidj)) { + compute_interface->correct_v(vj, vi, j, i); + rhoj = compute_interface->correct_rho(j, i); + } else if ((!fluidi) && fluidj) { + compute_interface->correct_v(vi, vj, i, j); + rhoi = compute_interface->correct_rho(i, j); + } else if ((!fluidi) && (!fluidj)) { + rhoi = rho0[itype]; + rhoj = rho0[jtype]; + } + } + + voli = imass / rhoi; + volj = jmass / rhoj; + + wp = compute_kernel->calc_dw(i, j, dx[0], dx[1], dx[2], r); + w = compute_kernel->calc_w(i, j, dx[0], dx[1], dx[2], r); + w0 = compute_kernel->calc_w(i, j, 0, 0, 0, cutthird); // dx, dy, dz irrelevant + w4 = w * w * w * w / (w0 * w0 * w0 * w0); + dr = -2 * cutthird * (1 + 0.2 * w4) * wp * rinv; + + if ((mask[i] & groupbit) && fluidi) { + vmag = sqrt(vi[0] * vi[0] + vi[1] * vi[1] + vi[2] * vi[2]); + prefactor = vmag * volj * dr; + + vshift[i][0] += prefactor * dx[0]; + vshift[i][1] += prefactor * dx[1]; + vshift[i][2] += prefactor * dx[2]; + } + + if (newton_pair || j < nlocal) { + if ((mask[j] & groupbit) && fluidj) { + vmag = sqrt(vj[0] * vj[0] + vj[1] * vj[1] + vj[2] * vj[2]); + prefactor = vmag * voli * dr; + + vshift[j][0] -= prefactor * dx[0]; + vshift[j][1] -= prefactor * dx[1]; + vshift[j][2] -= prefactor * dx[2]; + } + } + } + } + } + + if (newton_pair) comm->reverse_comm(this); +} + + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOVShift::correct_surfaces() +{ + if (!surface_flag) return; + + int i, a, b; + + int *status = atom->rheo_status; + int *mask = atom->mask; + double **nsurface = compute_surface->nsurface; + + int nlocal = atom->nlocal; + int dim = domain->dimension; + + double nx, ny, nz, vx, vy, vz, dot; + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + + if (status[i] & PHASECHECK) continue; + + //if ((status[i] & STATUS_SURFACE) || (status[i] & STATUS_LAYER)) { + if (status[i] & STATUS_SURFACE) { + nx = nsurface[i][0]; + ny = nsurface[i][1]; + vx = vshift[i][0]; + vy = vshift[i][1]; + + dot = nx * vx + ny * vy; + if (dim == 3) { + nz = nsurface[i][2]; + vz = vshift[i][2]; + dot += nz * vz; + } + + // Allowing shifting into the bulk + if (dot < 0.0) continue; + + vshift[i][0] = (1 - nx * nx) * vx - nx * ny * vy; + vshift[i][1] = (1 - ny * ny) * vy - nx * ny * vx; + if (dim == 3) { + vshift[i][0] -= nx * nz * vz; + vshift[i][1] -= ny * nz * vz; + vshift[i][2] = (1 - nz * nz) * vz - nz * ny * vy - nx * nz * vx; + } else { + vshift[i][2] = 0.0; + } + } else if (status[i] & STATUS_SPLASH) { + vshift[i][0] = 0.0; + vshift[i][1] = 0.0; + vshift[i][2] = 0.0; + } + } + } +} + +/* ---------------------------------------------------------------------- */ + +int ComputeRHEOVShift::pack_reverse_comm(int n, int first, double *buf) +{ + int i,m,last; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + buf[m++] = vshift[i][0]; + buf[m++] = vshift[i][1]; + buf[m++] = vshift[i][2]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void ComputeRHEOVShift::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i,j,m; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + vshift[j][0] += buf[m++]; + vshift[j][1] += buf[m++]; + vshift[j][2] += buf[m++]; + } +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based array +------------------------------------------------------------------------- */ + +double ComputeRHEOVShift::memory_usage() +{ + double bytes = 3 * nmax_store * sizeof(double); + return bytes; +} diff --git a/src/RHEO/compute_rheo_vshift.h b/src/RHEO/compute_rheo_vshift.h new file mode 100644 index 0000000000..485c6525f3 --- /dev/null +++ b/src/RHEO/compute_rheo_vshift.h @@ -0,0 +1,57 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS +// clang-format off +ComputeStyle(RHEO/VSHIFT,ComputeRHEOVShift) +// clang-format on +#else + +#ifndef LMP_COMPUTE_RHEO_VSHIFT_H +#define LMP_COMPUTE_RHEO_VSHIFT_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputeRHEOVShift : public Compute { + public: + ComputeRHEOVShift(class LAMMPS *, int, char **); + ~ComputeRHEOVShift() override; + void init() override; + void init_list(int, class NeighList *) override; + void compute_peratom() override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + double memory_usage() override; + void correct_surfaces(); + double **vshift; + + class FixRHEO *fix_rheo; + + private: + int nmax_store; + double dtv, cut, cutsq, cutthird; + int surface_flag, interface_flag; + double *rho0; + + class NeighList *list; + class ComputeRHEOInterface *compute_interface; + class ComputeRHEOKernel *compute_kernel; + class ComputeRHEOSurface *compute_surface; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/fix_rheo.cpp b/src/RHEO/fix_rheo.cpp new file mode 100644 index 0000000000..f70b9e121f --- /dev/null +++ b/src/RHEO/fix_rheo.cpp @@ -0,0 +1,515 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU), Eric Palermo (CMU) +----------------------------------------------------------------------- */ + +#include "fix_rheo.h" + +#include "atom.h" +#include "citeme.h" +#include "compute_rheo_grad.h" +#include "compute_rheo_interface.h" +#include "compute_rheo_surface.h" +#include "compute_rheo_kernel.h" +#include "compute_rheo_rho_sum.h" +#include "compute_rheo_vshift.h" +#include "domain.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "modify.h" +#include "update.h" +#include "utils.h" + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace FixConst; + +static const char cite_rheo[] = + "@article{PalermoInPrep,\n" + " journal = {in prep},\n" + " title = {RHEO: A Hybrid Mesh-Free Model Framework for Dynamic Multi-Phase Flows},\n" + " year = {2024},\n" + " author = {Eric T. Palermo and Ki T. Wolf and Joel T. Clemmer and Thomas C. O'Connor},\n" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +FixRHEO::FixRHEO(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), compute_grad(nullptr), compute_kernel(nullptr), compute_surface(nullptr), + compute_interface(nullptr), compute_rhosum(nullptr), compute_vshift(nullptr), rho0(nullptr), csq(nullptr) +{ + time_integrate = 1; + + viscosity_fix_defined = 0; + pressure_fix_defined = 0; + thermal_fix_defined = 0; + oxidation_fix_defined = 0; + + thermal_flag = 0; + rhosum_flag = 0; + shift_flag = 0; + interface_flag = 0; + surface_flag = 0; + oxidation_flag = 0; + self_mass_flag = 0; + + int i; + int n = atom->ntypes; + memory->create(rho0, n + 1, "rheo:rho0"); + memory->create(csq, n + 1, "rheo:csq"); + for (i = 1; i <= n; i++) { + rho0[i] = 1.0; + csq[i] = 1.0; + } + + if (igroup != 0) + error->all(FLERR, "fix rheo command requires group all"); + + if (atom->pressure_flag != 1) + error->all(FLERR, "fix rheo command requires atom_style with pressure"); + if (atom->rho_flag != 1) + error->all(FLERR, "fix rheo command requires atom_style with density"); + if (atom->viscosity_flag != 1) + error->all(FLERR, "fix rheo command requires atom_style with viscosity"); + if (atom->rheo_status_flag != 1) + error->all(FLERR, "fix rheo command requires atom_style with status"); + + if (narg < 5) + utils::missing_cmd_args(FLERR, "fix rheo", error); + + cut = utils::numeric(FLERR, arg[3], false, lmp); + if (strcmp(arg[4], "quintic") == 0) { + kernel_style = QUINTIC; + } else if (strcmp(arg[4], "wendland/c4") == 0) { + kernel_style = WENDLANDC4; + } else if (strcmp(arg[4], "RK0") == 0) { + kernel_style = RK0; + } else if (strcmp(arg[4], "RK1") == 0) { + kernel_style = RK1; + } else if (strcmp(arg[4], "RK2") == 0) { + kernel_style = RK2; + } else error->all(FLERR, "Unknown kernel style {} in fix rheo", arg[4]); + zmin_kernel = utils::numeric(FLERR, arg[5], false, lmp); + + int iarg = 6; + while (iarg < narg){ + if (strcmp(arg[iarg], "shift") == 0) { + shift_flag = 1; + } else if (strcmp(arg[iarg], "thermal") == 0) { + thermal_flag = 1; + } else if (strcmp(arg[iarg], "surface/detection") == 0) { + surface_flag = 1; + if(iarg + 3 >= narg) utils::missing_cmd_args(FLERR, "fix rheo surface/detection", error); + if (strcmp(arg[iarg + 1], "coordination") == 0) { + surface_style = COORDINATION; + zmin_surface = utils::inumeric(FLERR, arg[iarg + 2], false, lmp); + zmin_splash = utils::inumeric(FLERR, arg[iarg + 3], false, lmp); + } else if (strcmp(arg[iarg + 1], "divergence") == 0) { + surface_style = DIVR; + divr_surface = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + zmin_splash = utils::inumeric(FLERR, arg[iarg + 3], false, lmp); + } else { + error->all(FLERR, "Illegal surface/detection option in fix rheo, {}", arg[iarg + 1]); + } + + iarg += 3; + } else if (strcmp(arg[iarg], "interface/reconstruct") == 0) { + interface_flag = 1; + } else if (strcmp(arg[iarg], "rho/sum") == 0) { + rhosum_flag = 1; + } else if (strcmp(arg[iarg], "self/mass") == 0) { + self_mass_flag = 1; + } else if (strcmp(arg[iarg], "density") == 0) { + if (iarg + n >= narg) utils::missing_cmd_args(FLERR, "fix rheo density", error); + for (i = 1; i <= n; i++) + rho0[i] = utils::numeric(FLERR, arg[iarg + i], false, lmp); + iarg += n; + } else if (strcmp(arg[iarg], "speed/sound") == 0) { + if (iarg + n >= narg) utils::missing_cmd_args(FLERR, "fix rheo speed/sound", error); + for (i = 1; i <= n; i++) { + csq[i] = utils::numeric(FLERR, arg[iarg + i], false, lmp); + csq[i] *= csq[i]; + } + iarg += n; + } else { + error->all(FLERR, "Illegal fix rheo command: {}", arg[iarg]); + } + iarg += 1; + } + + if (self_mass_flag && (!rhosum_flag)) + error->all(FLERR, "Cannot use self/mass setting without rho/sum"); + + if (lmp->citeme) lmp->citeme->add(cite_rheo); +} + +/* ---------------------------------------------------------------------- */ + +FixRHEO::~FixRHEO() +{ + if (compute_kernel) modify->delete_compute("rheo_kernel"); + if (compute_grad) modify->delete_compute("rheo_grad"); + if (compute_interface) modify->delete_compute("rheo_interface"); + if (compute_surface) modify->delete_compute("rheo_surface"); + if (compute_rhosum) modify->delete_compute("rheo_rhosum"); + if (compute_vshift) modify->delete_compute("rheo_vshift"); + + memory->destroy(csq); + memory->destroy(rho0); +} + + +/* ---------------------------------------------------------------------- + Create necessary internal computes +------------------------------------------------------------------------- */ + +void FixRHEO::post_constructor() +{ + compute_kernel = dynamic_cast(modify->add_compute( + fmt::format("rheo_kernel all RHEO/KERNEL {}", kernel_style))); + compute_kernel->fix_rheo = this; + + std::string cmd = "rheo_grad all RHEO/GRAD velocity rho viscosity"; + if (thermal_flag) cmd += " energy"; + compute_grad = dynamic_cast(modify->add_compute(cmd)); + compute_grad->fix_rheo = this; + + if (rhosum_flag) { + compute_rhosum = dynamic_cast(modify->add_compute( + fmt::format("rheo_rhosum all RHEO/RHO/SUM {}", self_mass_flag))); + compute_rhosum->fix_rheo = this; + } + + if (shift_flag) { + compute_vshift = dynamic_cast(modify->add_compute( + "rheo_vshift all RHEO/VSHIFT")); + compute_vshift->fix_rheo = this; + } + + if (interface_flag) { + compute_interface = dynamic_cast(modify->add_compute( + "rheo_interface all RHEO/INTERFACE")); + compute_interface->fix_rheo = this; + } + + if (surface_flag) { + compute_surface = dynamic_cast(modify->add_compute( + "rheo_surface all RHEO/SURFACE")); + compute_surface->fix_rheo = this; + } +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEO::setmask() +{ + int mask = 0; + mask |= INITIAL_INTEGRATE; + mask |= FINAL_INTEGRATE; + mask |= PRE_FORCE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::init() +{ + dtv = update->dt; + dtf = 0.5 * update->dt * force->ftm2v; + + if (modify->get_fix_by_style("^rheo$").size() > 1) + error->all(FLERR, "Can only specify one instance of fix rheo"); + + if (atom->rheo_status_flag != 1) + error->all(FLERR,"fix rheo command requires atom property status"); + if (atom->rho_flag != 1) + error->all(FLERR,"fix rheo command requires atom property rho"); + if (atom->pressure_flag != 1) + error->all(FLERR,"fix rheo command requires atom property pressure"); + if (atom->viscosity_flag != 1) + error->all(FLERR,"fix rheo command requires atom property viscosity"); + + if (thermal_flag) { + if (atom->esph_flag != 1) + error->all(FLERR,"fix rheo command requires atom property esph with thermal setting"); + if (atom->temperature_flag != 1) + error->all(FLERR,"fix rheo command requires atom property temperature with thermal setting"); + if (atom->heatflow_flag != 1) + error->all(FLERR,"fix rheo command requires atom property heatflow with thermal setting"); + if (atom->conductivity_flag != 1) + error->all(FLERR,"fix rheo command requires atom property conductivity with thermal setting"); + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::setup_pre_force(int /*vflag*/) +{ + // Check to confirm accessory fixes do not preceed FixRHEO + // Note: fixes set this flag in setup_pre_force() + if (viscosity_fix_defined || pressure_fix_defined || thermal_fix_defined || oxidation_fix_defined) + error->all(FLERR, "Fix RHEO must be defined before all other RHEO fixes"); + + // Calculate surfaces + if (surface_flag) { + compute_kernel->compute_coordination(); + compute_surface->compute_peratom(); + } + + pre_force(0); +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::setup(int /*vflag*/) +{ + // Confirm all accessory fixes are defined + // Note: fixes set this flag in setup_pre_force() + if (!viscosity_fix_defined) + error->all(FLERR, "Missing fix rheo/viscosity"); + + if (!pressure_fix_defined) + error->all(FLERR, "Missing fix rheo/pressure"); + + if(thermal_flag && !thermal_fix_defined) + error->all(FLERR, "Missing fix rheo/thermal"); + + // Reset to zero for future runs + thermal_fix_defined = 0; + viscosity_fix_defined = 0; + pressure_fix_defined = 0; + oxidation_fix_defined = 0; + + if (rhosum_flag) + compute_rhosum->compute_peratom(); +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::initial_integrate(int /*vflag*/) +{ + // update v, x and rho of atoms in group + int i, a, b; + double dtfm, divu; + + int *type = atom->type; + int *mask = atom->mask; + int *status = atom->rheo_status; + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + double *rho = atom->rho; + double *drho = atom->drho; + double *mass = atom->mass; + double *rmass = atom->rmass; + double **gradr = compute_grad->gradr; + double **gradv = compute_grad->gradv; + double **vshift; + if (shift_flag) + vshift = compute_vshift->vshift; + + int nlocal = atom->nlocal; + int rmass_flag = atom->rmass_flag; + int dim = domain->dimension; + + if (igroup == atom->firstgroup) + nlocal = atom->nfirst; + + //Density Half-step + for (i = 0; i < nlocal; i++) { + if (status[i] & STATUS_NO_INTEGRATION) continue; + + if (mask[i] & groupbit) { + if (rmass_flag) { + dtfm = dtf / rmass[i]; + } else { + dtfm = dtf / mass[type[i]]; + } + + v[i][0] += dtfm * f[i][0]; + v[i][1] += dtfm * f[i][1]; + v[i][2] += dtfm * f[i][2]; + } + } + + // Update gradients and interpolate solid properties + compute_grad->forward_fields(); // also forwards v and rho for chi + if (interface_flag) { + // Need to save, wiped in exchange + compute_interface->store_forces(); + compute_interface->compute_peratom(); + } + compute_grad->compute_peratom(); + + // Position half-step + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + for (a = 0; a < dim; a++) { + x[i][a] += dtv * v[i][a]; + } + } + } + + // Update density using div(u) + if (!rhosum_flag) { + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (status[i] & STATUS_NO_INTEGRATION) continue; + if (status[i] & PHASECHECK) continue; + + divu = 0; + for (a = 0; a < dim; a++) { + divu += gradv[i][a * (1 + dim)]; + } + rho[i] += dtf * (drho[i] - rho[i] * divu); + } + } + } + + // Shifting atoms + if (shift_flag) { + for (i = 0; i < nlocal; i++) { + + if (status[i] & STATUS_NO_SHIFT) continue; + if (status[i] & PHASECHECK) continue; + + if (mask[i] & groupbit) { + for (a = 0; a < dim; a++) { + x[i][a] += dtv * vshift[i][a]; + for (b = 0; b < dim; b++) { + v[i][a] += dtv * vshift[i][b] * gradv[i][a * dim + b]; + } + } + + if (!rhosum_flag) { + if (status[i] & PHASECHECK) continue; + for (a = 0; a < dim; a++) { + rho[i] += dtv * vshift[i][a] * gradr[i][a]; + } + } + } + } + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::pre_force(int /*vflag*/) +{ + compute_kernel->compute_coordination(); // Needed for rho sum + + if (rhosum_flag) + compute_rhosum->compute_peratom(); + + compute_kernel->compute_peratom(); + + if (interface_flag) { + // Note on first setup, have no forces for pressure to reference + compute_interface->compute_peratom(); + } + + // No need to forward v, rho, or T for compute_grad since already done + compute_grad->compute_peratom(); + compute_grad->forward_gradients(); + + if (shift_flag) + compute_vshift->compute_peratom(); + + // Remove temporary options + int *mask = atom->mask; + int *status = atom->rheo_status; + int nall = atom->nlocal + atom->nghost; + for (int i = 0; i < nall; i++) + if (mask[i] & groupbit) + status[i] &= OPTIONSMASK; + + // Calculate surfaces, update status + if (surface_flag) { + compute_surface->compute_peratom(); + if (shift_flag) + compute_vshift->correct_surfaces(); + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::final_integrate() +{ + int nlocal = atom->nlocal; + if (igroup == atom->firstgroup) + nlocal = atom->nfirst; + + double dtfm, divu; + int i, a; + + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + double **gradv = compute_grad->gradv; + double *rho = atom->rho; + double *drho = atom->drho; + double *mass = atom->mass; + double *rmass = atom->rmass; + int *type = atom->type; + int *mask = atom->mask; + int *status = atom->rheo_status; + + int rmass_flag = atom->rmass_flag; + int dim = domain->dimension; + + // Update velocity + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (status[i] & STATUS_NO_INTEGRATION) continue; + + if (rmass_flag) { + dtfm = dtf / rmass[i]; + } else { + dtfm = dtf / mass[type[i]]; + } + + for (a = 0; a < dim; a++) { + v[i][a] += dtfm * f[i][a]; + } + } + } + + // Update density using divu + if (!rhosum_flag) { + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (status[i] & STATUS_NO_INTEGRATION) continue; + if (status[i] & PHASECHECK) continue; + + divu = 0; + for (a = 0; a < dim; a++) { + divu += gradv[i][a * (1 + dim)]; + } + rho[i] += dtf * (drho[i] - rho[i] * divu); + } + } + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEO::reset_dt() +{ + dtv = update->dt; + dtf = 0.5 * update->dt * force->ftm2v; +} diff --git a/src/RHEO/fix_rheo.h b/src/RHEO/fix_rheo.h new file mode 100644 index 0000000000..8c62197fcd --- /dev/null +++ b/src/RHEO/fix_rheo.h @@ -0,0 +1,108 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(rheo,FixRHEO) +// clang-format on +#else + +#ifndef LMP_FIX_RHEO_H +#define LMP_FIX_RHEO_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixRHEO : public Fix { + public: + FixRHEO(class LAMMPS *, int, char **); + ~FixRHEO() override; + int setmask() override; + void post_constructor() override; + void init() override; + void setup_pre_force(int) override; + void setup(int) override; + void pre_force(int) override; + void initial_integrate(int) override; + void final_integrate() override; + void reset_dt() override; + + // Model parameters + double cut; + double *rho0, *csq; + int self_mass_flag; + int zmin_kernel, zmin_surface, zmin_splash; + int kernel_style, surface_style; + double divr_surface; + + // Accessory fixes/computes + int thermal_flag; + int rhosum_flag; + int shift_flag; + int interface_flag; + int surface_flag; + int oxidation_flag; + + int viscosity_fix_defined; + int pressure_fix_defined; + int thermal_fix_defined; + int oxidation_fix_defined; + + class ComputeRHEOGrad *compute_grad; + class ComputeRHEOKernel *compute_kernel; + class ComputeRHEOInterface *compute_interface; + class ComputeRHEOSurface *compute_surface; + class ComputeRHEORhoSum *compute_rhosum; + class ComputeRHEOVShift *compute_vshift; + + protected: + double dtv, dtf; +}; + +namespace RHEO_NS { + + enum {QUINTIC, WENDLANDC4, RK0, RK1, RK2}; + enum {COORDINATION, DIVR}; + + // Status variables + enum Status{ + // Phase status + STATUS_SOLID = 1 << 0, + // Gap for future phase: STATUS_ = 1 << 1, + + // Surface status + STATUS_BULK = 1 << 2, + STATUS_LAYER = 1 << 3, + STATUS_SURFACE = 1 << 4, + STATUS_SPLASH = 1 << 5, + + // Temporary status options - reset in preforce + STATUS_NO_SHIFT = 1 << 6, + STATUS_NO_INTEGRATION = 1 << 7, + STATUS_FREEZING = 1 << 8, + STATUS_MELTING = 1 << 9 + }; + + // Masks and their inverses + #define PHASEMASK 0xFFFFFFFC // 11111111111111111111111111111100 + #define PHASECHECK 0x00000003 // 00000000000000000000000000000011 + #define SURFACEMASK 0xFFFFFFC3 // 11111111111111111111111111000011 + #define SURFACECHECK 0x0000003C // 00000000000000000000000000111100 + #define OPTIONSMASK 0xFFFFFC3F // 11111111111111111111110000111111 + +} // namespace RHEO_NS +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/fix_rheo_oxidation.cpp b/src/RHEO/fix_rheo_oxidation.cpp new file mode 100644 index 0000000000..a51f2feb95 --- /dev/null +++ b/src/RHEO/fix_rheo_oxidation.cpp @@ -0,0 +1,296 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "fix_rheo_oxidation.h" + +#include "atom.h" +#include "atom_vec.h" +#include "citeme.h" +#include "comm.h" +#include "compute_rheo_surface.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "modify.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "update.h" + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace FixConst; +enum {NONE, CONSTANT}; + +static const char cite_rheo_oxide[] = + "@article{ApplMathModel.130.310,\n" + " title = {A hybrid smoothed-particle hydrodynamics model of oxide skins on molten aluminum},\n" + " journal = {Applied Mathematical Modelling},\n" + " volume = {130},\n" + " pages = {310-326},\n" + " year = {2024},\n" + " issn = {0307-904X},\n" + " doi = {https://doi.org/10.1016/j.apm.2024.02.027},\n" + " author = {Joel T. Clemmer and Flint Pierce and Thomas C. O'Connor and Thomas D. Nevins and Elizabeth M.C. Jones and Jeremy B. Lechman and John Tencer},\n" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +FixRHEOOxidation::FixRHEOOxidation(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), compute_surface(nullptr), fix_rheo(nullptr) +{ + if (narg != 6) error->all(FLERR,"Illegal fix command"); + + force_reneighbor = 1; + next_reneighbor = -1; + comm_forward = 3; + + cut = utils::numeric(FLERR, arg[3], false, lmp); + if (cut <= 0.0) error->all(FLERR, "Illegal bond cutoff {} in fix rheo/oxidation", cut); + + btype = utils::inumeric(FLERR, arg[4], false, lmp); + if (btype < 1 || btype > atom->nbondtypes) error->all(FLERR, "Illegal value {} for bond type in fix rheo/oxidation", btype); + + rsurf = utils::numeric(FLERR, arg[5], false, lmp); + if (rsurf <= 0.0) error->all(FLERR, "Illegal surface distance {} in fix rheo/oxidation", cut); + + cutsq = cut * cut; + + if (lmp->citeme) lmp->citeme->add(cite_rheo_oxide); +} + +/* ---------------------------------------------------------------------- */ + +FixRHEOOxidation::~FixRHEOOxidation() +{ +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOOxidation::setmask() +{ + int mask = 0; + mask |= POST_INTEGRATE; + mask |= PRE_FORCE; + mask |= POST_FORCE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::init() +{ + auto fixes = modify->get_fix_by_style("^rheo$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use fix rheo/oxidation"); + fix_rheo = dynamic_cast(fixes[0]); + + if (cut > fix_rheo->cut) + error->all(FLERR, "Bonding length exceeds kernel cutoff"); + + if (rsurf >= fix_rheo->cut) + error->all(FLERR, "Surface distance must be less than kernel cutoff"); + + if (!force->bond) error->all(FLERR, "Must define a bond style with fix rheo/oxidation"); + if (!atom->avec->bonds_allow) error->all(FLERR, "Fix rheo/oxidation requires atom bonds"); + + int tmp1, tmp2; + index_nb = atom->find_custom("shell_nbond", tmp1, tmp2); + if (index_nb == -1) + error->all(FLERR, "Must use bond style rheo/shell to use fix rheo/oxidation"); + nbond = atom->ivector[index_nb]; + + // need a half neighbor list + auto req = neighbor->add_request(this, NeighConst::REQ_FULL); + req->set_cutoff(cut); +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::setup_pre_force(int /*vflag*/) +{ + // Not strictly required that this fix be after FixRHEO, + // but enforce to be consistent with other RHEO fixes + fix_rheo->oxidation_fix_defined = 1; + + if (!fix_rheo->surface_flag) error->all(FLERR, + "fix rheo/oxidation requires surface calculation in fix rheo"); + compute_surface = fix_rheo->compute_surface; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::pre_force(int /*vflag*/) +{ +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::post_integrate() +{ + int i, j, n, ii, jj, inum, jnum, bflag, fluidi, fluidj; + int *ilist, *jlist, *numneigh, **firstneigh; + double delx, dely, delz, rsq; + tagint tagi, tagj; + + int nlocal = atom->nlocal; + int newton_bond = force->newton_bond; + + tagint *tag = atom->tag; + tagint **bond_atom = atom->bond_atom; + int **bond_type = atom->bond_type; + int *num_bond = atom->num_bond; + int *mask = atom->mask; + int *status = atom->rheo_status; + double *rsurface = compute_surface->rsurface; + double **x = atom->x; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // Forward positions (after inititial integrate, before comm) + // Note: surface designation lags one timestep, acceptable error + comm->forward_comm(this); + + int added_bonds = 0; + // loop over neighbors of my atoms + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + if (!(mask[i] & groupbit)) continue; + + // Exclude particles that aren't solid or surface + fluidi = !(status[i] & PHASECHECK); + if (fluidi && (rsurface[i] > rsurf)) continue; + + tagi = tag[i]; + + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + if (!(mask[j] & groupbit)) continue; + + fluidj = !(status[j] & PHASECHECK); + if (fluidj && (rsurface[j] > rsurf)) continue; + + // Skip solid-solid, leaves surface-surface or surface-solid + if ((!fluidi) && (!fluidj)) continue; + + tagj = tag[j]; + + // Ensure pair is always ordered to ensure numerical operations + // are identical to minimize the possibility that a bond straddling + // an mpi grid (newton off) isn't created on one proc but not the other + if (tagi < tagj) { + delx = x[i][0] - x[j][0]; + dely = x[i][1] - x[j][1]; + delz = x[i][2] - x[j][2]; + } else { + delx = x[j][0] - x[i][0]; + dely = x[j][1] - x[i][1]; + delz = x[j][2] - x[i][2]; + } + rsq = delx * delx + dely * dely + delz * delz; + if (rsq > cutsq) continue; + + // Check if already have an oxide bond + bflag = 0; + for (n = 0; n < num_bond[i]; n++) { + if (bond_type[i][n] == btype && bond_atom[i][n] == tagj) { + bflag = 1; + break; + } + } + if (bflag) continue; + + added_bonds += 1; + + // Add bonds to owned atoms + // If newton bond off, add to both, otherwise add to whichever has a smaller tag + + if (!newton_bond || (tagi < tagj)) { + if (num_bond[i] == atom->bond_per_atom) + error->one(FLERR,"New bond exceeded bonds per atom in fix rheo/oxidation for atom {}", tagi); + bond_type[i][num_bond[i]] = btype; + bond_atom[i][num_bond[i]] = tagj; + num_bond[i]++; + } + } + } + + int added_bonds_all; + MPI_Allreduce(&added_bonds, &added_bonds_all, 1, MPI_INT, MPI_SUM, world); + + if (added_bonds_all > 0) + next_reneighbor = update->ntimestep; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::post_force(int /*vflag*/) +{ + int *status = atom->rheo_status; + int *num_bond = atom->num_bond; + for (int i = 0; i < atom->nlocal; i++) + if (num_bond[i] != 0) + status[i] |= STATUS_NO_SHIFT; +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOOxidation::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i, j, k, m; + double **x = atom->x; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = x[j][0]; + buf[m++] = x[j][1]; + buf[m++] = x[j][2]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOOxidation::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double **x = atom->x; + m = 0; + last = first + n; + for (i = first; i < last; i++) { + x[i][0] = buf[m++]; + x[i][1] = buf[m++]; + x[i][2] = buf[m++]; + } +} diff --git a/src/RHEO/fix_rheo_oxidation.h b/src/RHEO/fix_rheo_oxidation.h new file mode 100644 index 0000000000..6dddea867a --- /dev/null +++ b/src/RHEO/fix_rheo_oxidation.h @@ -0,0 +1,57 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(rheo/oxidation,FixRHEOOxidation) +// clang-format on +#else + +#ifndef LMP_FIX_RHEO_OXIDATION_H +#define LMP_FIX_RHEO_OXIDATION_H + +#include "fix.h" + +#include + +namespace LAMMPS_NS { + +class FixRHEOOxidation : public Fix { + public: + FixRHEOOxidation(class LAMMPS *, int, char **); + ~FixRHEOOxidation() override; + int setmask() override; + void init() override; + void init_list(int, class NeighList *) override; + void setup_pre_force(int) override; + void post_integrate() override; + void pre_force(int) override; + void post_force(int) override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + int *nbond; + double rsurf, cut; + + private: + int btype, index_nb; + double cutsq; + + class NeighList *list; + class ComputeRHEOSurface *compute_surface; + class FixRHEO *fix_rheo; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/fix_rheo_pressure.cpp b/src/RHEO/fix_rheo_pressure.cpp new file mode 100644 index 0000000000..82adf52012 --- /dev/null +++ b/src/RHEO/fix_rheo_pressure.cpp @@ -0,0 +1,254 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU) +----------------------------------------------------------------------- */ + +#include "fix_rheo_pressure.h" + +#include "atom.h" +#include "comm.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "memory.h" +#include "modify.h" +#include "update.h" + +#include + +using namespace LAMMPS_NS; +using namespace FixConst; +enum {NONE, LINEAR, CUBIC, TAITWATER, TAITGENERAL}; + +static constexpr double SEVENTH = 1.0 / 7.0; + +/* ---------------------------------------------------------------------- */ + +FixRHEOPressure::FixRHEOPressure(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), fix_rheo(nullptr), rho0(nullptr), csq(nullptr), rho0inv(nullptr), csqinv(nullptr), c_cubic(nullptr), tpower(nullptr), pbackground(nullptr), pressure_style(nullptr) +{ + if (narg < 4) error->all(FLERR,"Illegal fix command"); + + comm_forward = 1; + + // Currently can only have one instance of fix rheo/pressure + if (igroup != 0) + error->all(FLERR,"fix rheo/pressure command requires group all"); + + int i, nlo, nhi; + int n = atom->ntypes; + memory->create(pressure_style, n + 1, "rheo:pressure_style"); + memory->create(c_cubic, n + 1, "rheo:c_cubic"); + memory->create(tpower, n + 1, "rheo:tpower"); + memory->create(pbackground, n + 1, "rheo:pbackground"); + for (i = 1; i <= n; i++) pressure_style[i] = NONE; + + int iarg = 3; + while (iarg < narg) { + utils::bounds(FLERR, arg[iarg], 1, n, nlo, nhi, error); + + if (iarg + 1 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/pressure", error); + + if (strcmp(arg[iarg + 1], "linear") == 0) { + for (i = nlo; i <= nhi; i++) + pressure_style[i] = LINEAR; + } else if (strcmp(arg[iarg + 1], "tait/water") == 0) { + for (i = nlo; i <= nhi; i++) + pressure_style[i] = TAITWATER; + } else if (strcmp(arg[iarg + 1], "tait/general") == 0) { + if (iarg + 3 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/pressure tait", error); + + double tpower_one = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + double pbackground_one = utils::numeric(FLERR, arg[iarg + 3], false, lmp); + iarg += 2; + + for (i = nlo; i <= nhi; i++) { + pressure_style[i] = TAITGENERAL; + tpower[i] = tpower_one; + pbackground[i] = pbackground_one; + } + } else if (strcmp(arg[iarg + 1], "cubic") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/pressure cubic", error); + + double c_cubic_one = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + iarg += 1; + + for (i = nlo; i <= nhi; i++) { + pressure_style[i] = CUBIC; + c_cubic[i] = c_cubic_one; + } + } else { + error->all(FLERR,"Illegal fix command, {}", arg[iarg]); + } + iarg += 2; + } + + for (i = 1; i <= n; i++) + if (pressure_style[i] == NONE) + error->all(FLERR,"Must specify pressure for atom type {} in fix/rheo/pressure", i); +} + +/* ---------------------------------------------------------------------- */ + +FixRHEOPressure::~FixRHEOPressure() +{ + memory->destroy(pressure_style); + memory->destroy(csqinv); + memory->destroy(rho0inv); + memory->destroy(c_cubic); + memory->destroy(tpower); + memory->destroy(pbackground); +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOPressure::setmask() +{ + int mask = 0; + mask |= PRE_FORCE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOPressure::init() +{ + auto fixes = modify->get_fix_by_style("^rheo$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use fix rheo/pressure"); + fix_rheo = dynamic_cast(fixes[0]); + + csq = fix_rheo->csq; + rho0 = fix_rheo->rho0; + + int n = atom->ntypes; + memory->create(csqinv, n + 1, "rheo:rho0inv"); + memory->create(rho0inv, n + 1, "rheo:rho0inv"); + for (int i = 0; i <= n; i++) { + csqinv[i] = 1.0 / csq[i]; + rho0inv[i] = 1.0 / rho0[i]; + } + + if (modify->get_fix_by_style("rheo/pressure").size() > 1) + error->all(FLERR, "Can only specify one instance of fix rheo/pressure"); +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOPressure::setup_pre_force(int /*vflag*/) +{ + fix_rheo->pressure_fix_defined = 1; + pre_force(0); +} + +/* ---------------------------------------------------------------------- + Update (and forward) pressure every timestep +------------------------------------------------------------------------- */ + +void FixRHEOPressure::pre_force(int /*vflag*/) +{ + int i; + double dr, rr3, rho_ratio; + + int *mask = atom->mask; + int *type = atom->type; + double *rho = atom->rho; + double *pressure = atom->pressure; + + int nlocal = atom->nlocal; + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + pressure[i] = calc_pressure(rho[i], type[i]); + + if (comm_forward) comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOPressure::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i,j,k,m; + double *pressure = atom->pressure; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = pressure[j]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOPressure::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *pressure = atom->pressure; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + pressure[i] = buf[m++]; + } +} + +/* ---------------------------------------------------------------------- */ + +double FixRHEOPressure::calc_pressure(double rho, int type) +{ + double p, dr, rr3, rho_ratio; + + if (pressure_style[type] == LINEAR) { + p = csq[type] * (rho - rho0[type]); + } else if (pressure_style[type] == CUBIC) { + dr = rho - rho0[type]; + p = csq[type] * (dr + c_cubic[type] * dr * dr * dr); + } else if (pressure_style[type] == TAITWATER) { + rho_ratio = rho * rho0inv[type]; + rr3 = rho_ratio * rho_ratio * rho_ratio; + p = csq[type] * rho0[type] * SEVENTH * (rr3 * rr3 * rho_ratio - 1.0); + } else if (pressure_style[type] == TAITGENERAL) { + rho_ratio = rho * rho0inv[type]; + p = csq[type] * rho0[type] * (pow(rho_ratio, tpower[type]) - 1.0) / tpower[type]; + p += pbackground[type]; + } + return p; +} + +/* ---------------------------------------------------------------------- */ + +double FixRHEOPressure::calc_rho(double p, int type) +{ + double rho, dr, rr3, rho_ratio; + + if (pressure_style[type] == LINEAR) { + rho = csqinv[type] * p + rho0[type]; + } else if (pressure_style[type] == CUBIC) { + error->one(FLERR, "Rho calculation from pressure not yet supported for cubic pressure equation"); + } else if (pressure_style[type] == TAITWATER) { + rho = pow(7.0 * p + csq[type] * rho0[type], SEVENTH); + rho *= pow(rho0[type], 6.0 * SEVENTH); + rho *= pow(csq[type], -SEVENTH); + } else if (pressure_style[type] == TAITGENERAL) { + p -= pbackground[type]; + rho = pow(tpower[type] * p + csq[type] * rho0[type], 1.0 / tpower[type]); + rho *= pow(rho0[type], 1.0 - 1.0 / tpower[type]); + rho *= pow(csq[type], -1.0 / tpower[type]); + } + return rho; +} diff --git a/src/RHEO/fix_rheo_pressure.h b/src/RHEO/fix_rheo_pressure.h new file mode 100644 index 0000000000..ca165b1ed5 --- /dev/null +++ b/src/RHEO/fix_rheo_pressure.h @@ -0,0 +1,50 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(rheo/pressure,FixRHEOPressure) +// clang-format on +#else + +#ifndef LMP_FIX_RHEO_PRESSURE_H +#define LMP_FIX_RHEO_PRESSURE_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixRHEOPressure : public Fix { + public: + FixRHEOPressure(class LAMMPS *, int, char **); + ~FixRHEOPressure() override; + int setmask() override; + void init() override; + void setup_pre_force(int) override; + void pre_force(int) override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + double calc_pressure(double, int); + double calc_rho(double, int); + + private: + double *c_cubic, *csq, *csqinv, *rho0, *rho0inv, *tpower, *pbackground; + int *pressure_style; + + class FixRHEO *fix_rheo; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/fix_rheo_thermal.cpp b/src/RHEO/fix_rheo_thermal.cpp new file mode 100644 index 0000000000..daa5b347a7 --- /dev/null +++ b/src/RHEO/fix_rheo_thermal.cpp @@ -0,0 +1,786 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "fix_rheo_thermal.h" + +#include "atom.h" +#include "atom_vec.h" +#include "citeme.h" +#include "comm.h" +#include "compute_rheo_grad.h" +#include "compute_rheo_vshift.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "fix_bond_history.h" +#include "fix_update_special_bonds.h" +#include "force.h" +#include "math_extra.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "pair.h" +#include "update.h" + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace FixConst; +enum {NONE, CONSTANT}; + +static const char cite_rheo_oxide[] = + "@article{ApplMathModel.130.310,\n" + " title = {A hybrid smoothed-particle hydrodynamics model of oxide skins on molten aluminum},\n" + " journal = {Applied Mathematical Modelling},\n" + " volume = {130},\n" + " pages = {310-326},\n" + " year = {2024},\n" + " issn = {0307-904X},\n" + " doi = {https://doi.org/10.1016/j.apm.2024.02.027},\n" + " author = {Joel T. Clemmer and Flint Pierce and Thomas C. O'Connor and Thomas D. Nevins and Elizabeth M.C. Jones and Jeremy B. Lechman and John Tencer},\n" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +FixRHEOThermal::FixRHEOThermal(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), fix_rheo(nullptr), compute_grad(nullptr), compute_vshift(nullptr), + Tc(nullptr), kappa(nullptr), cv(nullptr), L(nullptr), + Tc_style(nullptr), kappa_style(nullptr), cv_style(nullptr), L_style(nullptr), + fix_update_special_bonds(nullptr) +{ + if (narg < 4) error->all(FLERR,"Illegal fix command"); + + force_reneighbor = 1; + next_reneighbor = -1; + cut_bond = 0; + comm_forward = 0; + + // Currently can only have one instance of fix rheo/thermal + if (igroup != 0) + error->all(FLERR,"fix rheo/thermal command requires group all"); + + int i, nlo, nhi; + int n = atom->ntypes; + + memory->create(Tc_style, n + 1, "rheo:Tc_style"); + memory->create(kappa_style, n + 1, "rheo:kappa_style"); + memory->create(cv_style, n + 1, "rheo:cv_style"); + memory->create(L_style, n + 1, "rheo:L_style"); + + memory->create(Tc, n + 1, "rheo:Tc"); + memory->create(kappa, n + 1, "rheo:kappa"); + memory->create(cv, n + 1, "rheo:cv"); + memory->create(L, n + 1, "rheo:L"); + + for (i = 1; i <= n; i++) { + Tc_style[i] = NONE; + kappa_style[i] = NONE; + cv_style[i] = NONE; + L_style[i] = NONE; + } + + int iarg = 3; + while (iarg < narg) { + if (strcmp(arg[iarg],"conductivity") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal conductivity", error); + utils::bounds(FLERR, arg[iarg + 1], 1, n, nlo, nhi, error); + + // Conductivity arguments + if (strcmp(arg[iarg + 2], "constant") == 0) { + if (iarg + 3 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal conductivity constant", error); + + double kappa_one = utils::numeric(FLERR, arg[iarg + 3], false, lmp); + if (kappa_one < 0.0) error->all(FLERR, "The conductivity must be positive"); + iarg += 2; + + for (i = nlo; i <= nhi; i++) { + kappa_style[i] = CONSTANT; + kappa[i] = kappa_one; + } + } else { + error->all(FLERR,"Illegal fix command, {}", arg[iarg + 2]); + } + + iarg += 2; + } else if (strcmp(arg[iarg], "specific/heat") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal specific/heat", error); + utils::bounds(FLERR, arg[iarg + 1], 1, n, nlo, nhi, error); + + // Cv arguments + if (strcmp(arg[iarg + 2], "constant") == 0) { + if (iarg + 3 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal specific/heat constant", error); + + double cv_one = utils::numeric(FLERR, arg[iarg + 3], false, lmp); + if (cv_one < 0.0) error->all(FLERR, "The specific heat must be positive"); + iarg += 2; + + for (i = nlo; i <= nhi; i++) { + cv_style[i] = CONSTANT; + cv[i] = cv_one; + } + + } else { + error->all(FLERR,"Illegal fix command, {}", arg[iarg + 2]); + } + + iarg += 2; + } else if (strcmp(arg[iarg], "Tfreeze") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal Tfreeze", error); + utils::bounds(FLERR, arg[iarg + 1], 1, n, nlo, nhi, error); + + // T freeze arguments + if (strcmp(arg[iarg + 2], "constant") == 0) { + if (iarg + 3 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal Tfreeze constant", error); + + double Tc_one = utils::numeric(FLERR, arg[iarg + 3], false, lmp); + iarg += 2; + + for (i = nlo; i <= nhi; i++) { + Tc_style[i] = CONSTANT; + Tc[i] = Tc_one; + } + + } else { + error->all(FLERR, "Illegal fix command, {}", arg[iarg + 2]); + } + + iarg += 2; + } else if (strcmp(arg[iarg], "latent/heat") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal latent/heat", error); + utils::bounds(FLERR, arg[iarg + 1], 1, n, nlo, nhi, error); + + // Cv arguments + if (strcmp(arg[iarg + 2], "constant") == 0) { + if (iarg + 3 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal latent/heat constant", error); + + double L_one = utils::numeric(FLERR, arg[iarg + 3], false, lmp); + if (L_one < 0.0) error->all(FLERR, "The latent heat must be positive"); + iarg += 2; + + for (i = nlo; i <= nhi; i++) { + L_style[i] = CONSTANT; + L[i] = L_one; + } + + } else { + error->all(FLERR,"Illegal fix command, {}", arg[iarg + 2]); + } + + iarg += 2; + } else if (strcmp(arg[iarg], "react") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/thermal react", error); + cut_bond = utils::numeric(FLERR, arg[iarg + 1], false, lmp); + btype = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + comm_forward = 4; + if (cut_bond <= 0.0) error->all(FLERR, "Illegal max bond length must be greater than zero");\ + if (btype < 1 || btype > atom->nbondtypes) error->all(FLERR, "Illegal value for bond type"); + + cutsq_bond = cut_bond * cut_bond; + iarg += 3; + } else { + error->all(FLERR,"Illegal fix command, {}", arg[iarg]); + } + } + + + for (i = 1; i <= n; i++) { + if (cv_style[i] == NONE) + error->all(FLERR, "Must specify specific/heat for atom type {} in fix/rheo/thermal", i); + if (kappa_style[i] == NONE) + error->all(FLERR, "Must specify conductivity for atom type {} in fix/rheo/thermal", i); + if (Tc_style[i] == NONE && L_style[i] != NONE) + error->all(FLERR, "Must specify critical temperature for atom type {} to use latent heat in fix rheo/thermal", i); + } + + if (lmp->citeme) lmp->citeme->add(cite_rheo_oxide); +} + +/* ---------------------------------------------------------------------- */ + +FixRHEOThermal::~FixRHEOThermal() +{ + // Remove custom property if it exists + int tmp1, tmp2, index; + index = atom->find_custom("rheo_conductivity", tmp1, tmp2); + if (index != -1) atom->remove_custom(index, 1, 0); + + memory->destroy(cv_style); + memory->destroy(Tc_style); + memory->destroy(kappa_style); + memory->destroy(L_style); + memory->destroy(cv); + memory->destroy(Tc); + memory->destroy(kappa); + memory->destroy(L); +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOThermal::setmask() +{ + int mask = 0; + mask |= INITIAL_INTEGRATE; + mask |= POST_INTEGRATE; + mask |= POST_NEIGHBOR; + mask |= PRE_FORCE; + mask |= FINAL_INTEGRATE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::init() +{ + auto fixes = modify->get_fix_by_style("^rheo$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use fix rheo/viscosity"); + fix_rheo = dynamic_cast(fixes[0]); + cut_kernel = fix_rheo->cut; + + if (cut_bond > cut_kernel) + error->all(FLERR, "Bonding length exceeds kernel cutoff"); + + if (!fix_rheo->thermal_flag) + error->all(FLERR, "Need to define thermal setting in fix rheo"); + compute_grad = fix_rheo->compute_grad; + compute_vshift = fix_rheo->compute_vshift; + + dt = update->dt; + dth = 0.5 * update->dt; + + if (atom->esph_flag != 1) + error->all(FLERR, "fix rheo/thermal command requires atom property esph"); + if (atom->temperature_flag != 1) + error->all(FLERR, "fix rheo/thermal command requires atom property temperature"); + if (atom->heatflow_flag != 1) + error->all(FLERR, "fix rheo/thermal command requires atom property heatflow"); + if (atom->conductivity_flag != 1) + error->all(FLERR, "fix rheo/thermal command requires atom property conductivity"); + + if (cut_bond > 0.0) { + if (!force->bond) error->all(FLERR, "Must define a bond style to use reactive bond generation with fix rheo/thermal"); + if (!atom->avec->bonds_allow) error->all(FLERR, "Reactive bond generation in fix rheo/thermal requires atom bonds"); + + // all special weights must be 1.0 (no special neighbors) or there must be an instance of fix update/special/bonds + if (force->special_lj[0] != 1.0 || force->special_lj[1] != 1.0 || force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0) { + auto fixes = modify->get_fix_by_style("UPDATE_SPECIAL_BONDS"); + if (fixes.size() == 0) error->all(FLERR, "Without fix update/special/bonds, reactive bond generation in fix rheo/thermal requires special weights of 1.0"); + fix_update_special_bonds = dynamic_cast(fixes[0]); + } + + // must have newton off so both processors will search nlist to build bonds + if (force->newton_pair) + error->all(FLERR, "Need Newton off for reactive bond generation"); + + // need a half neighbor list, built only when particles freeze + auto req = neighbor->add_request(this, NeighConst::REQ_OCCASIONAL); + req->set_cutoff(cut_kernel); + + // find instances of bond history to delete/shift data + histories = modify->get_fix_by_style("BOND_HISTORY"); + n_histories = histories.size(); + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::init_list(int /*id*/, NeighList *ptr) +{ + list = ptr; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::setup_pre_force(int /*vflag*/) +{ + fix_rheo->thermal_fix_defined = 1; + + if (modify->get_fix_by_style("rheo/thermal").size() > 1) + error->all(FLERR, "More than one fix rheo/thermal defined"); + + post_neighbor(); + pre_force(0); +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::initial_integrate(int /*vflag*/) +{ + // update temperature from shifting + if (!fix_rheo->shift_flag) return; + int i, a; + + int *status = atom->rheo_status; + double *energy = atom->esph; + double **grade = compute_grad->grade; + double **vshift = compute_vshift->vshift; + + int nlocal = atom->nlocal; + int dim = domain->dimension; + + if (igroup == atom->firstgroup) + nlocal = atom->nfirst; + + for (i = 0; i < nlocal; i++) { + if (status[i] & STATUS_NO_SHIFT) continue; + for (a = 0; a < dim; a++) + energy[i] += dt * vshift[i][a] * grade[i][a]; + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::post_integrate() +{ + int i, itype; + double cvi, Tci, Ti, Li; + + int *status = atom->rheo_status; + double *energy = atom->esph; + double *temperature = atom->temperature; + double *heatflow = atom->heatflow; + int *type = atom->type; + + int n_melt = 0; + int n_freeze = 0; + + //Integrate energy and check status + for (i = 0; i < atom->nlocal; i++) { + if (status[i] & STATUS_NO_INTEGRATION) continue; + + itype = type[i]; + cvi = calc_cv(i, itype); + energy[i] += dth * heatflow[i]; + temperature[i] = energy[i] / cvi; + + if (Tc_style[itype] != NONE) { + Ti = temperature[i]; + Tci = calc_Tc(i, itype); + + if (L_style[itype] != NONE) { + Li = calc_L(i, itype); + if (Ti > Tci) Ti = MAX(Tci, (energy[i] - Li) / cvi); + temperature[i] = Ti; + } + + // Check phase change if Ti != Tci + + if (Ti > Tci) { + // If solid, melt + if (status[i] & STATUS_SOLID) { + status[i] &= PHASEMASK; + status[i] |= STATUS_MELTING; + n_melt += 1; + } + } + + if (Ti < Tci) { + // If fluid, freeze + if (!(status[i] & STATUS_SOLID)) { + status[i] &= PHASEMASK; + status[i] |= STATUS_SOLID; + status[i] |= STATUS_FREEZING; + n_freeze += 1; + } + } + } + } + + int n_melt_all, n_freeze_all; + MPI_Allreduce(&n_melt, &n_melt_all, 1, MPI_INT, MPI_SUM, world); + MPI_Allreduce(&n_freeze, &n_freeze_all, 1, MPI_INT, MPI_SUM, world); + + if (cut_bond > 0 && (n_melt_all || n_freeze_all)) { + + // If a particle freezes, check if it already has bonds of that type + // If so, assume it was inserted as a solid particle + // Note: inserted solid particle may still shift one timestep + int *num_bond = atom->num_bond; + int **bond_type = atom->bond_type; + for (i = 0; i < atom->nlocal; i++) { + if (status[i] & STATUS_FREEZING) { + for (int n = 0; n < num_bond[i]; n++) { + if (bond_type[i][n] == btype) { + status[i] &= ~STATUS_FREEZING; + break; + } + } + } + } + + // Forward status + positions (after inititial integrate, before comm) + comm->forward_comm(this); + + if (n_freeze_all) create_bonds(); + if (n_melt_all) break_bonds(); + + next_reneighbor = update->ntimestep; + } +} + +/* ---------------------------------------------------------------------- + Only need to update non-evolving conductivity styles after atoms exchange +------------------------------------------------------------------------- */ + +void FixRHEOThermal::post_neighbor() +{ + int i, itype; + int *type = atom->type; + double *conductivity = atom->conductivity; + int nlocal = atom->nlocal; + int nall = nlocal + atom->nghost; + + for (i = 0; i < nall; i++) { + itype = type[i]; + if (kappa_style[itype] == CONSTANT) + conductivity[i] = kappa[itype]; + } +} + +/* ---------------------------------------------------------------------- + Calculate temperature + In the future, update & forward evolving conductivity styles every timestep +------------------------------------------------------------------------- */ + +void FixRHEOThermal::pre_force(int /*vflag*/) +{ + int i, itype; + double cvi, Tci, Ti, Li; + + double *energy = atom->esph; + double *temperature = atom->temperature; + int *type = atom->type; + int *status = atom->rheo_status; + + int nlocal = atom->nlocal; + int nall = nlocal + atom->nghost; + + // Calculate temperature + for (i = 0; i < nall; i++) { + itype = type[i]; + cvi = calc_cv(i, itype); + temperature[i] = energy[i] / cvi; + + if (Tc_style[itype] != NONE) { + Ti = temperature[i]; + Tci = calc_Tc(i, itype); + + if (L_style[itype] != NONE) { + Li = calc_L(i, itype); + if (Ti > Tci) Ti = MAX(Tci, (energy[i] - Li) / cvi); + temperature[i] = Ti; + } + } + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::final_integrate() +{ + int *status = atom->rheo_status; + double *energy = atom->esph; + double *heatflow = atom->heatflow; + + //Integrate energy + for (int i = 0; i < atom->nlocal; i++) { + if (status[i] & STATUS_NO_INTEGRATION) continue; + energy[i] += dth * heatflow[i]; + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::reset_dt() +{ + dt = update->dt; + dth = 0.5 * update->dt; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::break_bonds() +{ + int m, n, nmax, i, j, melti, meltj; + + tagint *tag = atom->tag; + int *status = atom->rheo_status; + int **bond_type = atom->bond_type; + tagint **bond_atom = atom->bond_atom; + int *num_bond = atom->num_bond; + + int **bondlist = neighbor->bondlist; + int nbondlist = neighbor->nbondlist; + + int nlocal = atom->nlocal; + int nall = nlocal + atom->nghost; + + // Delete all bonds for local atoms that melt of a given type + for (int i = 0; i < nlocal; i++) { + melti = status[i] & STATUS_MELTING; + if (!melti) continue; + for (m = (num_bond[i] - 1); m >= 0; m--) { + if (bond_type[i][m] != btype) continue; + + j = atom->map(bond_atom[i][m]); + meltj = status[j] & STATUS_MELTING; + + nmax = num_bond[i] - 1; + if (m == nmax) { + if (n_histories > 0) + for (auto &ihistory: histories) + dynamic_cast(ihistory)->delete_history(i, m); + } else { + bond_type[i][m] = bond_type[i][nmax]; + bond_atom[i][m] = bond_atom[i][nmax]; + if (n_histories > 0) { + for (auto &ihistory: histories) { + auto fix_bond_history = dynamic_cast (ihistory); + fix_bond_history->shift_history(i, m, nmax); + fix_bond_history->delete_history(i, nmax); + } + } + } + bond_type[i][nmax] = 0; + num_bond[i]--; + + // Update special unless two owned atoms melt simultaneously then + // only update for atom with lower tag + if (fix_update_special_bonds) { + if ((i < nlocal) && (j < nlocal) && melti && meltj) { + if (tag[i] < tag[j]) { + fix_update_special_bonds->add_broken_bond(i, j); + } + } else { + fix_update_special_bonds->add_broken_bond(i, j); + } + } + } + } + + // Update bond list and break solid-melted bonds + for (n = 0; n < nbondlist; n++) { + + // skip bond if not correct type + if (bondlist[n][2] != btype) continue; + i = bondlist[n][0]; + j = bondlist[n][1]; + + melti = status[i] & STATUS_MELTING; + meltj = status[j] & STATUS_MELTING; + + if (!melti && !meltj) continue; + + bondlist[n][2] = 0; + + // Delete bonds for non-melted local atoms (shifting) + if (i < nlocal && !melti) { + for (m = 0; m < num_bond[i]; m++) { + if ((bond_atom[i][m] == tag[j]) && (bond_type[i][m] == btype)) { + nmax = num_bond[i] - 1; + bond_type[i][m] = bond_type[i][nmax]; + bond_atom[i][m] = bond_atom[i][nmax]; + if (n_histories > 0) + for (auto &ihistory: histories) { + auto fix_bond_history = dynamic_cast (ihistory); + fix_bond_history->shift_history(i, m, nmax); + fix_bond_history->delete_history(i, nmax); + } + bond_type[i][nmax] = 0; + num_bond[i]--; + break; + } + } + } + + if (j < nlocal && !meltj) { + for (m = 0; m < num_bond[j]; m++) { + if ((bond_atom[j][m] == tag[i]) && (bond_type[j][m] == btype)) { + nmax = num_bond[j] - 1; + bond_type[j][m] = bond_type[j][nmax]; + bond_atom[j][m] = bond_atom[j][nmax]; + if (n_histories > 0) + for (auto &ihistory: histories) { + auto fix_bond_history = dynamic_cast (ihistory); + fix_bond_history->shift_history(j, m, nmax); + fix_bond_history->delete_history(j, nmax); + } + bond_type[j][nmax] = 0; + num_bond[j]--; + break; + } + } + } + + // Unless both atoms melt simultaneously, need to remove special bond if the melted atom is a ghost + if (melti && meltj) continue; + if (fix_update_special_bonds) + if (((i >= nlocal) && melti) || ((j >= nlocal) && meltj)) + fix_update_special_bonds->add_broken_bond(i, j); + } +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::create_bonds() +{ + int i, j, ii, jj, inum, jnum; + int *ilist, *jlist, *numneigh, **firstneigh; + double delx, dely, delz, rsq; + + int nlocal = atom->nlocal; + int newton_bond = force->newton_bond; + + tagint *tag = atom->tag; + tagint **bond_atom = atom->bond_atom; + int *status = atom->rheo_status; + int **bond_type = atom->bond_type; + int *num_bond = atom->num_bond; + double **x = atom->x; + + neighbor->build_one(list, 1); + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // loop over neighbors of my atoms + // might be faster to do a full list and just act on the atom that freezes + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + if (!(status[i] & STATUS_SOLID)) continue; + + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + if (!(status[j] & STATUS_SOLID)) continue; + if (!(status[i] & STATUS_FREEZING) && !(status[j] & STATUS_FREEZING)) continue; + + // Ensure pair is always ordered to ensure numerical operations + // are identical to minimize the possibility that a bond straddling + // an mpi grid (newton off) isn't created on one proc but not the other + if (tag[i] < tag[j]) { + delx = x[i][0] - x[j][0]; + dely = x[i][1] - x[j][1]; + delz = x[i][2] - x[j][2]; + } else { + delx = x[j][0] - x[i][0]; + dely = x[j][1] - x[i][1]; + delz = x[j][2] - x[i][2]; + } + rsq = delx * delx + dely * dely + delz * delz; + if (rsq > cutsq_bond) continue; + + // Add bonds to owned atoms + // If newton bond off, add to both, otherwise add to whichever has a smaller tag + if ((i < nlocal) && (!newton_bond || (tag[i] < tag[j]))) { + if (num_bond[i] == atom->bond_per_atom) + error->one(FLERR,"New bond exceeded bonds per atom in fix rheo/thermal"); + bond_type[i][num_bond[i]] = btype; + bond_atom[i][num_bond[i]] = tag[j]; + num_bond[i]++; + } + + if ((j < nlocal) && (!newton_bond || (tag[j] < tag[i]))) { + if (num_bond[j] == atom->bond_per_atom) + error->one(FLERR,"New bond exceeded bonds per atom in fix rheo/thermal"); + bond_type[j][num_bond[j]] = btype; + bond_atom[j][num_bond[j]] = tag[i]; + num_bond[j]++; + } + + if (fix_update_special_bonds) fix_update_special_bonds->add_created_bond(i, j); + } + } +} + +/* ---------------------------------------------------------------------- */ + +double FixRHEOThermal::calc_cv(int i, int itype) +{ + if (cv_style[itype] == CONSTANT) { + return cv[itype]; + } + + return 0.0; +} + +/* ---------------------------------------------------------------------- */ + +double FixRHEOThermal::calc_Tc(int i, int itype) +{ + if (Tc_style[itype] == CONSTANT) { + return Tc[itype]; + } + + return 0.0; +} + +/* ---------------------------------------------------------------------- */ + +double FixRHEOThermal::calc_L(int i, int itype) +{ + if (L_style[itype] == CONSTANT) { + return L[itype]; + } + + return 0.0; +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOThermal::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i, j, k, m; + int *status = atom->rheo_status; + double **x = atom->x; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = ubuf(status[j]).d; + buf[m++] = x[j][0]; + buf[m++] = x[j][1]; + buf[m++] = x[j][2]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOThermal::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + int *status = atom->rheo_status; + double **x = atom->x; + m = 0; + last = first + n; + for (i = first; i < last; i++) { + status[i] = (int) ubuf(buf[m++]).i; + x[i][0] = buf[m++]; + x[i][1] = buf[m++]; + x[i][2] = buf[m++]; + } +} diff --git a/src/RHEO/fix_rheo_thermal.h b/src/RHEO/fix_rheo_thermal.h new file mode 100644 index 0000000000..264bbdbce3 --- /dev/null +++ b/src/RHEO/fix_rheo_thermal.h @@ -0,0 +1,73 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(rheo/thermal,FixRHEOThermal) +// clang-format on +#else + +#ifndef LMP_FIX_RHEO_THERMAL_H +#define LMP_FIX_RHEO_THERMAL_H + +#include "fix.h" + +#include + +namespace LAMMPS_NS { + +class FixRHEOThermal : public Fix { + public: + FixRHEOThermal(class LAMMPS *, int, char **); + ~FixRHEOThermal() override; + int setmask() override; + void init() override; + void init_list(int, class NeighList *) override; + void setup_pre_force(int) override; + void initial_integrate(int) override; + void post_integrate() override; + void post_neighbor() override; + void pre_force(int) override; + void final_integrate() override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + void reset_dt() override; + double calc_cv(int, int); + double calc_Tc(int, int); + double calc_L(int, int); + + private: + double *cv, *Tc, *kappa, *L; + double dt, dth; + double cut_kernel, cut_bond, cutsq_bond; + int *cv_style, *Tc_style, *kappa_style, *L_style; + int btype; + class NeighList *list; + + int n_histories; + std::vector histories; + + class FixRHEO *fix_rheo; + class ComputeRHEOGrad *compute_grad; + class ComputeRHEOVShift *compute_vshift; + class FixUpdateSpecialBonds *fix_update_special_bonds; + + void grow_array(int); + void break_bonds(); + void create_bonds(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/fix_rheo_viscosity.cpp b/src/RHEO/fix_rheo_viscosity.cpp new file mode 100644 index 0000000000..3ca7fd8d13 --- /dev/null +++ b/src/RHEO/fix_rheo_viscosity.cpp @@ -0,0 +1,251 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU) +----------------------------------------------------------------------- */ + +#include "fix_rheo_viscosity.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_grad.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "memory.h" +#include "modify.h" +#include "update.h" + +#include + +using namespace LAMMPS_NS; +using namespace FixConst; +enum {NONE, CONSTANT, POWER}; + +/* ---------------------------------------------------------------------- */ + +FixRHEOViscosity::FixRHEOViscosity(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), fix_rheo(nullptr), compute_grad(nullptr), eta(nullptr), + npow(nullptr), K(nullptr), gd0(nullptr), tau0(nullptr), viscosity_style(nullptr) +{ + if (narg < 4) error->all(FLERR, "Illegal fix command"); + + comm_forward = 0; + constant_flag = 0; + evolve_flag = 0; + + // Currently can only have one instance of fix rheo/viscosity + if (igroup != 0) + error->all(FLERR,"fix rheo/viscosity command requires group all"); + + int i, nlo, nhi; + int n = atom->ntypes; + memory->create(viscosity_style, n + 1, "rheo:viscosity_style"); + memory->create(eta, n + 1, "rheo:eta"); + memory->create(gd0, n + 1, "rheo:gd0"); + memory->create(K, n + 1, "rheo:K"); + memory->create(npow, n + 1, "rheo:npow"); + memory->create(tau0, n + 1, "rheo:tau0"); + for (i = 1; i <= n; i++) viscosity_style[i] = NONE; + + int iarg = 3; + while (iarg < narg) { + utils::bounds(FLERR, arg[iarg], 1, n, nlo, nhi, error); + + if (iarg + 1 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/viscosity", error); + + if (strcmp(arg[iarg + 1], "constant") == 0) { + if (iarg + 2 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/viscosity constant", error); + + constant_flag = 1; + double eta_one = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + if (eta_one < 0.0) error->all(FLERR, "The viscosity must be positive"); + iarg += 1; + + for (i = nlo; i <= nhi; i++) { + viscosity_style[i] = CONSTANT; + eta[i] = eta_one; + } + } else if (strcmp(arg[iarg + 1], "power") == 0) { + if (iarg + 5 >= narg) utils::missing_cmd_args(FLERR, "fix rheo/viscosity power", error); + + comm_forward = 1; + evolve_flag = 1; + double eta_one = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + double gd0_one = utils::numeric(FLERR, arg[iarg + 3], false, lmp); + double K_one = utils::numeric(FLERR, arg[iarg + 4], false, lmp); + double npow_one = utils::numeric(FLERR, arg[iarg + 5], false, lmp); + if (eta_one < 0.0) error->all(FLERR, "The viscosity must be positive"); + iarg += 4; + + for (i = nlo; i <= nhi; i++) { + viscosity_style[i] = POWER; + eta[i] = eta_one; + gd0[i] = gd0_one; + K[i] = K_one; + npow[i] = npow_one; + tau0[i] = eta[i] * gd0[i] - K[i] * pow(gd0[i], npow[i]); + } + } else { + error->all(FLERR, "Illegal fix command, {}", arg[iarg]); + } + iarg += 2; + } + + for (i = 1; i <= n; i++) + if (viscosity_style[i] == NONE) + error->all(FLERR,"Must specify viscosity for atom type {} in fix/rheo/viscosity", i); +} + +/* ---------------------------------------------------------------------- */ + +FixRHEOViscosity::~FixRHEOViscosity() +{ + memory->destroy(viscosity_style); + memory->destroy(eta); + memory->destroy(gd0); + memory->destroy(K); + memory->destroy(npow); + memory->destroy(tau0); +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOViscosity::setmask() +{ + int mask = 0; + mask |= POST_NEIGHBOR; + mask |= PRE_FORCE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOViscosity::init() +{ + auto fixes = modify->get_fix_by_style("^rheo$"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use fix rheo/viscosity"); + fix_rheo = dynamic_cast(fixes[0]); + + compute_grad = fix_rheo->compute_grad; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOViscosity::setup_pre_force(int /*vflag*/) +{ + fix_rheo->viscosity_fix_defined = 1; + + if (modify->get_fix_by_style("rheo/viscosity").size() > 1) + error->all(FLERR, "More than one fix rheo/viscosity defined"); + + post_neighbor(); + pre_force(0); +} + +/* ---------------------------------------------------------------------- + Only need to update non-evolving viscosity styles after atoms exchange +------------------------------------------------------------------------- */ + +void FixRHEOViscosity::post_neighbor() +{ + if (!constant_flag) return; + + int i, itype; + int *type = atom->type; + double *viscosity = atom->viscosity; + + int nall = atom->nlocal + atom->nghost; + + for (i = 0; i < nall; i++) { + itype = type[i]; + if (viscosity_style[itype]) + viscosity[i] = eta[itype]; + } +} + +/* ---------------------------------------------------------------------- + Update (and forward) evolving viscosity styles every timestep +------------------------------------------------------------------------- */ + +void FixRHEOViscosity::pre_force(int /*vflag*/) +{ + if (!evolve_flag) return; + + int i, itype, a, b; + double tmp, gdot; + + int *type = atom->type; + double *viscosity = atom->viscosity; + double **gradv = compute_grad->gradv; + + int nlocal = atom->nlocal; + int dim = domain->dimension; + + + for (i = 0; i < nlocal; i++) { + itype = type[i]; + if (viscosity_style[itype] == POWER) { + gdot = 0.0; + for (a = 0; a < dim; a++) { + for (b = a; b < dim; b++) { + tmp = gradv[i][a * dim + b] + gradv[i][b * dim + a]; + tmp = tmp * tmp; + if (a == b) tmp *= 0.5; + gdot += tmp; + } + } + gdot = sqrt(gdot); + if (gdot <= gd0[itype]) { + viscosity[i] = eta[itype]; + } else { + viscosity[i] = K[itype] * pow(gdot, npow[itype] - 1) + tau0[itype] / gdot; + } + } + } + + if (comm_forward) comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int FixRHEOViscosity::pack_forward_comm(int n, int *list, double *buf, + int /*pbc_flag*/, int * /*pbc*/) +{ + int i, j, k, m; + double *viscosity = atom->viscosity; + m = 0; + + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = viscosity[j]; + } + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixRHEOViscosity::unpack_forward_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double *viscosity = atom->viscosity; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + viscosity[i] = buf[m++]; + } +} diff --git a/src/RHEO/fix_rheo_viscosity.h b/src/RHEO/fix_rheo_viscosity.h new file mode 100644 index 0000000000..f81feb74b2 --- /dev/null +++ b/src/RHEO/fix_rheo_viscosity.h @@ -0,0 +1,50 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(rheo/viscosity,FixRHEOViscosity) +// clang-format on +#else + +#ifndef LMP_FIX_RHEO_VISCOSITY_H +#define LMP_FIX_RHEO_VISCOSITY_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixRHEOViscosity : public Fix { + public: + FixRHEOViscosity(class LAMMPS *, int, char **); + ~FixRHEOViscosity() override; + int setmask() override; + void init() override; + void setup_pre_force(int) override; + void post_neighbor() override; + void pre_force(int) override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; + + private: + double *eta, *npow, *K, *gd0, *tau0; + int *viscosity_style, constant_flag, evolve_flag; + + class FixRHEO *fix_rheo; + class ComputeRHEOGrad *compute_grad; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/pair_rheo.cpp b/src/RHEO/pair_rheo.cpp new file mode 100644 index 0000000000..9ebf884b6e --- /dev/null +++ b/src/RHEO/pair_rheo.cpp @@ -0,0 +1,549 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL), Thomas O'Connor (CMU) +----------------------------------------------------------------------- */ + +#include "pair_rheo.h" + +#include "atom.h" +#include "comm.h" +#include "compute_rheo_kernel.h" +#include "compute_rheo_grad.h" +#include "compute_rheo_interface.h" +#include "domain.h" +#include "error.h" +#include "fix_rheo.h" +#include "fix_rheo_pressure.h" +#include "force.h" +#include "math_extra.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "neigh_list.h" +#include "utils.h" + +#include + +using namespace LAMMPS_NS; +using namespace RHEO_NS; +using namespace MathExtra; + +static constexpr double EPSILON = 1e-2; + +/* ---------------------------------------------------------------------- */ + +PairRHEO::PairRHEO(LAMMPS *lmp) : + Pair(lmp), compute_kernel(nullptr), compute_grad(nullptr), compute_interface(nullptr), fix_rheo(nullptr), + fix_pressure(nullptr), rho0(nullptr), csq(nullptr), cs(nullptr) +{ + restartinfo = 0; + single_enable = 0; + + artificial_visc_flag = 0; + rho_damp_flag = 0; + thermal_flag = 0; + harmonic_means_flag = 0; + + comm_reverse = 3; +} + +/* ---------------------------------------------------------------------- */ + +PairRHEO::~PairRHEO() +{ + if (allocated) { + memory->destroy(setflag); + memory->destroy(cutsq); + } + + memory->destroy(cs); +} + +/* ---------------------------------------------------------------------- */ + +void PairRHEO::compute(int eflag, int vflag) +{ + int i, j, a, b, ii, jj, inum, jnum, itype, jtype; + int pair_force_flag, pair_rho_flag, pair_avisc_flag; + int fluidi, fluidj; + double xtmp, ytmp, ztmp, w, wp, Ti, Tj, dT, csq_ave, cs_ave; + double rhoi, rhoj, rho0i, rho0j, voli, volj, Pi, Pj, etai, etaj, kappai, kappaj, eta_ave, kappa_ave, dT_prefactor; + double mu, q, fp_prefactor, drho_damp, fmag, psi_ij, Fij; + double *dWij, *dWji, *dW1ij, *dW1ji; + double dx[3], du[3], dv[3], fv[3], dfp[3], fsolid[3], ft[3], vi[3], vj[3]; + + int *ilist, *jlist, *numneigh, **firstneigh; + double imass, jmass, rsq, r, rinv; + + int nlocal = atom->nlocal; + int newton_pair = force->newton_pair; + int dim = domain->dimension; + + ev_init(eflag, vflag); + + double **gradv = compute_grad->gradv; + double **gradr = compute_grad->gradr; + double **v = atom->v; + double **x = atom->x; + double **f = atom->f; + double *rho = atom->rho; + double *mass = atom->mass; + double *drho = atom->drho; + double *pressure = atom->pressure; + double *viscosity = atom->viscosity; + double *conductivity = atom->conductivity; + double *temperature = atom->temperature; + double *heatflow = atom->heatflow; + double *special_lj = force->special_lj; + int *type = atom->type; + int *status = atom->rheo_status; + tagint *tag = atom->tag; + + double **fp_store, *chi; + if (compute_interface) { + fp_store = compute_interface->fp_store; + chi = compute_interface->chi; + + for (i = 0; i < atom->nmax; i++) { + fp_store[i][0] = 0.0; + fp_store[i][1] = 0.0; + fp_store[i][2] = 0.0; + } + } + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + for (a = 0; a < 3; a++) { + vi[a] = 0.0; + vj[a] = 0.0; + du[a] = 0.0; + fv[a] = 0.0; + dfp[a] = 0.0; + fsolid[a] = 0.0; + ft[0] = 0.0; + } + + // loop over neighbors of my atoms + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + imass = mass[itype]; + etai = viscosity[i]; + fluidi = !(status[i] & PHASECHECK); + if (thermal_flag) { + kappai = conductivity[i]; + Ti = temperature[i]; + } + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + j &= NEIGHMASK; + + dx[0] = xtmp - x[j][0]; + dx[1] = ytmp - x[j][1]; + dx[2] = ztmp - x[j][2]; + rsq = lensq3(dx); + jtype = type[j]; + + if (rsq < cutksq) { + r = sqrt(rsq); + rinv = 1 / r; + + jmass = mass[jtype]; + etaj = viscosity[j]; + fluidj = !(status[j] & PHASECHECK); + if (thermal_flag) { + Tj = temperature[j]; + kappaj = conductivity[j]; + } + + cs_ave = 0.5 * (cs[itype] + cs[jtype]); + csq_ave = cs_ave * cs_ave; + + pair_rho_flag = 0; + pair_force_flag = 0; + pair_avisc_flag = 0; + if (fluidi || fluidj) { + pair_force_flag = 1; + if (!interface_flag) pair_avisc_flag = 1; + } + if (fluidi && fluidj) { + pair_rho_flag = 1; + pair_avisc_flag = 1; + } + + wp = compute_kernel->calc_dw(i, j, dx[0], dx[1], dx[2], r); + dWij = compute_kernel->dWij; + dWji = compute_kernel->dWji; + + for (a = 0; a < dim; a++) { + vi[a] = v[i][a]; + vj[a] = v[j][a]; + } + + // Add corrections for walls + rhoi = rho[i]; + rhoj = rho[j]; + rho0i = rho0[itype]; + rho0j = rho0[jtype]; + Pi = pressure[i]; + Pj = pressure[j]; + fmag = 0; + if (interface_flag) { + if (fluidi && (!fluidj)) { + compute_interface->correct_v(vj, vi, j, i); + rhoj = compute_interface->correct_rho(j, i); + Pj = fix_pressure->calc_pressure(rhoj, jtype); + + if ((chi[j] > 0.9) && (r < (cutk * 0.5))) + fmag = (chi[j] - 0.9) * (cutk * 0.5 - r) * rho0j * csq_ave * cutk * rinv; + + } else if ((!fluidi) && fluidj) { + compute_interface->correct_v(vi, vj, i, j); + rhoi = compute_interface->correct_rho(i, j); + Pi = fix_pressure->calc_pressure(rhoi, itype); + + if (chi[i] > 0.9 && r < (cutk * 0.5)) + fmag = (chi[i] - 0.9) * (cutk * 0.5 - r) * rho0i * csq_ave * cutk * rinv; + + } else if ((!fluidi) && (!fluidj)) { + rhoi = rho0i; + rhoj = rho0j; + } + } + + // Repel if close to inner solid particle + scale3(fmag, dx, fsolid); + + // Compute volume after reconstructing + voli = imass / rhoi; + volj = jmass / rhoj; + + // Thermal Evolution + if (thermal_flag) { + if (harmonic_means_flag) { + kappa_ave = 2.0 * kappai * kappaj / (kappai + kappaj); + } else { + kappa_ave = 0.5 * (kappai + kappaj); + } + dT_prefactor = 2.0 * kappa_ave * (Ti - Tj) * rinv * rinv * voli * volj * 2.0 / (rhoi + rhoj); + + dT = dot3(dx, dWij); + heatflow[i] += dT * dT_prefactor; + + if (newton_pair || j < nlocal) { + dT = dot3(dx, dWji); + heatflow[j] += dT * dT_prefactor; + } + } + + if (pair_force_flag) { + + //Hydrostatic pressure forces + fp_prefactor = voli * volj * (Pj + Pi); + sub3(vi, vj, dv); + + if (harmonic_means_flag) { + eta_ave = 2.0 * etai * etaj / (etai + etaj); + } else { + eta_ave = 0.5 * (etai + etaj); + } + + //Add artificial viscous pressure if required + if (artificial_visc_flag && pair_avisc_flag) { + //Interpolate velocities to midpoint and use this difference for artificial viscosity + copy3(dv, du); + for (a = 0; a < dim; a++) + for (b = 0; b < dim; b++) + du[a] -= 0.5 * (gradv[i][a * dim + b] + gradv[j][a * dim + b]) * dx[b]; + + mu = dot3(du, dx) * cutkinv3; + mu /= (rsq * cutkinv3 * cutkinv3 + EPSILON); + mu = MIN(0.0, mu); + q = av * (-2.0 * cs_ave * mu + mu * mu); + fp_prefactor += voli * volj * q * (rhoj + rhoi); + } + + // -Grad[P + Q] + scale3(-fp_prefactor, dWij, dfp); + + // Now compute viscous eta*Lap[v] terms + for (a = 0; a < dim; a++) { + fv[a] = 0.0; + for (b = 0; b < dim; b++) + fv[a] += dv[a] * dx[b] * dWij[b]; + fv[a] *= 2.0 * eta_ave * voli * volj * rinv * rinv; + } + + add3(fv, dfp, ft); + add3(fsolid, ft, ft); + + f[i][0] += ft[0]; + f[i][1] += ft[1]; + f[i][2] += ft[2]; + + // Note the virial's definition is hazy, e.g. viscous contributions will depend on rotation + if (evflag) + ev_tally_xyz(i, j, nlocal, newton_pair, 0.0, 0.0, ft[0], ft[1], ft[2], dx[0], dx[1], dx[2]); + + if (newton_pair || j < nlocal) { + for (a = 0; a < dim; a ++) { + fv[a] = 0.0; + for (b = 0; b < dim; b++) + fv[a] += (vi[a] - vj[a]) * dx[b] * dWji[b]; + fv[a] *= -2.0 * eta_ave * voli * volj * rinv * rinv; + // flip sign here b/c -= at accummulator + } + + scale3(fp_prefactor, dWji, dfp); + add3(fv, dfp, ft); + add3(fsolid, ft, ft); + + f[j][0] -= ft[0]; + f[j][1] -= ft[1]; + f[j][2] -= ft[2]; + + if (evflag) + ev_tally_xyz(i, j, nlocal, newton_pair, 0.0, 0.0, ft[0], ft[1], ft[2], -dx[0], -dx[1], -dx[2]); + } + + if (compute_interface) { + fp_store[i][0] += dfp[0]; + fp_store[i][1] += dfp[1]; + fp_store[i][2] += dfp[2]; + + if (newton_pair || j < nlocal) { + fp_store[j][0] -= dfp[0]; + fp_store[j][1] -= dfp[1]; + fp_store[j][2] -= dfp[2]; + } + } + } + + // Density damping + // conventional for low-order h + // interpolated for RK 1 & 2 (Antuono et al., Computers & Fluids 2021) + if (rho_damp_flag && pair_rho_flag) { + if (laplacian_order >= 1) { + psi_ij = rhoj - rhoi; + Fij = -rinv * rinv * dot3(dx, dWij); + for (a = 0; a < dim; a++) + psi_ij += 0.5 * (gradr[i][a] + gradr[j][a]) * dx[a]; + drho[i] += 2 * rho_damp * psi_ij * Fij * volj; + } else { + drho_damp = 2 * rho_damp * ((rhoj - rho0[jtype]) - (rhoi - rho0[itype])) * rinv * wp; + drho[i] -= drho_damp * volj; + } + + if (newton_pair || j < nlocal) { + if (laplacian_order >= 1) { + Fij = rinv * rinv * dot3(dx, dWji); + psi_ij *= -1; + drho[j] += 2 * rho_damp * psi_ij * Fij * voli; + } else { + drho[j] += drho_damp * voli; + } + } + } + } + } + } + + if (vflag_fdotr) virial_fdotr_compute(); + + if (compute_interface) { + if (newton_pair) comm->reverse_comm(this); + comm->forward_comm(this); + } +} + +/* ---------------------------------------------------------------------- + allocate all arrays + ------------------------------------------------------------------------- */ + +void PairRHEO::allocate() +{ + allocated = 1; + int n = atom->ntypes; + + memory->create(setflag, n + 1, n + 1, "pair:setflag"); + for (int i = 1; i <= n; i++) + for (int j = i; j <= n; j++) + setflag[i][j] = 0; + + memory->create(cutsq, n + 1, n + 1, "pair:cutsq"); +} + +/* ---------------------------------------------------------------------- + global settings + ------------------------------------------------------------------------- */ + +void PairRHEO::settings(int narg, char **arg) +{ + if (narg < 1) error->all(FLERR, "Illegal pair_style command"); + + cutk = utils::numeric(FLERR, arg[0], false, lmp); + + int iarg = 1; + while (iarg < narg) { + if (strcmp(arg[iarg], "rho/damp") == 0) { + if (iarg + 1 >= narg) utils::missing_cmd_args(FLERR, "pair rheo rho/damp", error); + rho_damp_flag = 1; + rho_damp = utils::numeric(FLERR, arg[iarg + 1], false, lmp); + iarg++; + } else if (strcmp(arg[iarg], "artificial/visc") == 0) { + if (iarg + 1 >= narg) utils::missing_cmd_args(FLERR, "pair rheo artificial/visc", error); + artificial_visc_flag = 1; + av = utils::numeric(FLERR, arg[iarg + 1], false, lmp); + iarg++; + } else if (strcmp(arg[iarg], "harmonic/means") == 0) { + harmonic_means_flag = 1; + } else error->all(FLERR, "Illegal pair_style command, {}", arg[iarg]); + iarg++; + } +} + +/* ---------------------------------------------------------------------- + set coeffs for one or more type pairs + ------------------------------------------------------------------------- */ + +void PairRHEO::coeff(int narg, char **arg) +{ + if (narg != 2) + error->all(FLERR, "Incorrect number of args for pair_style rheo coefficients"); + if (!allocated) + allocate(); + + int ilo, ihi, jlo, jhi; + utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error); + utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error); + + int count = 0; + for (int i = ilo; i <= ihi; i++) { + for (int j = 0; j <= atom->ntypes; j++) { + setflag[i][j] = 1; + count++; + } + } + + if (count == 0) + error->all(FLERR, "Incorrect args for pair rheo coefficients"); +} + +/* ---------------------------------------------------------------------- + setup specific to this pair style + ------------------------------------------------------------------------- */ + +void PairRHEO::setup() +{ + auto fixes = modify->get_fix_by_style("rheo"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo to use pair rheo"); + fix_rheo = dynamic_cast(fixes[0]); + + // Currently only allow one instance of fix rheo/pressure + fixes = modify->get_fix_by_style("rheo/pressure"); + if (fixes.size() == 0) error->all(FLERR, "Need to define fix rheo/pressure to use pair rheo"); + fix_pressure = dynamic_cast(fixes[0]); + + compute_kernel = fix_rheo->compute_kernel; + compute_grad = fix_rheo->compute_grad; + compute_interface = fix_rheo->compute_interface; + thermal_flag = fix_rheo->thermal_flag; + interface_flag = fix_rheo->interface_flag; + csq = fix_rheo->csq; + rho0 = fix_rheo->rho0; + + if (cutk != fix_rheo->cut) + error->all(FLERR, "Pair rheo cutoff {} does not agree with fix rheo cutoff {}", cutk, fix_rheo->cut); + + cutksq = cutk * cutk; + cutkinv = 1.0 / cutk; + cutkinv3 = cutkinv * 3.0; + laplacian_order = -1; + + int n = atom->ntypes; + memory->create(cs, n + 1, "rheo:cs"); + for (int i = 1; i <= n; i++) + cs[i] = sqrt(csq[i]); + + if (comm->ghost_velocity == 0) + error->all(FLERR, "Pair RHEO requires ghost atoms store velocity"); + + if (laplacian_order == -1) { + if (fix_rheo->kernel_style == RK2) + laplacian_order = 2; + else if (fix_rheo->kernel_style == RK1) + laplacian_order = 1; + else + laplacian_order = 0; + } +} + +/* ---------------------------------------------------------------------- + init for one type pair i,j and corresponding j,i + ------------------------------------------------------------------------- */ + +double PairRHEO::init_one(int i, int j) +{ + if (setflag[i][j] == 0) + error->all(FLERR, "All pair rheo coeffs are not set"); + + return cutk; +} + +/* ---------------------------------------------------------------------- */ + +int PairRHEO::pack_reverse_comm(int n, int first, double *buf) +{ + int i, k, m, last; + double **fp_store = compute_interface->fp_store; + + m = 0; + last = first + n; + for (i = first; i < last; i++) { + buf[m++] = fp_store[i][0]; + buf[m++] = fp_store[i][1]; + buf[m++] = fp_store[i][2]; + } + + return m; +} + +/* ---------------------------------------------------------------------- */ + +void PairRHEO::unpack_reverse_comm(int n, int *list, double *buf) +{ + int i, j, k, m; + double **fp_store = compute_interface->fp_store; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + fp_store[j][0] += buf[m++]; + fp_store[j][1] += buf[m++]; + fp_store[j][2] += buf[m++]; + } +} diff --git a/src/RHEO/pair_rheo.h b/src/RHEO/pair_rheo.h new file mode 100644 index 0000000000..eba3a70eea --- /dev/null +++ b/src/RHEO/pair_rheo.h @@ -0,0 +1,63 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef PAIR_CLASS +// clang-format off +PairStyle(rheo,PairRHEO) +// clang-format on +#else + +#ifndef LMP_PAIR_RHEO_H +#define LMP_PAIR_RHEO_H + +#include "pair.h" + +namespace LAMMPS_NS { + +class PairRHEO : public Pair { + public: + PairRHEO(class LAMMPS *); + ~PairRHEO() override; + void compute(int, int) override; + void settings(int, char **) override; + void coeff(int, char **) override; + void setup() override; + double init_one(int, int) override; + int pack_reverse_comm(int, int, double *) override; + void unpack_reverse_comm(int, int *, double *) override; + + protected: + double cutk, *csq, *rho0; // From fix RHEO + double *cs, cutksq, cutkinv, cutkinv3, av, rho_damp; + + int laplacian_order; + int artificial_visc_flag; + int rho_damp_flag; + int thermal_flag; + int interface_flag; + + int harmonic_means_flag; + + void allocate(); + + class ComputeRHEOKernel *compute_kernel; + class ComputeRHEOGrad *compute_grad; + class ComputeRHEOInterface *compute_interface; + class FixRHEO *fix_rheo; + class FixRHEOPressure *fix_pressure; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/RHEO/pair_rheo_solid.cpp b/src/RHEO/pair_rheo_solid.cpp new file mode 100644 index 0000000000..070cabaf86 --- /dev/null +++ b/src/RHEO/pair_rheo_solid.cpp @@ -0,0 +1,359 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: + Joel Clemmer (SNL) +----------------------------------------------------------------------- */ + +#include "pair_rheo_solid.h" + +#include "atom.h" +#include "comm.h" +#include "error.h" +#include "fix_rheo.h" +#include "force.h" +#include "memory.h" +#include "neigh_list.h" +#include "neighbor.h" + +#include + +using namespace LAMMPS_NS; +using namespace RHEO_NS; + +/* ---------------------------------------------------------------------- */ + +PairRHEOSolid::PairRHEOSolid(LAMMPS *_lmp) : Pair(_lmp) +{ + writedata = 1; +} + +/* ---------------------------------------------------------------------- */ + +PairRHEOSolid::~PairRHEOSolid() +{ + if (allocated) { + memory->destroy(setflag); + memory->destroy(cutsq); + + memory->destroy(k); + memory->destroy(cut); + memory->destroy(gamma); + } +} + +/* ---------------------------------------------------------------------- */ + +void PairRHEOSolid::compute(int eflag, int vflag) +{ + int i, j, ii, jj, inum, jnum, itype, jtype; + double xtmp, ytmp, ztmp, delx, dely, delz, evdwl, fpair; + double r, rsq, rinv, factor_lj; + int *ilist, *jlist, *numneigh, **firstneigh; + double vxtmp, vytmp, vztmp, delvx, delvy, delvz, dot, smooth; + + evdwl = 0.0; + if (eflag || vflag) + ev_setup(eflag, vflag); + else + evflag = vflag_fdotr = 0; + + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + int *type = atom->type; + int *status = atom->rheo_status; + int nlocal = atom->nlocal; + int newton_pair = force->newton_pair; + double *special_lj = force->special_lj; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // loop over neighbors of my atoms + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + if (!(status[i] & STATUS_SOLID)) continue; + + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + vxtmp = v[i][0]; + vytmp = v[i][1]; + vztmp = v[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + factor_lj = special_lj[sbmask(j)]; + if (factor_lj == 0) continue; + j &= NEIGHMASK; + + if (!(status[j] & STATUS_SOLID)) continue; + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + jtype = type[j]; + + if (rsq < cutsq[itype][jtype]) { + r = sqrt(rsq); + + rinv = 1.0 / r; + fpair = k[itype][jtype] * (cut[itype][jtype] - r); + + smooth = rsq / cutsq[itype][jtype]; + smooth *= smooth; + smooth *= smooth; + smooth = 1.0 - smooth; + delvx = vxtmp - v[j][0]; + delvy = vytmp - v[j][1]; + delvz = vztmp - v[j][2]; + dot = delx * delvx + dely * delvy + delz * delvz; + fpair -= gamma[itype][jtype] * dot * smooth * rinv; + + fpair *= factor_lj * rinv; + if (eflag) evdwl = 0.0; + + f[i][0] += delx * fpair; + f[i][1] += dely * fpair; + f[i][2] += delz * fpair; + + if (newton_pair || j < nlocal) { + f[j][0] -= delx * fpair; + f[j][1] -= dely * fpair; + f[j][2] -= delz * fpair; + } + + if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0, fpair, delx, dely, delz); + } + } + } + + if (vflag_fdotr) virial_fdotr_compute(); +} + +/* ---------------------------------------------------------------------- + allocate all arrays +------------------------------------------------------------------------- */ + +void PairRHEOSolid::allocate() +{ + allocated = 1; + const int np1 = atom->ntypes + 1; + + memory->create(setflag, np1, np1, "pair:setflag"); + for (int i = 1; i < np1; i++) + for (int j = i; j < np1; j++) setflag[i][j] = 0; + + memory->create(cutsq, np1, np1, "pair:cutsq"); + + memory->create(k, np1, np1, "pair:k"); + memory->create(cut, np1, np1, "pair:cut"); + memory->create(gamma, np1, np1, "pair:gamma"); +} + +/* ---------------------------------------------------------------------- + global settings +------------------------------------------------------------------------- */ + +void PairRHEOSolid::settings(int narg, char ** /*arg*/) +{ + if (narg != 0) error->all(FLERR, "Illegal pair_style command"); +} + +/* ---------------------------------------------------------------------- + set coeffs for one or more type pairs +------------------------------------------------------------------------- */ + +void PairRHEOSolid::coeff(int narg, char **arg) +{ + if (narg != 5) error->all(FLERR, "Incorrect args for pair coefficients"); + if (!allocated) allocate(); + + int ilo, ihi, jlo, jhi; + utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error); + utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error); + + double k_one = utils::numeric(FLERR, arg[2], false, lmp); + double cut_one = utils::numeric(FLERR, arg[3], false, lmp); + double gamma_one = utils::numeric(FLERR, arg[4], false, lmp); + + if (cut_one <= 0.0) error->all(FLERR, "Incorrect args for pair coefficients"); + + int count = 0; + for (int i = ilo; i <= ihi; i++) { + for (int j = MAX(jlo, i); j <= jhi; j++) { + k[i][j] = k_one; + cut[i][j] = cut_one; + gamma[i][j] = gamma_one; + + setflag[i][j] = 1; + count++; + } + } + + if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients"); +} + +/* ---------------------------------------------------------------------- + init specific to this pair style +------------------------------------------------------------------------- */ + +void PairRHEOSolid::init_style() +{ + if (comm->ghost_velocity == 0) + error->all(FLERR,"Pair rheo/solid requires ghost atoms store velocity"); + + if (!atom->rheo_status_flag) + error->all(FLERR,"Pair rheo/solid requires atom_style rheo"); + + neighbor->add_request(this); +} + + +/* ---------------------------------------------------------------------- + init for one type pair i,j and corresponding j,i +------------------------------------------------------------------------- */ + +double PairRHEOSolid::init_one(int i, int j) +{ + if (setflag[i][j] == 0) { + cut[i][j] = mix_distance(cut[i][i], cut[j][j]); + k[i][j] = mix_energy(k[i][i], k[j][j], cut[i][i], cut[j][j]); + gamma[i][j] = mix_energy(gamma[i][i], gamma[j][j], cut[i][i], cut[j][j]); + } + + cut[j][i] = cut[i][j]; + k[j][i] = k[i][j]; + gamma[j][i] = gamma[i][j]; + + return cut[i][j]; +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file +------------------------------------------------------------------------- */ + +void PairRHEOSolid::write_restart(FILE *fp) +{ + write_restart_settings(fp); + + int i, j; + for (i = 1; i <= atom->ntypes; i++) + for (j = i; j <= atom->ntypes; j++) { + fwrite(&setflag[i][j], sizeof(int), 1, fp); + if (setflag[i][j]) { + fwrite(&k[i][j], sizeof(double), 1, fp); + fwrite(&cut[i][j], sizeof(double), 1, fp); + fwrite(&gamma[i][j], sizeof(double), 1, fp); + } + } +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts +------------------------------------------------------------------------- */ + +void PairRHEOSolid::read_restart(FILE *fp) +{ + read_restart_settings(fp); + allocate(); + + int i, j; + int me = comm->me; + for (i = 1; i <= atom->ntypes; i++) + for (j = i; j <= atom->ntypes; j++) { + if (me == 0) utils::sfread(FLERR, &setflag[i][j], sizeof(int), 1, fp, nullptr, error); + MPI_Bcast(&setflag[i][j], 1, MPI_INT, 0, world); + if (setflag[i][j]) { + if (me == 0) { + utils::sfread(FLERR, &k[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &cut[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &gamma[i][j], sizeof(double), 1, fp, nullptr, error); + } + MPI_Bcast(&k[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&cut[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&gamma[i][j], 1, MPI_DOUBLE, 0, world); + } + } +} + +/* ---------------------------------------------------------------------- + proc 0 writes to data file +------------------------------------------------------------------------- */ + +void PairRHEOSolid::write_data(FILE *fp) +{ + for (int i = 1; i <= atom->ntypes; i++) + fprintf(fp, "%d %g %g %g\n", i, k[i][i], cut[i][i], gamma[i][i]); +} + +/* ---------------------------------------------------------------------- + proc 0 writes all pairs to data file +------------------------------------------------------------------------- */ + +void PairRHEOSolid::write_data_all(FILE *fp) +{ + for (int i = 1; i <= atom->ntypes; i++) + for (int j = i; j <= atom->ntypes; j++) + fprintf(fp, "%d %d %g %g %g\n", i, j, k[i][j], cut[i][j], gamma[i][j]); +} + +/* ---------------------------------------------------------------------- */ + +double PairRHEOSolid::single(int i, int j, int itype, int jtype, double rsq, double /*factor_coul*/, + double factor_lj, double &fforce) +{ + double fpair, r, rinv; + double delx, dely, delz, delvx, delvy, delvz, dot, smooth; + + if (rsq > cutsq[itype][jtype]) return 0.0; + + int *status = atom->rheo_status; + if (!(status[i] & STATUS_SOLID)) return 0.0; + if (!(status[j] & STATUS_SOLID)) return 0.0; + + double **x = atom->x; + double **v = atom->v; + + r = sqrt(rsq); + rinv = 1.0 / r; + + fpair = k[itype][jtype] * (cut[itype][jtype] - r); + + smooth = rsq / cutsq[itype][jtype]; + smooth *= smooth; + smooth = 1.0 - smooth; + delx = x[i][0] - x[j][0]; + dely = x[i][1] - x[j][1]; + delz = x[i][2] - x[j][2]; + delvx = v[i][0] - v[j][0]; + delvy = v[i][1] - v[j][1]; + delvz = v[i][2] - v[j][2]; + dot = delx * delvx + dely * delvy + delz * delvz; + fpair -= gamma[itype][jtype] * dot * rinv * smooth; + + fpair *= factor_lj; + fforce = fpair; + + return 0.0; +} diff --git a/src/RHEO/pair_rheo_solid.h b/src/RHEO/pair_rheo_solid.h new file mode 100644 index 0000000000..66c2ac4bf1 --- /dev/null +++ b/src/RHEO/pair_rheo_solid.h @@ -0,0 +1,51 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef PAIR_CLASS +// clang-format off +PairStyle(rheo/solid,PairRHEOSolid); +// clang-format on +#else + +#ifndef LMP_PAIR_RHEO_SOLID_H +#define LMP_PAIR_RHEO_SOLID_H + +#include "pair.h" + +namespace LAMMPS_NS { + +class PairRHEOSolid : public Pair { + public: + PairRHEOSolid(class LAMMPS *); + ~PairRHEOSolid() override; + void compute(int, int) override; + void settings(int, char **) override; + void coeff(int, char **) override; + void init_style() override; + double init_one(int, int) override; + void write_restart(FILE *) override; + void read_restart(FILE *) override; + void write_data(FILE *) override; + void write_data_all(FILE *) override; + double single(int, int, int, int, double, double, double, double &) override; + + protected: + double **k, **cut, **gamma; + + void allocate(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/atom.cpp b/src/atom.cpp index 799a256e31..9af945367b 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -198,6 +198,13 @@ Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp), atom_style(nullptr), avec(nullptr), a eff_plastic_strain_rate = nullptr; damage = nullptr; + // RHEO package + + rheo_status = nullptr; + conductivity = nullptr; + pressure = nullptr; + viscosity = nullptr; + // SPH package rho = drho = esph = desph = cv = nullptr; @@ -529,6 +536,13 @@ void Atom::peratom_create() add_peratom("cc",&cc,DOUBLE,1); add_peratom("cc_flux",&cc_flux,DOUBLE,1,1); // set per-thread flag + // RHEO package + + add_peratom("rheo_status",&rheo_status,INT,0); + add_peratom("conductivity",&conductivity,DOUBLE,0); + add_peratom("pressure",&pressure,DOUBLE,0); + add_peratom("viscosity",&viscosity,DOUBLE,0); + // SPH package add_peratom("rho",&rho,DOUBLE,0); @@ -634,6 +648,7 @@ void Atom::set_atomflag_defaults() temperature_flag = heatflow_flag = 0; vfrac_flag = spin_flag = eradius_flag = ervel_flag = erforce_flag = 0; cs_flag = csforce_flag = vforce_flag = ervelforce_flag = etag_flag = 0; + rheo_status_flag = conductivity_flag = pressure_flag = viscosity_flag = 0; rho_flag = esph_flag = cv_flag = vest_flag = 0; dpd_flag = edpd_flag = tdpd_flag = 0; sp_flag = 0; @@ -3048,7 +3063,15 @@ void *Atom::extract(const char *name) if (strcmp(name,"vforce") == 0) return (void *) vforce; if (strcmp(name,"etag") == 0) return (void *) etag; + // RHEO package + + if (strcmp(name,"rheo_status") == 0) return (void *) rheo_status; + if (strcmp(name,"conductivity") == 0) return (void *) conductivity; + if (strcmp(name,"pressure") == 0) return (void *) pressure; + if (strcmp(name,"viscosity") == 0) return (void *) viscosity; + // SPH package + if (strcmp(name,"rho") == 0) return (void *) rho; if (strcmp(name,"drho") == 0) return (void *) drho; if (strcmp(name,"esph") == 0) return (void *) esph; @@ -3169,6 +3192,15 @@ int Atom::extract_datatype(const char *name) if (strcmp(name,"vforce") == 0) return LAMMPS_DOUBLE_2D; if (strcmp(name,"etag") == 0) return LAMMPS_INT; + // RHEO package + + if (strcmp(name,"rheo_status") == 0) return LAMMPS_INT; + if (strcmp(name,"conductivity") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"pressure") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"viscosity") == 0) return LAMMPS_DOUBLE; + + // SPH package + if (strcmp(name,"rho") == 0) return LAMMPS_DOUBLE; if (strcmp(name,"drho") == 0) return LAMMPS_DOUBLE; if (strcmp(name,"esph") == 0) return LAMMPS_DOUBLE; diff --git a/src/atom.h b/src/atom.h index 195c1b2cf9..bd5b352cd0 100644 --- a/src/atom.h +++ b/src/atom.h @@ -155,6 +155,13 @@ class Atom : protected Pointers { double *eff_plastic_strain_rate; double *damage; + // RHEO package + + int *rheo_status; + double *conductivity; + double *pressure; + double *viscosity; + // SPH package double *rho, *drho, *esph, *desph, *cv; @@ -190,6 +197,7 @@ class Atom : protected Pointers { int temperature_flag, heatflow_flag; int vfrac_flag, spin_flag, eradius_flag, ervel_flag, erforce_flag; int cs_flag, csforce_flag, vforce_flag, ervelforce_flag, etag_flag; + int rheo_status_flag, conductivity_flag, pressure_flag, viscosity_flag; int rho_flag, esph_flag, cv_flag, vest_flag; int dpd_flag, edpd_flag, tdpd_flag; int mesont_flag; diff --git a/src/bond_hybrid.cpp b/src/bond_hybrid.cpp index 7df4f31455..307cbd72fd 100644 --- a/src/bond_hybrid.cpp +++ b/src/bond_hybrid.cpp @@ -34,6 +34,7 @@ BondHybrid::BondHybrid(LAMMPS *lmp) : Bond(lmp) nstyles = 0; has_quartic = -1; nbondlist = nullptr; + orig_map = nullptr; maxbond = nullptr; bondlist = nullptr; } @@ -81,6 +82,10 @@ void BondHybrid::compute(int eflag, int vflag) memory->destroy(bondlist[m]); maxbond[m] = nbondlist[m] + EXTRA; memory->create(bondlist[m], maxbond[m], 3, "bond_hybrid:bondlist"); + if (partial_flag) { + memory->destroy(orig_map[m]); + memory->create(orig_map[m], maxbond[m], "bond_hybrid:orig_map"); + } } nbondlist[m] = 0; } @@ -91,6 +96,8 @@ void BondHybrid::compute(int eflag, int vflag) bondlist[m][n][0] = bondlist_orig[i][0]; bondlist[m][n][1] = bondlist_orig[i][1]; bondlist[m][n][2] = bondlist_orig[i][2]; + if (partial_flag) + orig_map[m][n] = i; nbondlist[m]++; } } @@ -135,6 +142,21 @@ void BondHybrid::compute(int eflag, int vflag) } } + // If bond style can be deleted by setting type to zero (BPM or quartic), update bondlist_orig + // Otherwise, bond type could be restored back to its original value during reneighboring + // Use orig_map to propagate changes from temporary bondlist array back to original array + + if (partial_flag) { + for (m = 0; m < nstyles; m++) { + for (i = 0; i < nbondlist[m]; i++) { + if (bondlist[m][i][2] <= 0) { + n = orig_map[m][i]; + bondlist_orig[n][2] = bondlist[m][i][2]; + } + } + } + } + // restore ptrs to original bondlist neighbor->nbondlist = nbondlist_orig; @@ -154,9 +176,11 @@ void BondHybrid::allocate() nbondlist = new int[nstyles]; maxbond = new int[nstyles]; + orig_map = new int *[nstyles]; bondlist = new int **[nstyles]; for (int m = 0; m < nstyles; m++) maxbond[m] = 0; for (int m = 0; m < nstyles; m++) bondlist[m] = nullptr; + for (int m = 0; m < nstyles; m++) orig_map[m] = nullptr; } /* ---------------------------------------------------------------------- */ @@ -173,6 +197,8 @@ void BondHybrid::deallocate() delete[] maxbond; for (int i = 0; i < nstyles; i++) memory->destroy(bondlist[i]); delete[] bondlist; + for (int i = 0; i < nstyles; i++) memory->destroy(orig_map[i]); + delete[] orig_map; } /* ---------------------------------------------------------------------- @@ -260,8 +286,13 @@ void BondHybrid::flags() if (styles[m]) comm_forward = MAX(comm_forward, styles[m]->comm_forward); if (styles[m]) comm_reverse = MAX(comm_reverse, styles[m]->comm_reverse); if (styles[m]) comm_reverse_off = MAX(comm_reverse_off, styles[m]->comm_reverse_off); + if (styles[m]) partial_flag = MAX(partial_flag, styles[m]->partial_flag); } + for (m = 0; m < nstyles; m++) + if (styles[m]->partial_flag != partial_flag) + error->all(FLERR, "Cannot hybridize bond styles with different topology settings"); + init_svector(); } @@ -351,6 +382,7 @@ void BondHybrid::init_style() // to create an entry for it in the bond type to sub-style map if (has_quartic >= 0) map[0] = has_quartic; + else map[0] = -1; } /* ---------------------------------------------------------------------- diff --git a/src/bond_hybrid.h b/src/bond_hybrid.h index d2496b8297..ba520b81b4 100644 --- a/src/bond_hybrid.h +++ b/src/bond_hybrid.h @@ -50,6 +50,7 @@ class BondHybrid : public Bond { int *nbondlist; // # of bonds in sub-style bondlists int *maxbond; // max # of bonds sub-style lists can store int ***bondlist; // bondlist for each sub-style + int **orig_map; // location of substyle bond in original bondlist virtual void allocate(); virtual void deallocate(); diff --git a/src/fix_bond_history.cpp b/src/fix_bond_history.cpp index 2d344e24fc..00ef0449f8 100644 --- a/src/fix_bond_history.cpp +++ b/src/fix_bond_history.cpp @@ -33,7 +33,7 @@ static constexpr int DELTA = 8192; /* ---------------------------------------------------------------------- */ FixBondHistory::FixBondHistory(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg), bondstore(nullptr), id_fix(nullptr), id_array(nullptr) + Fix(lmp, narg, arg), bondstore(nullptr), bondtype_orig(nullptr), bondstore_comp(nullptr), bondstore_orig(nullptr), id_fix(nullptr), id_array(nullptr) { if (narg != 5) error->all(FLERR, "Illegal fix bond/history command"); @@ -53,7 +53,6 @@ FixBondHistory::FixBondHistory(LAMMPS *lmp, int narg, char **arg) : updated_bond_flag = 0; maxbond = 0; - allocate(); } /* ---------------------------------------------------------------------- */ @@ -65,6 +64,8 @@ FixBondHistory::~FixBondHistory() delete[] id_array; memory->destroy(bondstore); + memory->destroy(bondstore_comp); + memory->destroy(bondtype_orig); } /* ---------------------------------------------------------------------- */ @@ -97,7 +98,7 @@ void FixBondHistory::post_constructor() void FixBondHistory::update_atom_value(int i, int m, int idata, double value) { - if (idata >= ndata || m > nbond) error->all(FLERR, "Index exceeded in fix bond history"); + if (idata >= ndata || m > nbond) error->one(FLERR, "Index exceeded in fix bond history"); atom->darray[index][i][m * ndata + idata] = value; } @@ -105,7 +106,7 @@ void FixBondHistory::update_atom_value(int i, int m, int idata, double value) double FixBondHistory::get_atom_value(int i, int m, int idata) { - if (idata >= ndata || m > nbond) error->all(FLERR, "Index exceeded in fix bond history"); + if (idata >= ndata || m > nbond) error->one(FLERR, "Index exceeded in fix bond history"); return atom->darray[index][i][m * ndata + idata]; } @@ -135,6 +136,7 @@ void FixBondHistory::pre_exchange() int nlocal = atom->nlocal; tagint **bond_atom = atom->bond_atom; + int **bond_type = atom->bond_type; int *num_bond = atom->num_bond; tagint *tag = atom->tag; @@ -142,12 +144,12 @@ void FixBondHistory::pre_exchange() i1 = bondlist[n][0]; i2 = bondlist[n][1]; - // skip bond if already broken - if (bondlist[n][2] <= 0) { continue; } + // skip bond if already broken or not allocated + if (bondlist[n][2] <= 0 || !setflag[bondlist[n][2]]) { continue; } if (i1 < nlocal) { for (m = 0; m < num_bond[i1]; m++) { - if (bond_atom[i1][m] == tag[i2]) { + if (bond_atom[i1][m] == tag[i2] && setflag[bond_type[i1][m]]) { for (idata = 0; idata < ndata; idata++) { stored[i1][m * ndata + idata] = bondstore[n][idata]; } @@ -157,7 +159,7 @@ void FixBondHistory::pre_exchange() if (i2 < nlocal) { for (m = 0; m < num_bond[i2]; m++) { - if (bond_atom[i2][m] == tag[i1]) { + if (bond_atom[i2][m] == tag[i1] && setflag[bond_type[i2][m]]) { for (idata = 0; idata < ndata; idata++) { stored[i2][m * ndata + idata] = bondstore[n][idata]; } @@ -179,17 +181,21 @@ void FixBondHistory::allocate() else maxbond = static_cast(LB_FACTOR * atom->nbonds / comm->nprocs); memory->create(bondstore, maxbond, ndata, "fix_bond_store:bondstore"); + if (hybrid_flag) { + memory->create(bondstore_comp, maxbond, ndata, "fix_bond_store:bondstore_comp"); + memory->create(bondtype_orig, maxbond, "fix_bond_store:bondtype_orig"); + } } /* ---------------------------------------------------------------------- */ void FixBondHistory::setup_post_neighbor() { - //Grow array if number of bonds has increased - while (neighbor->nbondlist >= maxbond) { - maxbond += DELTA; - memory->grow(bondstore, maxbond, ndata, "fix_bond_store:bondstore"); - } + hybrid_flag = 0; + for (int i = 1; i <= atom->nbondtypes; i++) + if (!setflag[i]) hybrid_flag = 1; + + if (maxbond == 0) allocate(); pre_exchange(); post_neighbor(); @@ -206,6 +212,10 @@ void FixBondHistory::post_neighbor() while (neighbor->nbondlist >= maxbond) { maxbond += DELTA; memory->grow(bondstore, maxbond, ndata, "fix_bond_store:bondstore"); + if (hybrid_flag) { + memory->grow(bondstore_comp, maxbond, ndata, "fix_bond_store:bondstore_comp"); + memory->grow(bondtype_orig, maxbond, "fix_bond_store:bondtype_orig"); + } } int i1, i2, n, m, idata; @@ -215,6 +225,7 @@ void FixBondHistory::post_neighbor() int nlocal = atom->nlocal; tagint **bond_atom = atom->bond_atom; + int **bond_type = atom->bond_type; int *num_bond = atom->num_bond; tagint *tag = atom->tag; @@ -222,12 +233,12 @@ void FixBondHistory::post_neighbor() i1 = bondlist[n][0]; i2 = bondlist[n][1]; - // skip bond if already broken - if (bondlist[n][2] <= 0) { continue; } + // skip bond if already broken or not allocated + if (bondlist[n][2] <= 0 || !setflag[bondlist[n][2]]) { continue; } if (i1 < nlocal) { for (m = 0; m < num_bond[i1]; m++) { - if (bond_atom[i1][m] == tag[i2]) { + if (bond_atom[i1][m] == tag[i2] && setflag[bond_type[i1][m]]) { for (idata = 0; idata < ndata; idata++) { bondstore[n][idata] = stored[i1][m * ndata + idata]; } @@ -237,7 +248,7 @@ void FixBondHistory::post_neighbor() if (i2 < nlocal) { for (m = 0; m < num_bond[i2]; m++) { - if (bond_atom[i2][m] == tag[i1]) { + if (bond_atom[i2][m] == tag[i1] && setflag[bond_type[i2][m]]) { for (idata = 0; idata < ndata; idata++) { bondstore[n][idata] = stored[i2][m * ndata + idata]; } @@ -246,6 +257,12 @@ void FixBondHistory::post_neighbor() } } + if (hybrid_flag) { + nbondlist_orig = nbondlist; + for (n = 0; n < nbondlist; n++) + bondtype_orig[n] = bondlist[n][2]; + } + updated_bond_flag = 1; } @@ -294,6 +311,57 @@ void FixBondHistory::set_arrays(int i) for (int idata = 0; idata < ndata; idata++) stored[i][m * ndata + idata] = 0.0; } +/* ---------------------------------------------------------------------- + Compress history arrays, cutting out unused types, for bond hybrid +------------------------------------------------------------------------- */ + +void FixBondHistory::compress_history() +{ + // if this is a re-neighbor step or updating, compress bondstore + + int type; + int ncomp = 0; + if (update_flag || (neighbor->ago == 0)) { + for (int n = 0; n < nbondlist_orig; n++) { + type = bondtype_orig[n]; + + if (type <= 0) continue; + if (!setflag[type]) continue; + + for (int m = 0; m < ndata; m++) + bondstore_comp[ncomp][m] = bondstore[n][m]; + ncomp += 1; + } + } + + // replace ptr to original array + bondstore_orig = bondstore; + bondstore = bondstore_comp; +} + +/* ---------------------------------------------------------------------- */ + +void FixBondHistory::uncompress_history() +{ + if (update_flag) { + int type; + int ncomp = 0; + for (int n = 0; n < nbondlist_orig; n++) { + type = bondtype_orig[n]; + + if (type <= 0) continue; + if (!setflag[type]) continue; + + for (int m = 0; m < ndata; m++) + bondstore_orig[n][m] = bondstore[ncomp][m]; + ncomp += 1; + } + } + + // restore ptr to original array + bondstore = bondstore_orig; +} + /* ---------------------------------------------------------------------- Delete bond by zeroing data ------------------------------------------------------------------------- */ diff --git a/src/fix_bond_history.h b/src/fix_bond_history.h index e19deee82f..377685ea84 100644 --- a/src/fix_bond_history.h +++ b/src/fix_bond_history.h @@ -53,20 +53,32 @@ class FixBondHistory : public Fix { void check_cache(int, int); void clear_cache(); + // methods for bond style hybrid + void compress_history(); + void uncompress_history(); + // if data is temporarily stored while the bond_atom array // is being reordered, use map of vectors with pairs for keys // to enable quick look up std::map, std::vector> cached_histories; + int *setflag; // Set by BondBPM, which bond types are used double **bondstore; int stored_flag; + int ndata; protected: void allocate(); - int update_flag; //Flag whether history values can evolve + int hybrid_flag; + int nbondlist_orig; + int *bondtype_orig; + double **bondstore_comp; + double **bondstore_orig; + + int update_flag; // Flag whether history values can evolve int updated_bond_flag; - int nbond, maxbond, ndata; + int nbond, maxbond; int index; char *id_fix; char *id_array; diff --git a/src/set.cpp b/src/set.cpp index 73e218db0f..93d5068ef3 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -49,7 +49,7 @@ enum{TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET, DIPOLE,DIPOLE_RANDOM,SPIN_ATOM,SPIN_RANDOM,SPIN_ELECTRON,RADIUS_ELECTRON, QUAT,QUAT_RANDOM,THETA,THETA_RANDOM,ANGMOM,OMEGA,TEMPERATURE, DIAMETER,RADIUS_ATOM,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER, - SPH_E,SPH_CV,SPH_RHO,EDPD_TEMP,EDPD_CV,CC,SMD_MASS_DENSITY, + RHEO_STATUS,SPH_E,SPH_CV,SPH_RHO,EDPD_TEMP,EDPD_CV,CC,SMD_MASS_DENSITY, SMD_CONTACT_RADIUS,DPDTHETA,EPSILON,IVEC,DVEC,IARRAY,DARRAY}; /* ---------------------------------------------------------------------- */ @@ -513,6 +513,24 @@ void Set::command(int narg, char **arg) topology(IMPROPER); iarg += 2; + } else if (strcmp(arg[iarg],"rheo/rho") == 0) { + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set rheo/rho", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rho_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + set(SPH_RHO); + iarg += 2; + + } else if (strcmp(arg[iarg],"rheo/status") == 0) { + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set rheo/status", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rheo_status_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + set(RHEO_STATUS); + iarg += 2; + } else if (strcmp(arg[iarg],"sph/e") == 0) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); @@ -879,6 +897,13 @@ void Set::set(int keyword) if (dvalue <= 0.0) error->one(FLERR,"Invalid volume in set command"); atom->vfrac[i] = dvalue; } + + else if (keyword == RHEO_STATUS) { + if (ivalue != 0 && ivalue != 1) + error->one(FLERR,"Invalid value {} in set command for rheo/status", ivalue); + atom->rheo_status[i] = ivalue; + } + else if (keyword == SPH_E) atom->esph[i] = dvalue; else if (keyword == SPH_CV) atom->cv[i] = dvalue; else if (keyword == SPH_RHO) atom->rho[i] = dvalue;